From efaae45870421e43f2dcb66e88b4bead46f71ea9 Mon Sep 17 00:00:00 2001 From: kushal khare Date: Sat, 28 Nov 2020 19:31:47 +0530 Subject: [PATCH 1/3] adding classes to block.js --- js/block.js | 6513 +++++++++++++++++++++++++-------------------------- 1 file changed, 3237 insertions(+), 3276 deletions(-) diff --git a/js/block.js b/js/block.js index c6cae2e96a..9580be6b60 100644 --- a/js/block.js +++ b/js/block.js @@ -94,1496 +94,1508 @@ const PIEMENUS = [ ]; // Define block instance objects and any methods that are intra-block. -function Block(protoblock, blocks, overrideName) { - if (protoblock === null) { - console.debug("null protoblock sent to Block"); - return; - } +class Block { + constructor(protoblock, blocks, overrideName) { + if (protoblock === null) { + console.debug("null protoblock sent to Block"); + return; + } - this.protoblock = protoblock; - this.name = protoblock.name; - this.overrideName = overrideName; - this.blocks = blocks; - this.collapsed = false; // Is this collapsible block collapsed? - this.inCollapsed = false; // Is this block in a collapsed stack? - this.trash = false; // Is this block in the trash? - this.loadComplete = false; // Has the block finished loading? - this.label = null; // Editable textview in DOM. - this.labelattr = null; // Editable textview in DOM. - this.text = null; // A dynamically generated text label on block itself. - this.value = null; // Value for number, text, and media blocks. - this.privateData = null; // A block may have some private data, - // e.g., nameboxes use this field to store - // the box name associated with the block. - this.image = protoblock.image; // The file path of the image. - this.imageBitmap = null; - this.controller = null; // Note blocks get a controller - - // All blocks have at a container and least one bitmap. - this.container = null; - this.bounds = null; - this.width = 0; - this.height = 0; - this.hitHeight = 0; - this.bitmap = null; - this.highlightBitmap = null; - this.disconnectedBitmap = null; - this.disconnectedHighlightBitmap = null; - - // The svg from which the bitmaps are generated - this.artwork = null; - this.collapseArtwork = null; - - // Start and Action blocks has a collapse button - this.collapseButtonBitmap = null; - this.expandButtonBitmap = null; - this.collapseBlockBitmap = null; - this.highlightCollapseBlockBitmap = null; - this.collapseText = null; - - this.size = 1; // Proto size is copied here. - this.docks = []; // Proto dock is copied here. - this.connections = []; - - // Keep track of clamp count for blocks with clamps. - this.clampCount = [1, 1]; - this.argClampSlots = [1]; - - // Some blocks have some post process after they are first loaded. - this.postProcess = null; - this.postProcessArg = this; - - // Lock on label change - this._labelLock = false; - this._piemenuExitTime = null; - this._triggerLongPress = false; - - // Don't trigger notes on top of each other. - this._triggerLock = false; - - // If we update the parameters of a meter block, we have extra - // actions to attend to. - this._check_meter_block = null; - - // Mouse position in events - this.original = {x: 0, y: 0}; - this.offset = {x: 0, y: 0}; - - // Internal function for creating cache. - // Includes workaround for a race condition. - this._createCache = function(callback, args) { - let that = this; - return new Promise(function(resolve, reject) { - let loopCount = 0; - - async function checkBounds(counter) { - try { - if (counter !== undefined) { - loopCount = counter; - } - if (loopCount > 3) { - throw new Error("COULD NOT CREATE CACHE"); - } - - that.bounds = that.container.getBounds(); - - if (that.bounds === null) { - await delayExecution(100); - that.regenerateArtwork(true, []); - checkBounds(loopCount + 1); - } else { - that.container.cache( - that.bounds.x, that.bounds.y, - that.bounds.width, that.bounds.height); - callback(that, args); - resolve(); - } - } catch (e) { - reject(e); - } - } - checkBounds(); - }); - }; + this.protoblock = protoblock; + this.name = protoblock.name; + this.overrideName = overrideName; + this.blocks = blocks; + this.collapsed = false; // Is this collapsible block collapsed? + this.inCollapsed = false; // Is this block in a collapsed stack? + this.trash = false; // Is this block in the trash? + this.loadComplete = false; // Has the block finished loading? + this.label = null; // Editable textview in DOM. + this.labelattr = null; // Editable textview in DOM. + this.text = null; // A dynamically generated text label on block itself. + this.value = null; // Value for number, text, and media blocks. + this.privateData = null; // A block may have some private data, + + + // e.g., nameboxes use this field to store + // the box name associated with the block. + this.image = protoblock.image; // The file path of the image. + this.imageBitmap = null; + this.controller = null; // Note blocks get a controller + + + // All blocks have at a container and least one bitmap. + this.container = null; + this.bounds = null; + this.width = 0; + this.height = 0; + this.hitHeight = 0; + this.bitmap = null; + this.highlightBitmap = null; + this.disconnectedBitmap = null; + this.disconnectedHighlightBitmap = null; + + // The svg from which the bitmaps are generated + this.artwork = null; + this.collapseArtwork = null; + + // Start and Action blocks has a collapse button + this.collapseButtonBitmap = null; + this.expandButtonBitmap = null; + this.collapseBlockBitmap = null; + this.highlightCollapseBlockBitmap = null; + this.collapseText = null; + + this.size = 1; // Proto size is copied here. + this.docks = []; // Proto dock is copied here. + this.connections = []; + + // Keep track of clamp count for blocks with clamps. + this.clampCount = [1, 1]; + this.argClampSlots = [1]; + + // Some blocks have some post process after they are first loaded. + this.postProcess = null; + this.postProcessArg = this; - // Internal function for updating the cache. - // Includes workaround for a race condition. - this.updateCache = function(counter) { - let that = this; - return new Promise(function(resolve, reject) { - let loopCount = 0; + // Lock on label change + this._labelLock = false; + this._piemenuExitTime = null; + this._triggerLongPress = false; - async function updateBounds(counter) { - try { - if (counter !== undefined) { - loopCount = counter; - } + // Don't trigger notes on top of each other. + this._triggerLock = false; - if (loopCount > 3) { - throw new Error("COULD NOT UPDATE CACHE"); - } + // If we update the parameters of a meter block, we have extra + // actions to attend to. + this._check_meter_block = null; - if (that.bounds == null) { - updateBounds(loopCount + 1); - await that.pause(200); - } else { - that.container.updateCache(); - that.blocks.refreshCanvas(); - resolve(); + // Mouse position in events + this.original = { x: 0, y: 0 }; + this.offset = { x: 0, y: 0 }; + + // Internal function for creating cache. + // Includes workaround for a race condition. + this._createCache = function (callback, args) { + let that = this; + return new Promise(function (resolve, reject) { + let loopCount = 0; + + async function checkBounds(counter) { + try { + if (counter !== undefined) { + loopCount = counter; + } + if (loopCount > 3) { + throw new Error("COULD NOT CREATE CACHE"); + } + + that.bounds = that.container.getBounds(); + + if (that.bounds === null) { + await delayExecution(100); + that.regenerateArtwork(true, []); + checkBounds(loopCount + 1); + } else { + that.container.cache( + that.bounds.x, that.bounds.y, + that.bounds.width, that.bounds.height); + callback(that, args); + resolve(); + } + } catch (e) { + reject(e); } - } catch (e) { - reject(e); } - } - updateBounds(); - }); - }; - - this.ignore = function() { - if (this.bitmap === null) { - return true; - } + checkBounds(); + }); + }; - if (this.name === "hidden") { - return true; - } + // Internal function for updating the cache. + // Includes workaround for a race condition. + this.updateCache = function (counter) { + let that = this; + return new Promise(function (resolve, reject) { + let loopCount = 0; + + async function updateBounds(counter) { + try { + if (counter !== undefined) { + loopCount = counter; + } - if (this.name === "hiddennoflow") { - return true; - } + if (loopCount > 3) { + throw new Error("COULD NOT UPDATE CACHE"); + } - if (this.trash) { - return true; - } + if (that.bounds == null) { + updateBounds(loopCount + 1); + await that.pause(200); + } else { + that.container.updateCache(); + that.blocks.refreshCanvas(); + resolve(); + } + } catch (e) { + reject(e); + } + } + updateBounds(); + }); + }; - if (this.inCollapsed) { - return true; - } + this.ignore = function () { + if (this.bitmap === null) { + return true; + } - if (this.disconnectedBitmap !== null && - this.disconnectedHighlightBitmap !== null) { - if (!this.bitmap.visible && - !this.highlightBitmap.visible && - !this.disconnectedBitmap.visible && - !this.disconnectedHighlightBitmap.visible) { - if (this.collapseBlockBitmap === null) { - return true; - } else if (!this.collapseBlockBitmap.visible && - !this.highlightCollapseBlockBitmap.visible) { - return true; - } + if (this.name === "hidden") { + return true; } - } else { - if (!this.bitmap.visible && !this.highlightBitmap.visible) { - if (this.collapseBlockBitmap === null) { - return true; - } else if (!this.collapseBlockBitmap.visible && - !this.highlightCollapseBlockBitmap.visible) { - return true; - } + + if (this.name === "hiddennoflow") { + return true; } - } - return false; - }; + if (this.trash) { + return true; + } - this.offScreen = function(boundary) { - return (!this.trash && boundary.offScreen( - this.container.x, this.container.y)); - }; + if (this.inCollapsed) { + return true; + } - this.copySize = function() { - this.size = this.protoblock.size; - }; + if (this.disconnectedBitmap !== null && + this.disconnectedHighlightBitmap !== null) { + if (!this.bitmap.visible && + !this.highlightBitmap.visible && + !this.disconnectedBitmap.visible && + !this.disconnectedHighlightBitmap.visible) { + if (this.collapseBlockBitmap === null) { + return true; + } else if (!this.collapseBlockBitmap.visible && + !this.highlightCollapseBlockBitmap.visible) { + return true; + } + } + } else { + if (!this.bitmap.visible && !this.highlightBitmap.visible) { + if (this.collapseBlockBitmap === null) { + return true; + } else if (!this.collapseBlockBitmap.visible && + !this.highlightCollapseBlockBitmap.visible) { + return true; + } + } + } - this.getInfo = function() { - return this.name + " block"; - }; + return false; + }; - this.isCollapsible = function() { - return COLLAPSIBLES.indexOf(this.name) !== -1; - }; + this.offScreen = function (boundary) { + return (!this.trash && boundary.offScreen( + this.container.x, this.container.y)); + }; - this.isInlineCollapsible = function() { - return INLINECOLLAPSIBLES.indexOf(this.name) !== -1; - }; + this.copySize = function () { + this.size = this.protoblock.size; + }; - /* - * Show the highlight artwork - * @return{void} - * @public - */ - this.highlight = function() { - if (this.trash) { - return; - } + this.getInfo = function () { + return this.name + " block"; + }; - if (this.inCollapsed) { - // In collapsed, so do nothing. - return; - } + this.isCollapsible = function () { + return COLLAPSIBLES.indexOf(this.name) !== -1; + }; - if (!this.container.visible) { - // block is hidden, so do nothing. - return; - } + this.isInlineCollapsible = function () { + return INLINECOLLAPSIBLES.indexOf(this.name) !== -1; + }; - if (this.disconnectedBitmap !== null) { - if (!this.bitmap.visible && !this.disconnectedBitmap.visible) { - // block is hidden, so do nothing. + /* + * Show the highlight artwork + * @return{void} + * @public + */ + this.highlight = function () { + if (this.trash) { return; } - } else if (!this.bitmap.visible) { - return; - } - - // Always hide the non-highlighted artwork. - this.container.visible = true; - this.bitmap.visible = false; - if (this.disconnectedBitmap !== null) { - this.disconnectedBitmap.visible = false; - } - // If it is a collapsed collapsable, hightlight the collapsed state. - if (this.collapsed) { - // Show the highlighted collapsed artwork. - if (this.highlightCollapseBlockBitmap !== null) { - this.highlightCollapseBlockBitmap.visible = true; + if (this.inCollapsed) { + // In collapsed, so do nothing. + return; } - if (this.collapseText !== null) { - this.collapseText.visible = true; + if (!this.container.visible) { + // block is hidden, so do nothing. + return; } - // and hide the unhighlighted collapsed artwork... - if (this.collapseBlockBitmap !== null) { - this.collapseBlockBitmap.visible = false; + if (this.disconnectedBitmap !== null) { + if (!this.bitmap.visible && !this.disconnectedBitmap.visible) { + // block is hidden, so do nothing. + return; + } + } else if (!this.bitmap.visible) { + return; } - // but not the uncollapsed highlighted artwork. - this.highlightBitmap.visible = false; - if (this.disconnectedHighlightBitmap !== null) { - this.disconnectedHighlightBitmap.visible = false; + // Always hide the non-highlighted artwork. + this.container.visible = true; + this.bitmap.visible = false; + if (this.disconnectedBitmap !== null) { + this.disconnectedBitmap.visible = false; } - this.highlightBitmap.visible = false; - } else { - // Show the highlighted artwork. - // If the block is disconnected, use the disconnected bitmap. - if (this.isDisconnected()) { - this.disconnectedHighlightBitmap.visible = true; - this.highlightBitmap.visible = false; - } else { - if (this.disconnectedHighlightBitmap !== null) { - this.disconnectedHighlightBitmap.visible = false; + // If it is a collapsed collapsable, hightlight the collapsed state. + if (this.collapsed) { + // Show the highlighted collapsed artwork. + if (this.highlightCollapseBlockBitmap !== null) { + this.highlightCollapseBlockBitmap.visible = true; } - this.highlightBitmap.visible = true; - } - - // If it is an uncollapsed collapsable, make sure the - // collapsed artwork is hidden. - if (this.isCollapsible()) { - // There could be a race condition when making a - // new action block. if (this.collapseText !== null) { - this.collapseText.visible = false; + this.collapseText.visible = true; } + // and hide the unhighlighted collapsed artwork... if (this.collapseBlockBitmap !== null) { this.collapseBlockBitmap.visible = false; } - if (this.highlightCollapseBlockBitmap !== null) { - this.highlightCollapseBlockBitmap.visible = false; + // but not the uncollapsed highlighted artwork. + this.highlightBitmap.visible = false; + if (this.disconnectedHighlightBitmap !== null) { + this.disconnectedHighlightBitmap.visible = false; } - } - } - this.container.updateCache(); - }; + this.highlightBitmap.visible = false; + } else { + // Show the highlighted artwork. + // If the block is disconnected, use the disconnected bitmap. + if (this.isDisconnected()) { + this.disconnectedHighlightBitmap.visible = true; + this.highlightBitmap.visible = false; + } else { + if (this.disconnectedHighlightBitmap !== null) { + this.disconnectedHighlightBitmap.visible = false; + } - /* - * Remove highlight from block - * @return{void} - * @public - */ - this.unhighlight = function() { - if (this.trash) { - return; - } + this.highlightBitmap.visible = true; + } - if (this.inCollapsed) { - // In collapsed, so do nothing. - return; - } + // If it is an uncollapsed collapsable, make sure the + // collapsed artwork is hidden. + if (this.isCollapsible()) { + // There could be a race condition when making a + // new action block. + if (this.collapseText !== null) { + this.collapseText.visible = false; + } - if (this.bitmap === null) { - console.debug("bitmap not ready"); - return; - } + if (this.collapseBlockBitmap !== null) { + this.collapseBlockBitmap.visible = false; + } - // Always hide the highlighted artwork. - this.highlightBitmap.visible = false; - if (this.disconnectedHighlightBitmap !== null) { - this.disconnectedHighlightBitmap.visible = false; - } + if (this.highlightCollapseBlockBitmap !== null) { + this.highlightCollapseBlockBitmap.visible = false; + } + } + } - this.container.visible = true; + this.container.updateCache(); + }; - // If it is a collapsed collapsable, unhightlight the collapsed state. - if (this.collapsed) { - // Show the unhighlighted collapsed artwork.' - // We may have a race condition... - if (this.collapseBlockBitmap !== null) { - this.collapseBlockBitmap.visible = true; + /* + * Remove highlight from block + * @return{void} + * @public + */ + this.unhighlight = function () { + if (this.trash) { + return; } - if (this.collapseText !== null) { - this.collapseText.visible = true; + if (this.inCollapsed) { + // In collapsed, so do nothing. + return; } - // but not the highlighted collapsed artwork... - if (this.highlightCollapseBlockBitmap !== null) { - this.highlightCollapseBlockBitmap.visible = false; + if (this.bitmap === null) { + console.debug("bitmap not ready"); + return; } - // and not the uncollapsed artwork. - this.bitmap.visible = false; - } else { - // If the block is disconnected, use the disconnected bitmap. - if (this.isDisconnected()) { - this.disconnectedBitmap.visible = true; - this.bitmap.visible = false; - } else { - if (this.disconnectedBitmap !== null) { - this.disconnectedBitmap.visible = false; - } - - this.bitmap.visible = true; + // Always hide the highlighted artwork. + this.highlightBitmap.visible = false; + if (this.disconnectedHighlightBitmap !== null) { + this.disconnectedHighlightBitmap.visible = false; } this.container.visible = true; - if (this.isCollapsible()) { - // There could be a race condition when making a - // new action block. - if (this.collapseText !== null) { - this.collapseText.visible = false; + // If it is a collapsed collapsable, unhightlight the collapsed state. + if (this.collapsed) { + // Show the unhighlighted collapsed artwork.' + // We may have a race condition... + if (this.collapseBlockBitmap !== null) { + this.collapseBlockBitmap.visible = true; } - if (this.collapseBlockBitmap !== null) { - this.collapseBlockBitmap.visible = false; + if (this.collapseText !== null) { + this.collapseText.visible = true; } + // but not the highlighted collapsed artwork... if (this.highlightCollapseBlockBitmap !== null) { this.highlightCollapseBlockBitmap.visible = false; } - } - } - this.container.updateCache(); - }; + // and not the uncollapsed artwork. + this.bitmap.visible = false; + } else { + // If the block is disconnected, use the disconnected bitmap. + if (this.isDisconnected()) { + this.disconnectedBitmap.visible = true; + this.bitmap.visible = false; + } else { + if (this.disconnectedBitmap !== null) { + this.disconnectedBitmap.visible = false; + } - /* - * Resize and update number of slots in argClamp - * @param-slotList how many slots to use - * @return{void} - * @public - */ - this.updateArgSlots = function(slotList) { - this.argClampSlots = slotList; - this._newArtwork(0); - this.regenerateArtwork(false); - }; + this.bitmap.visible = true; + } - /* - * Resize an expandable block. - * @param-clamp which clamp to update (ifthenelse has 2 clamps) - * @param-plusMinus how many slots to add or subtract - * @return{void} - * @public - */ - this.updateSlots = function(clamp, plusMinus) { - this.clampCount[clamp] += plusMinus; - this._newArtwork(plusMinus); - this.regenerateArtwork(false); - }; + this.container.visible = true; - /* - * If the block scale changes, we need to regenerate the - * artwork and recalculate the hitarea. - * @param-scale new block scale - * @return{void} - * @public - */ - this.resize = function(scale) { - let that = this; + if (this.isCollapsible()) { + // There could be a race condition when making a + // new action block. + if (this.collapseText !== null) { + this.collapseText.visible = false; + } - /* - * After the new artwork is created, this function is used to add - * decorations. - * @param-that = this - * @return{void} - * @public - */ - this.postProcess = function(that) { - if (that.imageBitmap !== null) { - that._positionMedia(that.imageBitmap, - that.imageBitmap.image.width, - that.imageBitmap.image.height, scale); - z = that.container.children.length - 1; - that.container.setChildIndex(that.imageBitmap, z); - } - - if (that.name === "start" || that.name === "drum") { - // Rescale the decoration on the start blocks. - for (let t = 0; t < that.blocks.turtles.turtleList.length; t++) { - if (that.blocks.turtles.turtleList[t].startBlock === that) { - that.blocks.turtles.turtleList[t].resizeDecoration( - scale, that.bitmap.image.width); - that._ensureDecorationOnTop(); - break; + if (this.collapseBlockBitmap !== null) { + this.collapseBlockBitmap.visible = false; + } + + if (this.highlightCollapseBlockBitmap !== null) { + this.highlightCollapseBlockBitmap.visible = false; } } - } else if (that.isCollapsible()) { - that._ensureDecorationOnTop(); } - that.updateCache(); - that._calculateBlockHitArea(); - - // If it is in the trash, make sure it remains hidden. - if (that.trash) { - that.hide(); - } + this.container.updateCache(); }; - this.postProcessArg = this; - - this.protoblock.scale = scale; - this._newArtwork(0); - this.regenerateArtwork(true, []); + /* + * Resize and update number of slots in argClamp + * @param-slotList how many slots to use + * @return{void} + * @public + */ + this.updateArgSlots = function (slotList) { + this.argClampSlots = slotList; + this._newArtwork(0); + this.regenerateArtwork(false); + }; - if (this.text !== null) { - this._positionText(scale); - } + /* + * Resize an expandable block. + * @param-clamp which clamp to update (ifthenelse has 2 clamps) + * @param-plusMinus how many slots to add or subtract + * @return{void} + * @public + */ + this.updateSlots = function (clamp, plusMinus) { + this.clampCount[clamp] += plusMinus; + this._newArtwork(plusMinus); + this.regenerateArtwork(false); + }; - if (this.container !== null) { - that = this; + /* + * If the block scale changes, we need to regenerate the + * artwork and recalculate the hitarea. + * @param-scale new block scale + * @return{void} + * @public + */ + this.resize = function (scale) { + let that = this; /* - * After new buttons are creates, they are cached and a - * new hit are is calculated - * @param-that = this = container + * After the new artwork is created, this function is used to add + * decorations. + * @param-that = this * @return{void} - * @private + * @public */ - let _postProcess = function(that) { - that.collapseButtonBitmap.scaleX = - that.collapseButtonBitmap.scaleY = - that.collapseButtonBitmap.scale = scale / 3; - that.expandButtonBitmap.scaleX = - that.expandButtonBitmap.scaleY = - that.expandButtonBitmap.scale = scale / 3; + this.postProcess = function (that) { + if (that.imageBitmap !== null) { + that._positionMedia(that.imageBitmap, + that.imageBitmap.image.width, + that.imageBitmap.image.height, scale); + let z = that.container.children.length - 1; + that.container.setChildIndex(that.imageBitmap, z); + } + + if (that.name === "start" || that.name === "drum") { + // Rescale the decoration on the start blocks. + for (let t = 0; t < that.blocks.turtles.turtleList.length; t++) { + if (that.blocks.turtles.turtleList[t].startBlock === that) { + that.blocks.turtles.turtleList[t].resizeDecoration( + scale, that.bitmap.image.width); + that._ensureDecorationOnTop(); + break; + } + } + } else if (that.isCollapsible()) { + that._ensureDecorationOnTop(); + } + that.updateCache(); that._calculateBlockHitArea(); - }; - - if (this.isCollapsible()) { - this._generateCollapseArtwork(_postProcess); - let fontSize = 10 * scale; - this.collapseText.font = fontSize + "px Sans"; - this._positionCollapseLabel(scale); - } - } - }; - /* - * Create new artwork for a block - * @param-plusMinus specifies how much a clamp block expands or contracts - * @return{void} - * @private - */ - this._newArtwork = function(plusMinus) { - let proto, obj; - if (this.isInlineCollapsible()) { - proto = new ProtoBlock("collapse-note"); - proto.scale = this.protoblock.scale; - if (this.name === "interval") { - proto.extraWidth = 80; - } else { - proto.extraWidth = 40; - } - proto.zeroArgBlock(); - obj = proto.generator(); - this.collapseArtwork = obj[0]; - obj = this.protoblock.generator(this.clampCount[0]); - } else if (this.isCollapsible()) { - proto = new ProtoBlock("collapse"); - proto.scale = this.protoblock.scale; - proto.extraWidth = 40; - proto.basicBlockCollapsed(); - obj = proto.generator(); - this.collapseArtwork = obj[0]; - obj = this.protoblock.generator(this.clampCount[0]); - } else if (this.name === "ifthenelse") { - obj = this.protoblock.generator(this.clampCount[0], - this.clampCount[1]); - } else if (this.protoblock.style === "clamp") { - obj = this.protoblock.generator(this.clampCount[0]); - } else if (this.protoblock.style === "argflowclamp") { - obj = this.protoblock.generator(this.clampCount[0]); - } else { - switch (this.name) { - case "equal": - case "greater": - case "less": - obj = this.protoblock.generator(this.clampCount[0]); - break; - case "makeblock": - case "calcArg": - case "doArg": - case "namedcalcArg": - case "nameddoArg": - obj = this.protoblock.generator(this.argClampSlots); - this.size = 2; - for (let i = 0; i < this.argClampSlots.length; i++) { - this.size += this.argClampSlots[i]; - } - this.docks = []; - this.docks.push([obj[1][0][0], obj[1][0][1], - this.protoblock.dockTypes[0]]); - break; - default: - if (this.isArgBlock()) { - obj = this.protoblock.generator(this.clampCount[0]); - } else if (this.isTwoArgBlock()) { - obj = this.protoblock.generator(this.clampCount[0]); - } else { - obj = this.protoblock.generator(); + // If it is in the trash, make sure it remains hidden. + if (that.trash) { + that.hide(); } - this.size += plusMinus; - break; - } - } + }; - switch (this.name) { - case "nameddoArg": - for (let i = 1; i < obj[1].length - 1; i++) { - this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); - } - this.docks.push([obj[1][2][0], obj[1][2][1], "in"]); - break; - case "namedcalcArg": - for (let i = 1; i < obj[1].length; i++) { - this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); - } - break; - case "doArg": - this.docks.push([obj[1][1][0], obj[1][1][1], - this.protoblock.dockTypes[1]]); - for (let i = 2; i < obj[1].length - 1; i++) { - this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); - } - this.docks.push([obj[1][3][0], obj[1][3][1], "in"]); - break; - case "makeblock": - case "calcArg": - this.docks.push([obj[1][1][0], obj[1][1][1], - this.protoblock.dockTypes[1]]); - for (let i = 2; i < obj[1].length; i++) { - this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); - } - break; - default: - break; - } + this.postProcessArg = this; - // Save new artwork and dock positions. - this.artwork = obj[0]; - for (let i = 0; i < this.docks.length; i++) { - this.docks[i][0] = obj[1][i][0]; - this.docks[i][1] = obj[1][i][1]; - } + this.protoblock.scale = scale; + this._newArtwork(0); + this.regenerateArtwork(true, []); - this.width = obj[2]; - this.height = obj[3]; - this.hitHeight = obj[4]; - }; + if (this.text !== null) { + this._positionText(scale); + } - /* - * Load any artwork associated with the block and create any - * extra parts. Image components are loaded asynchronously so - * most the work happens in callbacks. - * - * We also need a text label for some blocks. For number and - * text blocks, this is the primary label; for parameter - * blocks, this is used to display the current block value. - * @return{void} - * @public - */ - this.imageLoad = function() { - let fontSize = 10 * this.protoblock.scale; - this.text = new createjs.Text("", fontSize + "px Sans", - platformColor.blockText); - this.generateArtwork(true, []); - }; + if (this.container !== null) { + that = this; + + /* + * After new buttons are creates, they are cached and a + * new hit are is calculated + * @param-that = this = container + * @return{void} + * @private + */ + let _postProcess = function (that) { + that.collapseButtonBitmap.scaleX = + that.collapseButtonBitmap.scaleY = + that.collapseButtonBitmap.scale = scale / 3; + that.expandButtonBitmap.scaleX = + that.expandButtonBitmap.scaleY = + that.expandButtonBitmap.scale = scale / 3; + that.updateCache(); + that._calculateBlockHitArea(); + }; - /* - * Add an image to a block - * @return{void} - * @private - */ - this._addImage = function() { - let image = new Image(); - let that = this; + if (this.isCollapsible()) { + this._generateCollapseArtwork(_postProcess); + let fontSize = 10 * scale; + this.collapseText.font = fontSize + "px Sans"; + this._positionCollapseLabel(scale); + } + } + }; /* - * The loader + * Create new artwork for a block + * @param-plusMinus specifies how much a clamp block expands or contracts * @return{void} * @private */ - image.onload = function() { - let bitmap = new createjs.Bitmap(image); - // Don't override the image on a media block. - if (that.name === "media") { - for (let i = 0; i < that.container.children.length; i++) { - if (that.container.children[i].name === "media") { - return; - } + this._newArtwork = function (plusMinus) { + let proto, obj; + if (this.isInlineCollapsible()) { + proto = new ProtoBlock("collapse-note"); + proto.scale = this.protoblock.scale; + if (this.name === "interval") { + proto.extraWidth = 80; + } else { + proto.extraWidth = 40; } - } - bitmap.name = "media"; - that.container.addChild(bitmap); - that._positionMedia(bitmap, image.width, image.height, - that.protoblock.scale); - /* - that._positionMedia( - bitmap, - image.width, - image.height, - that.protoblock.scale - ); - */ - that.imageBitmap = bitmap; - that.updateCache(); - }; - - image.src = this.image; - }; - - /* - * Sometimes (in the case of namedboxes and nameddos) we need - * to regenerate the artwork associated with a block. - * @param-is the collapse artwork also generated? - * @return{void} - * @public - */ - this.regenerateArtwork = function(collapse) { - // First we need to remove the old artwork. - if (this.bitmap != null) { - this.container.removeChild(this.bitmap); - } - - if (this.highlightBitmap != null) { - this.container.removeChild(this.highlightBitmap); - } - - if (this.disconnectedBitmap != null) { - this.container.removeChild(this.disconnectedBitmap); - } - - if (this.disconnectedHighlightBitmap != null) { - this.container.removeChild(this.disconnectedHighlightBitmap); - } - - if (collapse && this.collapseBlockBitmap !== null) { - this.container.removeChild(this.collapseButtonBitmap); - this.container.removeChild(this.expandButtonBitmap); - this.container.removeChild(this.collapseBlockBitmap); - this.container.removeChild(this.highlightCollapseBlockBitmap); - } - - // Then we generate new artwork. - this.generateArtwork(false); - }; - - /* - * Generate the artwork for a block. - * @param-the first time, add the event handlers - * @return{void} - * @public - */ - this.generateArtwork = function(firstTime) { - // Get the block labels from the protoblock. - let that = this; - let thisBlock = this.blocks.blockList.indexOf(this); - let block_label = ""; - - // Create the highlight bitmap for the block. - let __processHighlightBitmap = function(bitmap, that) { - if (that.highlightBitmap != null) { - that.container.removeChild(that.highlightBitmap); - } - - that.highlightBitmap = bitmap; - that.container.addChild(that.highlightBitmap); - that.highlightBitmap.x = 0; - that.highlightBitmap.y = 0; - that.highlightBitmap.name = "bmp_highlight_" + thisBlock; - if (!that.blocks.logo.runningLilypond) { - that.highlightBitmap.cursor = "pointer"; - } - // Hide highlight bitmap to start. - that.highlightBitmap.visible = false; - - // At me point, it should be safe to calculate the - // bounds of the container and cache its contents. - if (!firstTime) { - that.container.uncache(); - } - - __callback = function(that, firstTime) { - that.blocks.refreshCanvas(); - let thisBlock = that.blocks.blockList.indexOf(that); + proto.zeroArgBlock(); + obj = proto.generator(); + this.collapseArtwork = obj[0]; + obj = this.protoblock.generator(this.clampCount[0]); + } else if (this.isCollapsible()) { + proto = new ProtoBlock("collapse"); + proto.scale = this.protoblock.scale; + proto.extraWidth = 40; + proto.basicBlockCollapsed(); + obj = proto.generator(); + this.collapseArtwork = obj[0]; + obj = this.protoblock.generator(this.clampCount[0]); + } else if (this.name === "ifthenelse") { + obj = this.protoblock.generator(this.clampCount[0], + this.clampCount[1]); + } else if (this.protoblock.style === "clamp") { + obj = this.protoblock.generator(this.clampCount[0]); + } else if (this.protoblock.style === "argflowclamp") { + obj = this.protoblock.generator(this.clampCount[0]); + } else { + switch (this.name) { + case "equal": + case "greater": + case "less": + obj = this.protoblock.generator(this.clampCount[0]); + break; + case "makeblock": + case "calcArg": + case "doArg": + case "namedcalcArg": + case "nameddoArg": + obj = this.protoblock.generator(this.argClampSlots); + this.size = 2; + for (let i = 0; i < this.argClampSlots.length; i++) { + this.size += this.argClampSlots[i]; + } + this.docks = []; + this.docks.push([obj[1][0][0], obj[1][0][1], + this.protoblock.dockTypes[0]]); + break; + default: + if (this.isArgBlock()) { + obj = this.protoblock.generator(this.clampCount[0]); + } else if (this.isTwoArgBlock()) { + obj = this.protoblock.generator(this.clampCount[0]); + } else { + obj = this.protoblock.generator(); + } + this.size += plusMinus; + break; + } + } - if (firstTime) { - that._loadEventHandlers(); - if (that.image !== null) { - console.log(that.name); - that._addImage(); + switch (this.name) { + case "nameddoArg": + for (let i = 1; i < obj[1].length - 1; i++) { + this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); } - - that._finishImageLoad(); - } else { - if (that.isCollapsible()) { - that._ensureDecorationOnTop(); + this.docks.push([obj[1][2][0], obj[1][2][1], "in"]); + break; + case "namedcalcArg": + for (let i = 1; i < obj[1].length; i++) { + this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); + } + break; + case "doArg": + this.docks.push([obj[1][1][0], obj[1][1][1], + this.protoblock.dockTypes[1]]); + for (let i = 2; i < obj[1].length - 1; i++) { + this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); + } + this.docks.push([obj[1][3][0], obj[1][3][1], "in"]); + break; + case "makeblock": + case "calcArg": + this.docks.push([obj[1][1][0], obj[1][1][1], + this.protoblock.dockTypes[1]]); + for (let i = 2; i < obj[1].length; i++) { + this.docks.push([obj[1][i][0], obj[1][i][1], "anyin"]); } + break; + default: + break; + } - // Adjust the docks. - that.blocks.adjustDocks(thisBlock, true); + // Save new artwork and dock positions. + this.artwork = obj[0]; + for (let i = 0; i < this.docks.length; i++) { + this.docks[i][0] = obj[1][i][0]; + this.docks[i][1] = obj[1][i][1]; + } - // Adjust the text position. - that._positionText(that.protoblock.scale); + this.width = obj[2]; + this.height = obj[3]; + this.hitHeight = obj[4]; + }; - if (that.isCollapsible()) { - that.bitmap.visible = !that.collapsed; - that.highlightBitmap.visible = false; - that.updateCache(); - } + /* + * Load any artwork associated with the block and create any + * extra parts. Image components are loaded asynchronously so + * most the work happens in callbacks. + * + * We also need a text label for some blocks. For number and + * text blocks, this is the primary label; for parameter + * blocks, this is used to display the current block value. + * @return{void} + * @public + */ + this.imageLoad = function () { + let fontSize = 10 * this.protoblock.scale; + this.text = new createjs.Text("", fontSize + "px Sans", + platformColor.blockText); + this.generateArtwork(true, []); + }; - if (that.postProcess != null) { - that.postProcess(that.postProcessArg); - that.postProcess = null; + /* + * Add an image to a block + * @return{void} + * @private + */ + this._addImage = function () { + let image = new Image(); + let that = this; + + /* + * The loader + * @return{void} + * @private + */ + image.onload = function () { + let bitmap = new createjs.Bitmap(image); + // Don't override the image on a media block. + if (that.name === "media") { + for (let i = 0; i < that.container.children.length; i++) { + if (that.container.children[i].name === "media") { + return; + } } } + bitmap.name = "media"; + that.container.addChild(bitmap); + that._positionMedia(bitmap, image.width, image.height, + that.protoblock.scale); + /* + that._positionMedia( + bitmap, + image.width, + image.height, + that.protoblock.scale + ); + */ + that.imageBitmap = bitmap; + that.updateCache(); }; - that._createCache(__callback, firstTime); + image.src = this.image; }; - // Create the disconnect highlight bitmap for the block. - let __processDisconnectedHighlightBitmap = function(bitmap, that) { - if (that.disconnectedHighlightBitmap != null) { - that.container.removeChild(that.disconnectedHighlightBitmap); + /* + * Sometimes (in the case of namedboxes and nameddos) we need + * to regenerate the artwork associated with a block. + * @param-is the collapse artwork also generated? + * @return{void} + * @public + */ + this.regenerateArtwork = function (collapse) { + // First we need to remove the old artwork. + if (this.bitmap != null) { + this.container.removeChild(this.bitmap); } - that.disconnectedHighlightBitmap = bitmap; - that.container.addChild(that.disconnectedHighlightBitmap); - that.disconnectedHighlightBitmap.x = 0; - that.disconnectedHighlightBitmap.y = 0; - that.disconnectedHighlightBitmap.name = - "bmp_disconnect_hightlight_" + thisBlock; - if (!that.blocks.logo.runningLilypond) { - that.disconnectedHighlightBitmap.cursor = "pointer"; + if (this.highlightBitmap != null) { + this.container.removeChild(this.highlightBitmap); } - // Hide disconnected bitmap to start. - that.disconnectedHighlightBitmap.visible = false; - let artwork; - if (that.protoblock.disabled) { - artwork = that.artwork - .replace(/fill_color/g, DISABLEDFILLCOLOR) - .replace(/stroke_color/g, DISABLEDSTROKECOLOR) - .replace("block_label", safeSVG(block_label)); - } else { - artwork = that.artwork - .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[ - that.protoblock.palette.name]) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ - that.protoblock.palette.name]) - .replace("block_label", safeSVG(block_label)); + + if (this.disconnectedBitmap != null) { + this.container.removeChild(this.disconnectedBitmap); } - for (let i = 1; i < that.protoblock.staticLabels.length; i++) { - artwork = artwork.replace("arg_label_" + i, - that.protoblock.staticLabels[i]); + if (this.disconnectedHighlightBitmap != null) { + this.container.removeChild(this.disconnectedHighlightBitmap); } - _blockMakeBitmap(artwork, __processHighlightBitmap, that); + if (collapse && this.collapseBlockBitmap !== null) { + this.container.removeChild(this.collapseButtonBitmap); + this.container.removeChild(this.expandButtonBitmap); + this.container.removeChild(this.collapseBlockBitmap); + this.container.removeChild(this.highlightCollapseBlockBitmap); + } + + // Then we generate new artwork. + this.generateArtwork(false); }; - // Create the disconnect bitmap for the block. - let __processDisconnectedBitmap = function(bitmap, that) { - if (that.disconnectedBitmap != null) { - that.container.removeChild(that.disconnectedBitmap); - } + /* + * Generate the artwork for a block. + * @param-the first time, add the event handlers + * @return{void} + * @public + */ + this.generateArtwork = function (firstTime) { + // Get the block labels from the protoblock. + let that = this; + let thisBlock = this.blocks.blockList.indexOf(this); + let block_label = ""; + + // Create the highlight bitmap for the block. + let __processHighlightBitmap = function (bitmap, that) { + if (that.highlightBitmap != null) { + that.container.removeChild(that.highlightBitmap); + } + + that.highlightBitmap = bitmap; + that.container.addChild(that.highlightBitmap); + that.highlightBitmap.x = 0; + that.highlightBitmap.y = 0; + that.highlightBitmap.name = "bmp_highlight_" + thisBlock; + if (!that.blocks.logo.runningLilypond) { + that.highlightBitmap.cursor = "pointer"; + } + // Hide highlight bitmap to start. + that.highlightBitmap.visible = false; + + // At me point, it should be safe to calculate the + // bounds of the container and cache its contents. + if (!firstTime) { + that.container.uncache(); + } + + const __callback = function (that, firstTime) { + that.blocks.refreshCanvas(); + let thisBlock = that.blocks.blockList.indexOf(that); + + if (firstTime) { + that._loadEventHandlers(); + if (that.image !== null) { + console.log(that.name); + that._addImage(); + } - that.disconnectedBitmap = bitmap; - that.container.addChild(that.disconnectedBitmap); - that.disconnectedBitmap.x = 0; - that.disconnectedBitmap.y = 0; - that.disconnectedBitmap.name = "bmp_disconnect_" + thisBlock; - if (!that.blocks.logo.runningLilypond) { - that.disconnectedBitmap.cursor = "pointer"; - } - // Hide disconnected bitmap to start. - that.disconnectedBitmap.visible = false; - let artwork; - if (that.protoblock.disabled) { - artwork = that.artwork - .replace(/fill_color/g, DISABLEDFILLCOLOR) - .replace(/stroke_color/g, DISABLEDSTROKECOLOR) - .replace("block_label", safeSVG(block_label)); - } else { - artwork = that.artwork - .replace(/fill_color/g, platformColor.paletteColors[ - that.protoblock.palette.name][3]) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ - that.protoblock.palette.name]) - .replace("block_label", safeSVG(block_label)); + that._finishImageLoad(); + } else { + if (that.isCollapsible()) { + that._ensureDecorationOnTop(); + } + + // Adjust the docks. + that.blocks.adjustDocks(thisBlock, true); + + // Adjust the text position. + that._positionText(that.protoblock.scale); + + if (that.isCollapsible()) { + that.bitmap.visible = !that.collapsed; + that.highlightBitmap.visible = false; + that.updateCache(); + } + + if (that.postProcess != null) { + that.postProcess(that.postProcessArg); + that.postProcess = null; + } + } + }; + + that._createCache(__callback, firstTime); + }; + + // Create the disconnect highlight bitmap for the block. + let __processDisconnectedHighlightBitmap = function (bitmap, that) { + if (that.disconnectedHighlightBitmap != null) { + that.container.removeChild(that.disconnectedHighlightBitmap); + } + + that.disconnectedHighlightBitmap = bitmap; + that.container.addChild(that.disconnectedHighlightBitmap); + that.disconnectedHighlightBitmap.x = 0; + that.disconnectedHighlightBitmap.y = 0; + that.disconnectedHighlightBitmap.name = + "bmp_disconnect_hightlight_" + thisBlock; + if (!that.blocks.logo.runningLilypond) { + that.disconnectedHighlightBitmap.cursor = "pointer"; + } + // Hide disconnected bitmap to start. + that.disconnectedHighlightBitmap.visible = false; + let artwork; + if (that.protoblock.disabled) { + artwork = that.artwork + .replace(/fill_color/g, DISABLEDFILLCOLOR) + .replace(/stroke_color/g, DISABLEDSTROKECOLOR) + .replace("block_label", safeSVG(block_label)); + } else { + artwork = that.artwork + .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[that.protoblock.palette.name]) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace("block_label", safeSVG(block_label)); + } + + for (let i = 1; i < that.protoblock.staticLabels.length; i++) { + artwork = artwork.replace("arg_label_" + i, + that.protoblock.staticLabels[i]); + } + + _blockMakeBitmap(artwork, __processHighlightBitmap, that); + }; + + // Create the disconnect bitmap for the block. + let __processDisconnectedBitmap = function (bitmap, that) { + if (that.disconnectedBitmap != null) { + that.container.removeChild(that.disconnectedBitmap); + } + + that.disconnectedBitmap = bitmap; + that.container.addChild(that.disconnectedBitmap); + that.disconnectedBitmap.x = 0; + that.disconnectedBitmap.y = 0; + that.disconnectedBitmap.name = "bmp_disconnect_" + thisBlock; + if (!that.blocks.logo.runningLilypond) { + that.disconnectedBitmap.cursor = "pointer"; + } + // Hide disconnected bitmap to start. + that.disconnectedBitmap.visible = false; + let artwork; + if (that.protoblock.disabled) { + artwork = that.artwork + .replace(/fill_color/g, DISABLEDFILLCOLOR) + .replace(/stroke_color/g, DISABLEDSTROKECOLOR) + .replace("block_label", safeSVG(block_label)); + } else { + artwork = that.artwork + .replace(/fill_color/g, platformColor.paletteColors[that.protoblock.palette.name][3]) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace("block_label", safeSVG(block_label)); + } + + for (let i = 1; i < that.protoblock.staticLabels.length; i++) { + artwork = artwork.replace("arg_label_" + i, + that.protoblock.staticLabels[i]); + } + + _blockMakeBitmap(artwork, __processDisconnectedHighlightBitmap, + that); + }; + + // Create the bitmap for the block. + let __processBitmap = function (bitmap, that) { + if (that.bitmap != null) { + that.container.removeChild(that.bitmap); + } + + that.bitmap = bitmap; + that.container.addChild(that.bitmap); + that.bitmap.x = 0; + that.bitmap.y = 0; + that.bitmap.name = "bmp_" + thisBlock; + that.bitmap.cursor = "pointer"; + that.blocks.refreshCanvas(); + let artwork; + if (that.protoblock.disabled) { + artwork = that.artwork + .replace(/fill_color/g, DISABLEDFILLCOLOR) + .replace(/stroke_color/g, DISABLEDSTROKECOLOR) + .replace("block_label", safeSVG(block_label)); + } else { + artwork = that.artwork + .replace(/fill_color/g, platformColor.disconnected) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace("block_label", safeSVG(block_label)); + } + + for (let i = 1; i < that.protoblock.staticLabels.length; i++) { + artwork = artwork.replace("arg_label_" + i, + that.protoblock.staticLabels[i]); + } + + _blockMakeBitmap(artwork, __processDisconnectedBitmap, that); + }; + + if (this.overrideName && this.name !== "outputtools") { + if (["namedbox", "storein2", "nameddo", "nameddoArg", "namedcalc", + "namedcalcArg"].indexOf(this.name) !== -1) { + block_label = this.overrideName; + if (getTextWidth(block_label, "bold 20pt Sans") > TEXTWIDTH) { + block_label = block_label.substr(0, STRINGLEN) + "..."; + } + } else { + block_label = this.overrideName; + } + } else if (this.protoblock.staticLabels.length > 0 && + !this.protoblock.image) { + // Label should be defined inside _(). + block_label = this.protoblock.staticLabels[0]; } - for (let i = 1; i < that.protoblock.staticLabels.length; i++) { - artwork = artwork.replace("arg_label_" + i, - that.protoblock.staticLabels[i]); + while (this.protoblock.staticLabels.length < this.protoblock.args + 1) { + this.protoblock.staticLabels.push(""); } - _blockMakeBitmap(artwork, __processDisconnectedHighlightBitmap, - that); - }; + if (firstTime) { + // Create artwork and dock. + this.protoblock.scale = this.blocks.blockScale; - // Create the bitmap for the block. - let __processBitmap = function(bitmap, that) { - if (that.bitmap != null) { - that.container.removeChild(that.bitmap); - } + let obj = this.protoblock.generator(); + this.artwork = obj[0]; + for (let i = 0; i < obj[1].length; i++) { + this.docks.push([obj[1][i][0], obj[1][i][1], + this.protoblock.dockTypes[i]]); + } - that.bitmap = bitmap; - that.container.addChild(that.bitmap); - that.bitmap.x = 0; - that.bitmap.y = 0; - that.bitmap.name = "bmp_" + thisBlock; - that.bitmap.cursor = "pointer"; - that.blocks.refreshCanvas(); + this.width = obj[2]; + this.height = obj[3]; + this.hitHeight = obj[4]; + } let artwork; - if (that.protoblock.disabled) { - artwork = that.artwork + if (this.protoblock.disabled) { + artwork = this.artwork .replace(/fill_color/g, DISABLEDFILLCOLOR) .replace(/stroke_color/g, DISABLEDSTROKECOLOR) .replace("block_label", safeSVG(block_label)); } else { - artwork = that.artwork - .replace(/fill_color/g, platformColor.disconnected) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ - that.protoblock.palette.name]) + artwork = this.artwork + .replace(/fill_color/g, PALETTEFILLCOLORS[this.protoblock.palette.name]) + .replace(/stroke_color/g, PALETTESTROKECOLORS[this.protoblock.palette.name]) .replace("block_label", safeSVG(block_label)); } - for (let i = 1; i < that.protoblock.staticLabels.length; i++) { + for (let i = 1; i < this.protoblock.staticLabels.length; i++) { artwork = artwork.replace("arg_label_" + i, - that.protoblock.staticLabels[i]); + this.protoblock.staticLabels[i]); } - _blockMakeBitmap(artwork, __processDisconnectedBitmap, that); + that.blocks.blockArt[that.blocks.blockList.indexOf(that)] = artwork; + + _blockMakeBitmap(artwork, __processBitmap, this); }; - if (this.overrideName && this.name !== "outputtools") { - if (["namedbox", "storein2", "nameddo", "nameddoArg", "namedcalc", - "namedcalcArg"].indexOf(this.name) !== -1) { - block_label = this.overrideName; - if (getTextWidth(block_label, "bold 20pt Sans") > TEXTWIDTH) { - block_label = block_label.substr(0, STRINGLEN) + "..."; + /* + * After the block artwork has loaded, update labels, etc. + * @return{void} + * @private + */ + this._finishImageLoad = function () { + let thisBlock = this.blocks.blockList.indexOf(this); + let proto, obj, label, attr; + // Value blocks get a modifiable text label. + if (SPECIALINPUTS.indexOf(this.name) !== -1) { + if (this.value == null) { + switch (this.name) { + case "text": + this.value = "---"; + break; + case "solfege": + case "eastindiansolfege": + this.value = "sol"; + break; + case "scaledegree2": + this.value = "5"; + break; + case "customNote": + let len = this.blocks.logo.synth.startingPitch.length; + this.value = + this.blocks.logo.synth.startingPitch.substring( + 0, len - 1) + "(+0)"; + break; + case "notename": + this.value = "G"; + break; + case "rest": + this.value = "rest"; + break; + case "boolean": + this.value = true; + break; + case "number": + this.value = NUMBERBLOCKDEFAULT; + break; + case "modename": + this.value = DEFAULTMODE; + break; + case "accidentalname": + this.value = DEFAULTACCIDENTAL; + break; + case "intervalname": + this.value = DEFAULTINTERVAL; + break; + case "invertmode": + this.value = DEFAULTINVERT; + break; + case "voicename": + this.value = DEFAULTVOICE; + break; + case "noisename": + this.value = DEFAULTNOISE; + break; + case "drumname": + this.value = DEFAULTDRUM; + break; + case "effectsname": + this.value = DEFAULTEFFECT; + break; + case "filtertype": + this.value = DEFAULTFILTERTYPE; + break; + case "oscillatortype": + this.value = DEFAULTOSCILLATORTYPE; + break; + case "temperamentname": + this.value = "equal"; + break; + case "grid": + this.value = "Cartesian"; + break; + } } - } else { - block_label = this.overrideName; - } - } else if ( - this.protoblock.staticLabels.length > 0 && - !this.protoblock.image - ) { - // Label should be defined inside _(). - block_label = this.protoblock.staticLabels[0]; - } - while (this.protoblock.staticLabels.length < this.protoblock.args + 1) { - this.protoblock.staticLabels.push(""); - } + if (this.name === "solfege") { + obj = splitSolfege(this.value); + label = i18nSolfege(obj[0]); + attr = obj[1]; + + if (attr !== "♮") { + label += attr; + } + } else if (this.name === "eastindiansolfege") { + obj = splitSolfege(this.value); + label = WESTERN2EISOLFEGENAMES[obj[0]]; + attr = obj[1]; - if (firstTime) { - // Create artwork and dock. - this.protoblock.scale = this.blocks.blockScale; + if (attr !== "♮") { + label += attr; + } + } else if (this.name === "scaledegree2") { + obj = splitScaleDegree(this.value); + label = obj[0]; + attr = obj[1]; - let obj = this.protoblock.generator(); - this.artwork = obj[0]; - for (let i = 0; i < obj[1].length; i++) { - this.docks.push([obj[1][i][0], obj[1][i][1], - this.protoblock.dockTypes[i]]); + if (attr !== "♮") { + label += attr; + } + } else if (this.name === "drumname") { + label = getDrumName(this.value); + } else if (this.name === "noisename") { + label = getNoiseName(this.value); + } else if (this.name === "outputtools") { + label = this.overrideName; + } else { + if (this.value !== null) { + label = this.value.toString(); + } else { + label = "???"; + } + } + + if (WIDENAMES.indexOf(this.name) === -1 && + getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { + label = label.substr(0, STRINGLEN) + "..."; + } + + this.text.text = label; + this.container.addChild(this.text); + this._positionText(this.protoblock.scale); + } else if (this.protoblock.parameter) { + // Parameter blocks get a text label to show their current value. + this.container.addChild(this.text); + this._positionText(this.protoblock.scale); } - this.width = obj[2]; - this.height = obj[3]; - this.hitHeight = obj[4]; - } - let artwork; - if (this.protoblock.disabled) { - artwork = this.artwork - .replace(/fill_color/g, DISABLEDFILLCOLOR) - .replace(/stroke_color/g, DISABLEDSTROKECOLOR) - .replace("block_label", safeSVG(block_label)); - } else { - artwork = this.artwork - .replace(/fill_color/g, PALETTEFILLCOLORS[ - this.protoblock.palette.name]) - .replace(/stroke_color/g, PALETTESTROKECOLORS[ - this.protoblock.palette.name]) - .replace("block_label", safeSVG(block_label)); - } + if (!this.isCollapsible()) { + this.loadComplete = true; + if (this.postProcess !== null) { + this.postProcess(this.postProcessArg); + this.postProcess = null; + } - for (let i = 1; i < this.protoblock.staticLabels.length; i++) { - artwork = artwork.replace("arg_label_" + i, - this.protoblock.staticLabels[i]); - } + // this.blocks.refreshCanvas(); + this.blocks.cleanupAfterLoad(this.name); + } else { + // Some blocks, e.g., Start blocks and Action blocks can + // collapse, so add an event handler. + if (this.isInlineCollapsible()) { + proto = new ProtoBlock("collapse-note"); + proto.scale = this.protoblock.scale; + if (this.name === "interval") { + proto.extraWidth = 80; + } else { + proto.extraWidth = 40; + } + proto.zeroArgBlock(); + } else { + proto = new ProtoBlock("collapse"); + proto.scale = this.protoblock.scale; + proto.extraWidth = 40; + proto.basicBlockCollapsed(); + } - that.blocks.blockArt[that.blocks.blockList.indexOf(that)] = artwork; + obj = proto.generator(); + this.collapseArtwork = obj[0]; - _blockMakeBitmap(artwork, __processBitmap, this); - }; + let postProcess = function (that) { + that.loadComplete = true; - /* - * After the block artwork has loaded, update labels, etc. - * @return{void} - * @private - */ - this._finishImageLoad = function() { - let thisBlock = this.blocks.blockList.indexOf(this); - let proto, obj, label, attr; - // Value blocks get a modifiable text label. - if (SPECIALINPUTS.indexOf(this.name) !== -1) { - if (this.value == null) { - switch (this.name) { - case "text": - this.value = "---"; - break; - case "solfege": - case "eastindiansolfege": - this.value = "sol"; - break; - case "scaledegree2": - this.value = "5"; - break; - case "customNote": - let len = this.blocks.logo.synth.startingPitch.length; - this.value = - this.blocks.logo.synth.startingPitch.substring( - 0, len - 1) + "(+0)"; - break; - case "notename": - this.value = "G"; - break; - case "rest": - this.value = "rest"; - break; - case "boolean": - this.value = true; - break; - case "number": - this.value = NUMBERBLOCKDEFAULT; - break; - case "modename": - this.value = DEFAULTMODE; - break; - case "accidentalname": - this.value = DEFAULTACCIDENTAL; - break; - case "intervalname": - this.value = DEFAULTINTERVAL; - break; - case "invertmode": - this.value = DEFAULTINVERT; - break; - case "voicename": - this.value = DEFAULTVOICE; - break; - case "noisename": - this.value = DEFAULTNOISE; - break; - case "drumname": - this.value = DEFAULTDRUM; - break; - case "effectsname": - this.value = DEFAULTEFFECT; - break; - case "filtertype": - this.value = DEFAULTFILTERTYPE; - break; - case "oscillatortype": - this.value = DEFAULTOSCILLATORTYPE; - break; - case "temperamentname": - this.value = "equal"; - break; - case "grid": - this.value = "Cartesian"; - break; + if (that.postProcess !== null) { + that.postProcess(that.postProcessArg); + that.postProcess = null; + } + }; + + if (this.isCollapsible()) { + this._generateCollapseArtwork(postProcess); } } - if (this.name === "solfege") { - obj = splitSolfege(this.value); - label = i18nSolfege(obj[0]); - attr = obj[1]; + this.blocks.refreshCanvas(); + }; - if (attr !== "♮") { - label += attr; - } - } else if (this.name === "eastindiansolfege") { - obj = splitSolfege(this.value); - label = WESTERN2EISOLFEGENAMES[obj[0]]; - attr = obj[1]; + /* + * Generate the collapsed artwork + * @param postProcess = a process to run after the artwork is generated + * @return{void} + * @private + */ + this._generateCollapseArtwork = function (postProcess) { + let that = this; + let thisBlock = this.blocks.blockList.indexOf(this); - if (attr !== "♮") { - label += attr; + /* + * Run the postprocess function after the artwork is loaded + * @return{void} + * @private + */ + let __finishCollapse = function (that) { + if (postProcess !== null) { + postProcess(that); } - } else if(this.name === "scaledegree2") { - obj = splitScaleDegree(this.value); - label = obj[0]; - attr = obj[1]; - if(attr !== "♮") { - label += attr; - } - } else if (this.name === "drumname") { - label = getDrumName(this.value); - } else if (this.name === "noisename") { - label = getNoiseName(this.value); - } else if (this.name === "outputtools") { - label = this.overrideName; - } else { - if (this.value !== null) { - label = this.value.toString(); - } else { - label = "???"; + that.blocks.refreshCanvas(); + that.blocks.cleanupAfterLoad(that.name); + if (that.trash) { + that.collapseText.visible = false; + that.collapseButtonBitmap.visible = false; + that.expandButtonBitmap.visible = false; } - } + }; - if (WIDENAMES.indexOf(this.name) === -1 && - getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { - label = label.substr(0, STRINGLEN) + "..."; - } + /* + * Create the artwork for the collapse buttons + * @param - that = this + * @return{void} + * @private + */ + let __processCollapseButton = function (that) { + let image = new Image(); + image.onload = function () { + that.collapseButtonBitmap = new createjs.Bitmap(image); + that.collapseButtonBitmap.scaleX = + that.collapseButtonBitmap.scaleY = + that.collapseButtonBitmap.scale = + that.protoblock.scale / 3; + that.container.addChild(that.collapseButtonBitmap); + that.collapseButtonBitmap.x = 2 * that.protoblock.scale; + if (that.isInlineCollapsible()) { + that.collapseButtonBitmap.y = 4 * that.protoblock.scale; + } else { + that.collapseButtonBitmap.y = 10 * that.protoblock.scale; + } - this.text.text = label; - this.container.addChild(this.text); - this._positionText(this.protoblock.scale); - } else if (this.protoblock.parameter) { - // Parameter blocks get a text label to show their current value. - this.container.addChild(this.text); - this._positionText(this.protoblock.scale); - } + that.collapseButtonBitmap.visible = !that.collapsed; - if (!this.isCollapsible()) { - this.loadComplete = true; - if (this.postProcess !== null) { - this.postProcess(this.postProcessArg); - this.postProcess = null; - } + __finishCollapse(that); + }; - // this.blocks.refreshCanvas(); - this.blocks.cleanupAfterLoad(this.name); - } else { - // Some blocks, e.g., Start blocks and Action blocks can - // collapse, so add an event handler. - if (this.isInlineCollapsible()) { - proto = new ProtoBlock("collapse-note"); - proto.scale = this.protoblock.scale; - if (this.name === "interval") { - proto.extraWidth = 80; - } else { - proto.extraWidth = 40; + image.src = + "data:image/svg+xml;base64," + + window.btoa(unescape(encodeURIComponent(COLLAPSEBUTTON))); + }; + + /* + * Create the artwork for the expand buttons + * @param - that = this + * @return{void} + * @private + */ + let __processExpandButton = function (that) { + let image = new Image(); + image.onload = function () { + that.expandButtonBitmap = new createjs.Bitmap(image); + that.expandButtonBitmap.scaleX = + that.expandButtonBitmap.scaleY = + that.expandButtonBitmap.scale = + that.protoblock.scale / 3; + + that.container.addChild(that.expandButtonBitmap); + that.expandButtonBitmap.visible = that.collapsed; + + that.expandButtonBitmap.x = 2 * that.protoblock.scale; + if (that.isInlineCollapsible()) { + that.expandButtonBitmap.y = 4 * that.protoblock.scale; + } else { + that.expandButtonBitmap.y = 10 * that.protoblock.scale; + } + + __processCollapseButton(that); + }; + + image.src = + "data:image/svg+xml;base64," + + window.btoa(unescape(encodeURIComponent(EXPANDBUTTON))); + }; + + /* + * Processing the highlighted collapsed image + * @param-bitmap = highlight artwork + * @param-that = this + * @return{void} + * @private + */ + let __processHighlightCollapseBitmap = function (bitmap, that) { + that.highlightCollapseBlockBitmap = bitmap; + that.highlightCollapseBlockBitmap.name = + "highlight_collapse_" + thisBlock; + that.container.addChild(that.highlightCollapseBlockBitmap); + that.highlightCollapseBlockBitmap.visible = false; + + if (that.collapseText === null) { + let fontSize = 10 * that.protoblock.scale; + switch (that.name) { + case "action": + that.collapseText = new createjs.Text( + _("action"), fontSize + "px Sans", + platformColor.blockText); + break; + case "start": + that.collapseText = new createjs.Text( + _("start"), fontSize + "px Sans", + platformColor.blockText); + break; + case "matrix": + that.collapseText = new createjs.Text( + _("matrix"), fontSize + "px Sans", + platformColor.blockText); + break; + case "status": + that.collapseText = new createjs.Text( + _("status"), fontSize + "px Sans", + platformColor.blockText); + break; + case "pitchdrummatrix": + that.collapseText = new createjs.Text( + _("drum mapper"), fontSize + "px Sans", + platformColor.blockText); + break; + case "rhythmruler": + that.collapseText = new createjs.Text( + _("ruler"), fontSize + "px Sans", + platformColor.blockText); + break; + case "timbre": + that.collapseText = new createjs.Text( + _("timbre"), fontSize + "px Sans", + platformColor.blockText); + break; + case "pitchstaircase": + that.collapseText = new createjs.Text( + _("stair"), fontSize + "px Sans", + platformColor.blockText); + break; + case "tempo": + that.collapseText = new createjs.Text( + _("tempo"), fontSize + "px Sans", + platformColor.blockText); + break; + case "modewidget": + that.collapseText = new createjs.Text( + _("mode"), fontSize + "px Sans", + platformColor.blockText); + break; + case "pitchslider": + that.collapseText = new createjs.Text( + _("slider"), fontSize + "px Sans", + platformColor.blockText); + break; + case "musickeyboard": + that.collapseText = new createjs.Text( + _("keyboard"), fontSize + "px Sans", + platformColor.blockText); + break; + case "drum": + that.collapseText = new createjs.Text( + _("drum"), fontSize + "px Sans", + platformColor.blockText); + break; + case "rhythmruler2": + that.collapseText = new createjs.Text( + _("rhythm maker"), fontSize + "px Sans", + platformColor.blockText); + break; + case "newnote": + that.collapseText = new createjs.Text( + _("note value"), fontSize + "px Sans", + platformColor.blockText); + break; + case "interval": + that.collapseText = new createjs.Text( + _("scalar interval"), fontSize + "px Sans", + platformColor.blockText); + break; + case "osctime": + that.collapseText = new createjs.Text( + _("milliseconds"), fontSize + "px Sans", + platformColor.blockText); + break; + case "temperament": + that.collapseText = new createjs.Text( + _("temperament"), fontSize + "px Sans", + platformColor.blockText); + break; + default: + that.collapseText = new createjs.Text( + "foobar", fontSize + "px Sans", + platformColor.blockText); + } + + that.collapseText.textAlign = "left"; + that.collapseText.textBaseline = "alphabetic"; + that.container.addChild(that.collapseText); } - proto.zeroArgBlock(); - } else { - proto = new ProtoBlock("collapse"); - proto.scale = this.protoblock.scale; - proto.extraWidth = 40; - proto.basicBlockCollapsed(); - } - obj = proto.generator(); - this.collapseArtwork = obj[0]; + that._positionCollapseLabel(that.protoblock.scale); + that.collapseText.visible = that.collapsed; + that._ensureDecorationOnTop(); - let postProcess = function(that) { - that.loadComplete = true; + // Save the collapsed block artwork for export. + that.blocks.blockCollapseArt[that.blocks.blockList.indexOf(that)] = + that.collapseArtwork + .replace(/fill_color/g, PALETTEFILLCOLORS[that.protoblock.palette.name]) + .replace(/stroke_color/g, PALETTESTROKECOLORS[that.protoblock.palette.name]) + .replace("block_label", safeSVG(that.collapseText.text)); - if (that.postProcess !== null) { - that.postProcess(that.postProcessArg); - that.postProcess = null; - } + __processExpandButton(that); }; - if (this.isCollapsible()) { - this._generateCollapseArtwork(postProcess); - } - } + /* + * Processing the collapsed block + * @param-bitmap = block artwork + * @param-that = this + * @return{void} + * @private + */ + let __processCollapseBitmap = function (bitmap, that) { + that.collapseBlockBitmap = bitmap; + that.collapseBlockBitmap.name = "collapse_" + thisBlock; + that.container.addChild(that.collapseBlockBitmap); + that.collapseBlockBitmap.visible = that.collapsed; + that.blocks.refreshCanvas(); - this.blocks.refreshCanvas(); - }; + let artwork = that.collapseArtwork; + _blockMakeBitmap( + artwork + .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[that.protoblock.palette.name]) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace("block_label", ""), + __processHighlightCollapseBitmap, that); + }; - /* - * Generate the collapsed artwork - * @param postProcess = a process to run after the artwork is generated - * @return{void} - * @private - */ - this._generateCollapseArtwork = function(postProcess) { - let that = this; - let thisBlock = this.blocks.blockList.indexOf(this); + let artwork = this.collapseArtwork + .replace(/fill_color/g, PALETTEFILLCOLORS[this.protoblock.palette.name]) + .replace(/stroke_color/g, PALETTESTROKECOLORS[this.protoblock.palette.name]) + .replace("block_label", ""); + _blockMakeBitmap(artwork, __processCollapseBitmap, this); + }; /* - * Run the postprocess function after the artwork is loaded + * Hide this block * @return{void} - * @private + * @public */ - let __finishCollapse = function(that) { - if (postProcess !== null) { - postProcess(that); + this.hide = function () { + this.container.visible = false; + if (this.isCollapsible()) { + this.collapseText.visible = false; + this.expandButtonBitmap.visible = false; + this.collapseButtonBitmap.visible = false; } - that.blocks.refreshCanvas(); - that.blocks.cleanupAfterLoad(that.name); - if (that.trash) { - that.collapseText.visible = false; - that.collapseButtonBitmap.visible = false; - that.expandButtonBitmap.visible = false; - } + this.updateCache(); + this.blocks.refreshCanvas(); }; /* - * Create the artwork for the collapse buttons - * @param - that = this - * @return{void} - * @private + * Is this block disconnected from other blocks? + * @return{boolean} true if the block is disconnected from other blocks + * @public */ - let __processCollapseButton = function(that) { - let image = new Image(); - image.onload = function() { - that.collapseButtonBitmap = new createjs.Bitmap(image); - that.collapseButtonBitmap.scaleX = - that.collapseButtonBitmap.scaleY = - that.collapseButtonBitmap.scale = - that.protoblock.scale / 3; - that.container.addChild(that.collapseButtonBitmap); - that.collapseButtonBitmap.x = 2 * that.protoblock.scale; - if (that.isInlineCollapsible()) { - that.collapseButtonBitmap.y = 4 * that.protoblock.scale; - } else { - that.collapseButtonBitmap.y = 10 * that.protoblock.scale; - } - - that.collapseButtonBitmap.visible = !that.collapsed; - - __finishCollapse(that); - }; + this.isDisconnected = function () { + if (this.disconnectedBitmap === null) { + return false; + } - image.src = - "data:image/svg+xml;base64," + - window.btoa(unescape(encodeURIComponent(COLLAPSEBUTTON))); - }; + if (this.connections[0] !== null) { + return false; + } - /* - * Create the artwork for the expand buttons - * @param - that = this - * @return{void} - * @private - */ - let __processExpandButton = function(that) { - let image = new Image(); - image.onload = function() { - that.expandButtonBitmap = new createjs.Bitmap(image); - that.expandButtonBitmap.scaleX = - that.expandButtonBitmap.scaleY = - that.expandButtonBitmap.scale = - that.protoblock.scale / 3; - - that.container.addChild(that.expandButtonBitmap); - that.expandButtonBitmap.visible = that.collapsed; - - that.expandButtonBitmap.x = 2 * that.protoblock.scale; - if (that.isInlineCollapsible()) { - that.expandButtonBitmap.y = 4 * that.protoblock.scale; - } else { - that.expandButtonBitmap.y = 10 * that.protoblock.scale; + if (COLLAPSIBLES.indexOf(this.name) !== -1) { + if (INLINECOLLAPSIBLES.indexOf(this.name) === -1) { + return false; } + } - __processCollapseButton(that); - }; + if (this.isArgBlock()) { + return true; + } - image.src = - "data:image/svg+xml;base64," + - window.btoa(unescape(encodeURIComponent(EXPANDBUTTON))); - }; + if (last(this.connections) === null) { + return true; + } - /* - * Processing the highlighted collapsed image - * @param-bitmap = highlight artwork - * @param-that = this - * @return{void} - * @private - */ - let __processHighlightCollapseBitmap = function(bitmap, that) { - that.highlightCollapseBlockBitmap = bitmap; - that.highlightCollapseBlockBitmap.name = - "highlight_collapse_" + thisBlock; - that.container.addChild(that.highlightCollapseBlockBitmap); - that.highlightCollapseBlockBitmap.visible = false; - - if (that.collapseText === null) { - let fontSize = 10 * that.protoblock.scale; - switch (that.name) { - case "action": - that.collapseText = new createjs.Text( - _("action"), fontSize + "px Sans", - platformColor.blockText); - break; - case "start": - that.collapseText = new createjs.Text( - _("start"), fontSize + "px Sans", - platformColor.blockText); - break; - case "matrix": - that.collapseText = new createjs.Text( - _("matrix"), fontSize + "px Sans", - platformColor.blockText); - break; - case "status": - that.collapseText = new createjs.Text( - _("status"), fontSize + "px Sans", - platformColor.blockText); - break; - case "pitchdrummatrix": - that.collapseText = new createjs.Text( - _("drum mapper"), fontSize + "px Sans", - platformColor.blockText); - break; - case "rhythmruler": - that.collapseText = new createjs.Text( - _("ruler"), fontSize + "px Sans", - platformColor.blockText); - break; - case "timbre": - that.collapseText = new createjs.Text( - _("timbre"), fontSize + "px Sans", - platformColor.blockText); - break; - case "pitchstaircase": - that.collapseText = new createjs.Text( - _("stair"), fontSize + "px Sans", - platformColor.blockText); - break; - case "tempo": - that.collapseText = new createjs.Text( - _("tempo"), fontSize + "px Sans", - platformColor.blockText); - break; - case "modewidget": - that.collapseText = new createjs.Text( - _("mode"), fontSize + "px Sans", - platformColor.blockText); - break; - case "pitchslider": - that.collapseText = new createjs.Text( - _("slider"), fontSize + "px Sans", - platformColor.blockText); - break; - case "musickeyboard": - that.collapseText = new createjs.Text( - _("keyboard"), fontSize + "px Sans", - platformColor.blockText); - break; - case "drum": - that.collapseText = new createjs.Text( - _("drum"), fontSize + "px Sans", - platformColor.blockText); - break; - case "rhythmruler2": - that.collapseText = new createjs.Text( - _("rhythm maker"), fontSize + "px Sans", - platformColor.blockText); - break; - case "newnote": - that.collapseText = new createjs.Text( - _("note value"), fontSize + "px Sans", - platformColor.blockText); - break; - case "interval": - that.collapseText = new createjs.Text( - _("scalar interval"), fontSize + "px Sans", - platformColor.blockText); - break; - case "osctime": - that.collapseText = new createjs.Text( - _("milliseconds"), fontSize + "px Sans", - platformColor.blockText); - break; - case "temperament": - that.collapseText = new createjs.Text( - _("temperament"), fontSize + "px Sans", - platformColor.blockText); - break; - default: - that.collapseText = new createjs.Text( - "foobar", fontSize + "px Sans", - platformColor.blockText); + if (this.blocks.blockList[last(this.connections)].name === "hidden") { + if (last(this.blocks.blockList[last(this.connections)].connections) === null) { + return true; } - - that.collapseText.textAlign = "left"; - that.collapseText.textBaseline = "alphabetic"; - that.container.addChild(that.collapseText); } - that._positionCollapseLabel(that.protoblock.scale); - that.collapseText.visible = that.collapsed; - that._ensureDecorationOnTop(); - - // Save the collapsed block artwork for export. - that.blocks.blockCollapseArt[that.blocks.blockList.indexOf(that)] = - that.collapseArtwork - .replace(/fill_color/g, PALETTEFILLCOLORS[ - that.protoblock.palette.name]) - .replace(/stroke_color/g, PALETTESTROKECOLORS[ - that.protoblock.palette.name]) - .replace("block_label", safeSVG(that.collapseText.text)); - - __processExpandButton(that); + return false; }; /* - * Processing the collapsed block - * @param-bitmap = block artwork - * @param-that = this + * Show this block * @return{void} - * @private + * @public */ - let __processCollapseBitmap = function(bitmap, that) { - that.collapseBlockBitmap = bitmap; - that.collapseBlockBitmap.name = "collapse_" + thisBlock; - that.container.addChild(that.collapseBlockBitmap); - that.collapseBlockBitmap.visible = that.collapsed; - that.blocks.refreshCanvas(); - - let artwork = that.collapseArtwork; - _blockMakeBitmap( - artwork - .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[ - that.protoblock.palette.name]) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ - that.protoblock.palette.name]) - .replace("block_label", ""), - __processHighlightCollapseBitmap, that); - }; - - let artwork = this.collapseArtwork - .replace(/fill_color/g, PALETTEFILLCOLORS[ - this.protoblock.palette.name]) - .replace(/stroke_color/g, PALETTESTROKECOLORS[ - this.protoblock.palette.name]) - .replace("block_label", ""); - _blockMakeBitmap(artwork, __processCollapseBitmap, this); - }; - - /* - * Hide this block - * @return{void} - * @public - */ - this.hide = function() { - this.container.visible = false; - if (this.isCollapsible()) { - this.collapseText.visible = false; - this.expandButtonBitmap.visible = false; - this.collapseButtonBitmap.visible = false; - } - - this.updateCache(); - this.blocks.refreshCanvas(); - }; - - /* - * Is this block disconnected from other blocks? - * @return{boolean} true if the block is disconnected from other blocks - * @public - */ - this.isDisconnected = function() { - if (this.disconnectedBitmap === null) { - return false; - } - - if (this.connections[0] !== null) { - return false; - } - - if (COLLAPSIBLES.indexOf(this.name) !== -1) { - if (INLINECOLLAPSIBLES.indexOf(this.name) === -1) { - return false; - } - } - - if (this.isArgBlock()) { - return true; - } - - if (last(this.connections) === null) { - return true; - } + this.show = function () { + // If it is not in the trash and not in collapsed, then show it. + if (!this.trash && !this.inCollapsed) { + this.container.visible = true; + if (this.isCollapsible()) { + if (this.collapsed) { + this.bitmap.visible = false; + this.highlightBitmap.visible = false; + this.collapseBlockBitmap.visible = true; + this.highlightCollapseBlockBitmap.visible = false; + this.collapseText.visible = true; + this.expandButtonBitmap.visible = true; + this.collapseButtonBitmap.visible = false; + if (this.disconnectedBitmap !== null) { + this.disconnectedBitmap.visible = false; + } - if (this.blocks.blockList[last(this.connections)].name === "hidden") { - if (last(this.blocks.blockList[ - last(this.connections)].connections) === null) { - return true; - } - } + if (this.disconnectedHighlightBitmap !== null) { + this.disconnectedHighlightBitmap.visible = false; + } + } else { + // If the block is disconnected, use the + // disconnected bitmap. + if (this.isDisconnected()) { + this.disconnectedBitmap.visible = true; + this.bitmap.visible = false; + } else { + if (this.disconnectedBitmap !== null) { + this.disconnectedBitmap.visible = false; + } - return false; - }; + this.bitmap.visible = true; + } - /* - * Show this block - * @return{void} - * @public - */ - this.show = function() { - // If it is not in the trash and not in collapsed, then show it. - if (!this.trash && !this.inCollapsed) { - this.container.visible = true; - if (this.isCollapsible()) { - if (this.collapsed) { - this.bitmap.visible = false; - this.highlightBitmap.visible = false; - this.collapseBlockBitmap.visible = true; - this.highlightCollapseBlockBitmap.visible = false; - this.collapseText.visible = true; - this.expandButtonBitmap.visible = true; - this.collapseButtonBitmap.visible = false; - if (this.disconnectedBitmap !== null) { - this.disconnectedBitmap.visible = false; - } + this.highlightBitmap.visible = false; + if (this.disconnectedHighlightBitmap !== null) { + this.disconnectedHighlightBitmap.visible = false; + } - if (this.disconnectedHighlightBitmap !== null) { - this.disconnectedHighlightBitmap.visible = false; + this.collapseBlockBitmap.visible = false; + this.highlightCollapseBlockBitmap.visible = false; + this.collapseText.visible = false; + this.expandButtonBitmap.visible = false; + this.collapseButtonBitmap.visible = true; } } else { - // If the block is disconnected, use the - // disconnected bitmap. + // If the block is disconnected, use the disconnected bitmap. if (this.isDisconnected()) { this.disconnectedBitmap.visible = true; this.bitmap.visible = false; @@ -1599,370 +1611,390 @@ function Block(protoblock, blocks, overrideName) { if (this.disconnectedHighlightBitmap !== null) { this.disconnectedHighlightBitmap.visible = false; } - - this.collapseBlockBitmap.visible = false; - this.highlightCollapseBlockBitmap.visible = false; - this.collapseText.visible = false; - this.expandButtonBitmap.visible = false; - this.collapseButtonBitmap.visible = true; - } - } else { - // If the block is disconnected, use the disconnected bitmap. - if (this.isDisconnected()) { - this.disconnectedBitmap.visible = true; - this.bitmap.visible = false; - } else { - if (this.disconnectedBitmap !== null) { - this.disconnectedBitmap.visible = false; - } - - this.bitmap.visible = true; } - this.highlightBitmap.visible = false; - if (this.disconnectedHighlightBitmap !== null) { - this.disconnectedHighlightBitmap.visible = false; - } + this.updateCache(); + this.blocks.refreshCanvas(); } + }; - this.updateCache(); - this.blocks.refreshCanvas(); - } - }; - - // Utility functions - this.isValueBlock = function() { - return this.protoblock.style === "value"; - }; + // Utility functions + this.isValueBlock = function () { + return this.protoblock.style === "value"; + }; - this.isNoHitBlock = function() { - return NOHIT.indexOf(this.name) !== -1; - }; + this.isNoHitBlock = function () { + return NOHIT.indexOf(this.name) !== -1; + }; - this.isArgBlock = function() { - return (this.protoblock.style === "value" || + this.isArgBlock = function () { + return (this.protoblock.style === "value" || this.protoblock.style === "arg"); - }; + }; - this.isTwoArgBlock = function() { - return this.protoblock.style === "twoarg"; - }; + this.isTwoArgBlock = function () { + return this.protoblock.style === "twoarg"; + }; - this.isTwoArgBooleanBlock = function() { - return ["equal", "greater", "less"].indexOf(this.name) !== -1; - }; + this.isTwoArgBooleanBlock = function () { + return ["equal", "greater", "less"].indexOf(this.name) !== -1; + }; - this.isClampBlock = function() { - return (this.protoblock.style === "clamp" || + this.isClampBlock = function () { + return (this.protoblock.style === "clamp" || this.isDoubleClampBlock() || this.isArgFlowClampBlock()); - }; + }; - this.isArgFlowClampBlock = function() { - return this.protoblock.style === "argflowclamp"; - }; + this.isArgFlowClampBlock = function () { + return this.protoblock.style === "argflowclamp"; + }; - this.isLeftClampBlock = function() { - return this.protoblock.isLeftClamp; - }; + this.isLeftClampBlock = function () { + return this.protoblock.isLeftClamp; + }; - this.isDoubleClampBlock = function() { - return this.protoblock.style === "doubleclamp"; - }; + this.isDoubleClampBlock = function () { + return this.protoblock.style === "doubleclamp"; + }; - this.isNoRunBlock = function() { - return this.name === "action"; - }; + this.isNoRunBlock = function () { + return this.name === "action"; + }; - this.isArgClamp = function() { - return (this.protoblock.style === "argclamp" || + this.isArgClamp = function () { + return (this.protoblock.style === "argclamp" || this.protoblock.style === "argclamparg"); - }; + }; - this.isExpandableBlock = function() { - return this.protoblock.expandable; - }; + this.isExpandableBlock = function () { + return this.protoblock.expandable; + }; - this.getBlockId = function() { - // Generate a UID based on the block index into the blockList. - let number = blockBlocks.blockList.indexOf(this); - return "_" + number.toString(); - }; + this.getBlockId = function () { + // Generate a UID based on the block index into the blockList. + let number = blockBlocks.blockList.indexOf(this); + return "_" + number.toString(); + }; - this.removeChildBitmap = function(name) { - for (let child = 0; child < this.container.children.length; child++) { - if (this.container.children[child].name === name) { - this.container.removeChild(this.container.children[child]); - break; + this.removeChildBitmap = function (name) { + for (let child = 0; child < this.container.children.length; child++) { + if (this.container.children[child].name === name) { + this.container.removeChild(this.container.children[child]); + break; + } } - } - }; + }; - this.loadThumbnail = function(imagePath) { - // Load an image thumbnail onto block. - let thisBlock = this.blocks.blockList.indexOf(this); - let that = this; + this.loadThumbnail = function (imagePath) { + // Load an image thumbnail onto block. + let thisBlock = this.blocks.blockList.indexOf(this); + let that = this; - if (this.blocks.blockList[thisBlock].value === null && - imagePath === null) { - return; - } - let image = new Image(); + if (this.blocks.blockList[thisBlock].value === null && + imagePath === null) { + return; + } + let image = new Image(); - image.onload = function() { - // Before adding new artwork, remove any old artwork. - // that.removeChildBitmap("media"); + image.onload = function () { + // Before adding new artwork, remove any old artwork. + // that.removeChildBitmap("media"); + let bitmap = new createjs.Bitmap(image); + bitmap.name = "media"; + + let myContainer = new createjs.Container(); + myContainer.addChild(bitmap); + + // Resize the image to a reasonable maximum. + let MAXWIDTH = 600; + let MAXHEIGHT = 450; + if (image.width > image.height) { + if (image.width > MAXWIDTH) { + bitmap.scaleX = bitmap.scaleY = bitmap.scale = + MAXWIDTH / image.width; + } + } else { + if (image.height > MAXHEIGHT) { + bitmap.scaleX = bitmap.scaleY = bitmap.scale = + MAXHEIGHT / image.height; + } + } - let bitmap = new createjs.Bitmap(image); - bitmap.name = "media"; + let bounds = myContainer.getBounds(); + myContainer.cache(bounds.x, bounds.y, bounds.width, bounds.height); + that.value = myContainer.bitmapCache.getCacheDataURL(); + that.imageBitmap = bitmap; - let myContainer = new createjs.Container(); - myContainer.addChild(bitmap); + // Next, scale the bitmap for the thumbnail. + that._positionMedia(bitmap, bitmap.image.width, bitmap.image.height, + that.protoblock.scale); + that.container.addChild(bitmap); + that.updateCache(); + }; - // Resize the image to a reasonable maximum. - let MAXWIDTH = 600; - let MAXHEIGHT = 450; - if (image.width > image.height) { - if (image.width > MAXWIDTH) { - bitmap.scaleX = bitmap.scaleY = bitmap.scale = - MAXWIDTH / image.width; - } + if (imagePath === null) { + image.src = this.value; } else { - if (image.height > MAXHEIGHT) { - bitmap.scaleX = bitmap.scaleY = bitmap.scale = - MAXHEIGHT / image.height; - } + image.src = imagePath; } - - let bounds = myContainer.getBounds(); - myContainer.cache(bounds.x, bounds.y, bounds.width, bounds.height); - that.value = myContainer.bitmapCache.getCacheDataURL(); - that.imageBitmap = bitmap; - - // Next, scale the bitmap for the thumbnail. - that._positionMedia(bitmap, bitmap.image.width, bitmap.image.height, - that.protoblock.scale); - that.container.addChild(bitmap); - that.updateCache(); }; - if (imagePath === null) { - image.src = this.value; - } else { - image.src = imagePath; - } - }; - - this._doOpenMedia = function(thisBlock) { - let fileChooser = docById("myOpenAll"); - let that = this; + this._doOpenMedia = function (thisBlock) { + let fileChooser = docById("myOpenAll"); + let that = this; - let __readerAction = function(event) { - window.scroll(0, 0); + let __readerAction = function (event) { + window.scroll(0, 0); - let reader = new FileReader(); - reader.onloadend = function() { - if (reader.result) { - if (that.name === "media") { - that.value = reader.result; - that.loadThumbnail(null); - return; + let reader = new FileReader(); + reader.onloadend = function () { + if (reader.result) { + if (that.name === "media") { + that.value = reader.result; + that.loadThumbnail(null); + return; + } + that.value = [fileChooser.files[0].name, reader.result]; + that.blocks.updateBlockText(thisBlock); } - that.value = [fileChooser.files[0].name, reader.result]; - that.blocks.updateBlockText(thisBlock); + }; + if (that.name === "media") { + reader.readAsDataURL(fileChooser.files[0]); + } else { + reader.readAsText(fileChooser.files[0]); } + fileChooser.removeEventListener("change", __readerAction); }; - if (that.name === "media") { - reader.readAsDataURL(fileChooser.files[0]); - } else { - reader.readAsText(fileChooser.files[0]); - } - fileChooser.removeEventListener("change", __readerAction); - }; - fileChooser.addEventListener("change", __readerAction, false); - fileChooser.focus(); - fileChooser.click(); - window.scroll(0, 0); - }; + fileChooser.addEventListener("change", __readerAction, false); + fileChooser.focus(); + fileChooser.click(); + window.scroll(0, 0); + }; - this.setCollapsedState = function() { - // Mark it as in a collapsed block and hide it. - this.inCollapsed = true; - this.hide(); - }; + this.setCollapsedState = function () { + // Mark it as in a collapsed block and hide it. + this.inCollapsed = true; + this.hide(); + }; - this.setUncollapsedState = function(nblk) { - // It could be a block inside a note block, which may or may - // not be hidden depending on the collapsed state of the - // containing note block. - if (nblk === null) { - this.inCollapsed = false; - this.show(); - } else { - // if we are inside of a collapsed note block, do nothing. - if (this.blocks.blockList[nblk].collapsed) { - } else { + this.setUncollapsedState = function (nblk) { + // It could be a block inside a note block, which may or may + // not be hidden depending on the collapsed state of the + // containing note block. + if (nblk === null) { this.inCollapsed = false; this.show(); + } else { + // if we are inside of a collapsed note block, do nothing. + if (this.blocks.blockList[nblk].collapsed) { + } else { + this.inCollapsed = false; + this.show(); + } } - } - }; + }; - this.collapseToggle = function() { - // Find the blocks to collapse/expand inside of a collapable - // block. - let thisBlock = this.blocks.blockList.indexOf(this); - this.blocks.findDragGroup(thisBlock); + this.collapseToggle = function () { + // Find the blocks to collapse/expand inside of a collapable + // block. + let thisBlock = this.blocks.blockList.indexOf(this); + this.blocks.findDragGroup(thisBlock); - if (this.collapseBlockBitmap === null) { - console.debug("collapse bitmap not ready"); - return; - } + if (this.collapseBlockBitmap === null) { + console.debug("collapse bitmap not ready"); + return; + } - // Remember the current state. - let isCollapsed = this.collapsed; - // Toggle the state. - this.collapsed = !isCollapsed; + // Remember the current state. + let isCollapsed = this.collapsed; + // Toggle the state. + this.collapsed = !isCollapsed; - // These are the buttons to collapse/expand the stack. - this.collapseButtonBitmap.visible = isCollapsed; - this.expandButtonBitmap.visible = !isCollapsed; + // These are the buttons to collapse/expand the stack. + this.collapseButtonBitmap.visible = isCollapsed; + this.expandButtonBitmap.visible = !isCollapsed; - // These are the collpase-state bitmaps. - this.collapseBlockBitmap.visible = !isCollapsed; - this.highlightCollapseBlockBitmap.visible = false; - this.collapseText.visible = !isCollapsed; + // These are the collpase-state bitmaps. + this.collapseBlockBitmap.visible = !isCollapsed; + this.highlightCollapseBlockBitmap.visible = false; + this.collapseText.visible = !isCollapsed; - if (this.isInlineCollapsible() && this.collapseText.visible) { - switch (this.name) { - case "newnote": - this._newNoteLabel(); - break; - case "interval": - this._intervalLabel(); - break; - case "osctime": - this._oscTimeLabel(); - break; - default: - console.debug("What do we do with a collapsed " + this.name + - " block?"); - break; + if (this.isInlineCollapsible() && this.collapseText.visible) { + switch (this.name) { + case "newnote": + this._newNoteLabel(); + break; + case "interval": + this._intervalLabel(); + break; + case "osctime": + this._oscTimeLabel(); + break; + default: + console.debug("What do we do with a collapsed " + this.name + + " block?"); + break; + } } - } - this.bitmap.visible = this.collapsed; - this.highlightBitmap.visible = false; - if (this.disconnectedBitmap !== null) { - this.disconnectedBitmap.visible = false; - } + this.bitmap.visible = this.collapsed; + this.highlightBitmap.visible = false; + if (this.disconnectedBitmap !== null) { + this.disconnectedBitmap.visible = false; + } - if (this.disconnectedHighlightBitmap !== null) { - this.disconnectedHighlightBitmap.visible = false; - } + if (this.disconnectedHighlightBitmap !== null) { + this.disconnectedHighlightBitmap.visible = false; + } + + this.updateCache(); - this.updateCache(); + if (this.name === "action") { + // Label the collapsed block with the action label. + if (this.connections[1] !== null) { + let text = this.blocks.blockList[this.connections[1]].value; + if (getTextWidth(text, "bold 20pt Sans") > TEXTWIDTH) { + text = text.substr(0, STRINGLEN) + "..."; + } - if (this.name === "action") { - // Label the collapsed block with the action label. - if (this.connections[1] !== null) { - let text = this.blocks.blockList[this.connections[1]].value; - if (getTextWidth(text, "bold 20pt Sans") > TEXTWIDTH) { - text = text.substr(0, STRINGLEN) + "..."; + this.collapseText.text = text; + } else { + this.collapseText.text = ""; } - - this.collapseText.text = text; - } else { - this.collapseText.text = ""; } - } - // Make sure the text is on top. - this.container.setChildIndex(this.collapseText, - this.container.children.length - 1); - - if (this.isInlineCollapsible()) { - // Only collapse the contents of the note block. - this._toggle_inline(thisBlock, isCollapsed); - } else { - // Set collapsed state of all of the blocks in the drag group. - if (this.blocks.dragGroup.length > 0) { - for (let b = 1; b < this.blocks.dragGroup.length; b++) { - let blk = this.blocks.dragGroup[b]; - if (this.collapsed) { - // if (this.blocks.blockList[blk].inCollapsed) { - this.blocks.blockList[blk].setCollapsedState(); - } else { - this.blocks.blockList[blk].setUncollapsedState( - this.blocks.insideInlineCollapsibleBlock(blk) - ); + // Make sure the text is on top. + this.container.setChildIndex(this.collapseText, + this.container.children.length - 1); + + if (this.isInlineCollapsible()) { + // Only collapse the contents of the note block. + this._toggle_inline(thisBlock, isCollapsed); + } else { + // Set collapsed state of all of the blocks in the drag group. + if (this.blocks.dragGroup.length > 0) { + for (let b = 1; b < this.blocks.dragGroup.length; b++) { + let blk = this.blocks.dragGroup[b]; + if (this.collapsed) { + // if (this.blocks.blockList[blk].inCollapsed) { + this.blocks.blockList[blk].setCollapsedState(); + } else { + this.blocks.blockList[blk].setUncollapsedState( + this.blocks.insideInlineCollapsibleBlock(blk) + ); + } } } } - } - - this.updateCache(); - this.unhighlight(); - this.blocks.refreshCanvas(); - }; - this._intervalLabel = function() { - // Find pitch and value to display on the collapsed interval - // block. - let degrees = DEGREES.split(" "); - let intervalLabels = {}; - for (let i = 0; i < degrees.length; i++) { - intervalLabels[i] = degrees[i]; - } + this.updateCache(); + this.unhighlight(); + this.blocks.refreshCanvas(); + }; - let intervals = []; - let i = 0; - - let c = this.blocks.blockList.indexOf(this), lastIntervalBlock; - while (c !== null) { - lastIntervalBlock = c; - let n = this.blocks.blockList[c].connections[1]; - let cblock = this.blocks.blockList[n]; - if (cblock.name === "number") { - if (Math.abs(cblock.value) in intervalLabels) { - if (cblock.value < 0) { - intervals.push("-" + intervalLabels[-cblock.value]); + this._intervalLabel = function () { + // Find pitch and value to display on the collapsed interval + // block. + let degrees = DEGREES.split(" "); + let intervalLabels = {}; + for (let i = 0; i < degrees.length; i++) { + intervalLabels[i] = degrees[i]; + } + + let intervals = []; + let i = 0; + + let c = this.blocks.blockList.indexOf(this), lastIntervalBlock; + while (c !== null) { + lastIntervalBlock = c; + let n = this.blocks.blockList[c].connections[1]; + let cblock = this.blocks.blockList[n]; + if (cblock.name === "number") { + if (Math.abs(cblock.value) in intervalLabels) { + if (cblock.value < 0) { + intervals.push("-" + intervalLabels[-cblock.value]); + } else { + intervals.push("+" + intervalLabels[cblock.value]); + } } else { - intervals.push("+" + intervalLabels[cblock.value]); + if (cblock.value < 0) { + intervals.push("-" + cblock.value); + } else { + intervals.push("+" + cblock.value); + } } } else { - if (cblock.value < 0) { - intervals.push("-" + cblock.value); - } else { - intervals.push("+" + cblock.value); - } + intervals.push(""); } - } else { - intervals.push(""); + + i += 1; + if (i > 5) { + console.debug("loop?"); + break; + } + + c = this.blocks.findNestedIntervalBlock( + this.blocks.blockList[c].connections[2] + ); } - i += 1; - if (i > 5) { - console.debug("loop?"); - break; + let itext = ""; + for (let i = intervals.length; i > 0; i--) { + itext += " " + intervals[i - 1]; } - c = this.blocks.findNestedIntervalBlock( - this.blocks.blockList[c].connections[2] - ); - } + let v = ""; + let nblk = this.blocks.findNoteBlock(lastIntervalBlock); + if (nblk === null) { + this.collapseText.text = _("scalar interval") + itext; + } else { + c = this.blocks.blockList[nblk].connections[1]; + if (c !== null) { + // Only look for standard form: / 1 4 + if (this.blocks.blockList[c].name === "divide") { + let c1 = this.blocks.blockList[c].connections[1]; + let c2 = this.blocks.blockList[c].connections[2]; + if (this.blocks.blockList[c1].name === "number" && + this.blocks.blockList[c2].name === "number") { + v = this.blocks.blockList[c1].value + "/" + + this.blocks.blockList[c2].value; + if (_THIS_IS_MUSIC_BLOCKS_) { + if (this.blocks.blockList[c2].value in NSYMBOLS) { + v += NSYMBOLS[this.blocks.blockList[c2].value]; + } + } + } + } + } - let itext = ""; - for (let i = intervals.length; i > 0; i--) { - itext += " " + intervals[i - 1]; - } + c = this.blocks.findFirstPitchBlock( + this.blocks.blockList[nblk].connections[2] + ); + let p = this._getPitch(c); + if (c === null || p === "") { + this.collapseText.text = _("scalar interval") + itext; + } else { + // Are there more pitch blocks in this note? + c = this.blocks.findFirstPitchBlock( + last(this.blocks.blockList[c].connections) + ); + // Update the collapsed-block label. + if (c === null) { + this.collapseText.text = p + " | " + v + itext; + } else { + this.collapseText.text = p + "..." + " | " + v + itext; + } + } + } + }; - let v = ""; - let nblk = this.blocks.findNoteBlock(lastIntervalBlock); - if (nblk === null) { - this.collapseText.text = _("scalar interval") + itext; - } else { - c = this.blocks.blockList[nblk].connections[1]; + this._newNoteLabel = function () { + // Find pitch and value to display on the collapsed note value + // block. + let v = ""; + let c = this.connections[1]; + let vi = null; if (c !== null) { // Only look for standard form: / 1 4 if (this.blocks.blockList[c].name === "divide") { @@ -1973,541 +2005,513 @@ function Block(protoblock, blocks, overrideName) { v = this.blocks.blockList[c1].value + "/" + this.blocks.blockList[c2].value; if (_THIS_IS_MUSIC_BLOCKS_) { - if (this.blocks.blockList[c2].value in NSYMBOLS) { - v += NSYMBOLS[this.blocks.blockList[c2].value]; + vi = this.blocks.blockList[c2].value; + if (vi in NSYMBOLS) { + v += NSYMBOLS[vi]; } } } } } - c = this.blocks.findFirstPitchBlock( - this.blocks.blockList[nblk].connections[2] - ); + c = this.connections[2]; + c = this.blocks.findFirstPitchBlock(c); let p = this._getPitch(c); - if (c === null || p === "") { - this.collapseText.text = _("scalar interval") + itext; + if (c === null) { + if (_THIS_IS_MUSIC_BLOCKS_) { + if (vi !== null) { + if (vi in NSYMBOLS) { + v = v.replace(NSYMBOLS[vi], RSYMBOLS[vi]); + } + } + } + this.collapseText.text = _("silence") + " | " + v; + } else if (p === "" && v === "") { + this.collapseText.text = _("note value"); } else { - // Are there more pitch blocks in this note? + if (_THIS_IS_MUSIC_BLOCKS_ && p === _("silence")) { + if (vi !== null) { + if (vi in NSYMBOLS) { + v = v.replace(NSYMBOLS[vi], RSYMBOLS[vi]); + } + } + } + + // are there more pitch blocks in this note? c = this.blocks.findFirstPitchBlock( last(this.blocks.blockList[c].connections) ); // Update the collapsed-block label. if (c === null) { - this.collapseText.text = p + " | " + v + itext; + this.collapseText.text = p + " | " + v; } else { - this.collapseText.text = p + "..." + " | " + v + itext; + this.collapseText.text = p + "... | " + v; } } - } - }; + }; - this._newNoteLabel = function() { - // Find pitch and value to display on the collapsed note value - // block. - let v = ""; - let c = this.connections[1]; - let vi = null; - if (c !== null) { - // Only look for standard form: / 1 4 - if (this.blocks.blockList[c].name === "divide") { - let c1 = this.blocks.blockList[c].connections[1]; - let c2 = this.blocks.blockList[c].connections[2]; - if (this.blocks.blockList[c1].name === "number" && - this.blocks.blockList[c2].name === "number") { - v = this.blocks.blockList[c1].value + "/" + - this.blocks.blockList[c2].value; - if (_THIS_IS_MUSIC_BLOCKS_) { - vi = this.blocks.blockList[c2].value; - if (vi in NSYMBOLS) { - v += NSYMBOLS[vi]; + this._oscTimeLabel = function () { + // Find Hertz and value to display on the collapsed note value + // block. + let v = ""; + let c = this.connections[1]; + if (c !== null) { + // Only look for standard form: / 1000 / 3 2 + if (this.blocks.blockList[c].name === "divide") { + let c1 = this.blocks.blockList[c].connections[1]; + let c2 = this.blocks.blockList[c].connections[2]; + if (c1 !== null && + c2 !== null && + this.blocks.blockList[c2].name === "divide") { + let ci = this.blocks.blockList[c2].connections[1]; + let cii = this.blocks.blockList[c2].connections[2]; + if (ci !== null && + cii !== null && + this.blocks.blockList[ci].name === "number" && + this.blocks.blockList[cii].name === "number") { + v = (this.blocks.blockList[c1].value / + this.blocks.blockList[ci].value) * + this.blocks.blockList[cii].value; } } } } - } - c = this.connections[2]; - c = this.blocks.findFirstPitchBlock(c); - let p = this._getPitch(c); - if (c === null) { - if (_THIS_IS_MUSIC_BLOCKS_) { - if (vi !== null) { - if (vi in NSYMBOLS) { - v = v.replace(NSYMBOLS[vi], RSYMBOLS[vi]); - } - } - } - this.collapseText.text = _("silence") + " | " + v; - } else if (p === "" && v === "") { - this.collapseText.text = _("note value"); - } else { - if (_THIS_IS_MUSIC_BLOCKS_ && p === _("silence")) { - if (vi !== null) { - if (vi in NSYMBOLS) { - v = v.replace(NSYMBOLS[vi], RSYMBOLS[vi]); + c = this.connections[2]; + c = this.blocks.findFirstPitchBlock(c); + let p = this._getPitch(c); + if (c === null) { + this.collapseText.text = _("silence") + " | " + v; + } else if (p === "" && v === "") { + this.collapseText.text = _("note value"); + } else { + // Are there more pitch blocks in this note? + c = this.blocks.findFirstPitchBlock( + last(this.blocks.blockList[c].connections) + ); + // Update the collapsed-block label. + if (v !== "") { + if (c === null) { + this.collapseText.text = p + " | " + v.toFixed(0); + } else { + this.collapseText.text = p + "... | " + v.toFixed(0); } + } else { + this.collapseText.text = p + "..."; } } + }; - // are there more pitch blocks in this note? - c = this.blocks.findFirstPitchBlock( - last(this.blocks.blockList[c].connections) - ); - // Update the collapsed-block label. + this._getPitch = function (c) { if (c === null) { - this.collapseText.text = p + " | " + v; - } else { - this.collapseText.text = p + "... | " + v; + return ""; } - } - }; - this._oscTimeLabel = function() { - // Find Hertz and value to display on the collapsed note value - // block. - let v = ""; - let c = this.connections[1]; - if (c !== null) { - // Only look for standard form: / 1000 / 3 2 - if (this.blocks.blockList[c].name === "divide") { - let c1 = this.blocks.blockList[c].connections[1]; - let c2 = this.blocks.blockList[c].connections[2]; - if ( - c1 !== null && - c2 !== null && - this.blocks.blockList[c2].name === "divide" - ) { - let ci = this.blocks.blockList[c2].connections[1]; - let cii = this.blocks.blockList[c2].connections[2]; - if ( - ci !== null && - cii !== null && - this.blocks.blockList[ci].name === "number" && - this.blocks.blockList[cii].name === "number" - ) { - v = (this.blocks.blockList[c1].value / - this.blocks.blockList[ci].value) * - this.blocks.blockList[cii].value; + let c1, c2; + switch (this.blocks.blockList[c].name) { + case "pitch": + c1 = this.blocks.blockList[c].connections[1]; + c2 = this.blocks.blockList[c].connections[2]; + if (this.blocks.blockList[c2].name === "number") { + if (this.blocks.blockList[c1].name === "solfege") { + let solfnotes_ = _("ti la sol fa mi re do").split(" "); + let stripped = this.blocks.blockList[c1].value + .replace(SHARP, "") + .replace(FLAT, "") + .replace(DOUBLESHARP, "") + .replace(DOUBLEFLAT, ""); + let i = ["ti", "la", "sol", "fa", "mi", "re", + "do"].indexOf(stripped); + if (this.blocks.blockList[c1].value.indexOf(SHARP) !== -1) { + return (solfnotes_[i] + SHARP + " " + + this.blocks.blockList[c2].value); + } else if (this.blocks.blockList[c1].value.indexOf(FLAT) + !== -1) { + return (solfnotes_[i] + FLAT + " " + + this.blocks.blockList[c2].value); + } else if (this.blocks.blockList[c1].value.indexOf( + DOUBLESHARP) !== -1) { + return (solfnotes_[i] + DOUBLESHARP + " " + + this.blocks.blockList[c2].value); + } else if (this.blocks.blockList[c1].value.indexOf( + DOUBLEFLAT) !== -1) { + return (solfnotes_[i] + DOUBLEFLAT + " " + + this.blocks.blockList[c2].value); + } else { + return (solfnotes_[i] + " " + + this.blocks.blockList[c2].value); + } + } else if (this.blocks.blockList[c1].name === "notename") { + return (this.blocks.blockList[c1].value + " " + + this.blocks.blockList[c2].value); + } else if (this.blocks.blockList[c1].name === "scaledegree2") { + obj = splitScaleDegree(this.blocks.blockList[c1].value); + let note = obj[0]; + if (obj[1] !== NATURAL) { + note += obj[1]; + } + return (note + " " + this.blocks.blockList[c2].value); + } } - } + break; + case "nthmodalpitch": + c1 = this.blocks.blockList[c].connections[1]; + c2 = this.blocks.blockList[c].connections[2]; + if (this.blocks.blockList[c2].name === "number") { + if (this.blocks.blockList[c1].name === "number") { + let degrees = DEGREES.split(" "); + let i = this.blocks.blockList[c1].value - 1; + if (i > 0 && i < degrees.length) { + return (degrees[i] + " " + + this.blocks.blockList[c2].value); + } else { + return (this.blocks.blockList[c1].value + " " + + this.blocks.blockList[c2].value); + } + } + } + break; + case "hertz": + c1 = this.blocks.blockList[c].connections[0]; + if (this.blocks.blockList[c1].name === "number") { + return this.blocks.blockList[c1].value + "HZ"; + } + break; + case "steppitch": + c1 = this.blocks.blockList[c].connections[1]; + if (this.blocks.blockList[c1].name === "number" && + this.blocks.blockList[c1].value < 0) { + //.TRANS: scalar step + return (_("down") + " " + Math.abs( + this.blocks.blockList[c1].value)); + } else + return _("up") + " " + this.blocks.blockList[c1].value; + break; + case "pitchnumber": + c1 = this.blocks.blockList[c].connections[1]; + if (this.blocks.blockList[c1].name === "number") { + //.TRANS: pitch number + return _("pitch") + " " + this.blocks.blockList[c1].value; + } + break; + case "playdrum": + return _("drum"); + break; + case "rest2": + return _("silence"); + break; + default: + return ""; } - } + }; - c = this.connections[2]; - c = this.blocks.findFirstPitchBlock(c); - let p = this._getPitch(c); - if (c === null) { - this.collapseText.text = _("silence") + " | " + v; - } else if (p === "" && v === "") { - this.collapseText.text = _("note value"); - } else { - // Are there more pitch blocks in this note? - c = this.blocks.findFirstPitchBlock( - last(this.blocks.blockList[c].connections) - ); - // Update the collapsed-block label. - if (v !== "") { - if (c === null) { - this.collapseText.text = p + " | " + v.toFixed(0); - } else { - this.collapseText.text = p + "... | " + v.toFixed(0); + this._toggle_inline = function (thisBlock, collapse) { + // Toggle the collapsed state of blocks inside of a note (or + // interval) block and reposition any blocks below + // it. Finally, resize any surrounding clamps. + // Set collapsed state of note value arg blocks... + if (this.connections[1] !== null) { + this.blocks.findDragGroup(this.connections[1]); + for (let b = 0; b < this.blocks.dragGroup.length; b++) { + let blk = this.blocks.dragGroup[b]; + this.blocks.blockList[blk].container.visible = collapse; + if (collapse) { + this.blocks.blockList[blk].inCollapsed = false; + } else { + this.blocks.blockList[blk].inCollapsed = true; + } } - } else { - this.collapseText.text = p + "..."; } - } - }; - this._getPitch = function(c) { - if (c === null) { - return ""; - } - - let c1, c2; - switch (this.blocks.blockList[c].name) { - case "pitch": - c1 = this.blocks.blockList[c].connections[1]; - c2 = this.blocks.blockList[c].connections[2]; - if (this.blocks.blockList[c2].name === "number") { - if (this.blocks.blockList[c1].name === "solfege") { - let solfnotes_ = _("ti la sol fa mi re do").split(" "); - let stripped = this.blocks.blockList[c1].value - .replace(SHARP, "") - .replace(FLAT, "") - .replace(DOUBLESHARP, "") - .replace(DOUBLEFLAT, ""); - let i = ["ti", "la", "sol", "fa", "mi", "re", - "do"].indexOf(stripped); - if (this.blocks.blockList[c1].value.indexOf(SHARP) !== -1) { - return (solfnotes_[i] + SHARP + " " + - this.blocks.blockList[c2].value); - } else if (this.blocks.blockList[c1].value.indexOf(FLAT) - !== -1) { - return (solfnotes_[i] + FLAT + " " + - this.blocks.blockList[c2].value); - } else if (this.blocks.blockList[c1].value.indexOf( - DOUBLESHARP) !== -1) { - return (solfnotes_[i] + DOUBLESHARP + " " + - this.blocks.blockList[c2].value); - } else if (this.blocks.blockList[c1].value.indexOf( - DOUBLEFLAT) !== -1) { - return (solfnotes_[i] + DOUBLEFLAT + " " + - this.blocks.blockList[c2].value); - } else { - return (solfnotes_[i] + " " + - this.blocks.blockList[c2].value); - } - } else if (this.blocks.blockList[c1].name === "notename") { - return (this.blocks.blockList[c1].value + " " + - this.blocks.blockList[c2].value); - } else if (this.blocks.blockList[c1].name === "scaledegree2") { - obj = splitScaleDegree(this.blocks.blockList[c1].value); - let note = obj[0]; - if (obj[1] !== NATURAL) { - note += obj[1]; - } - return (note + " " + this.blocks.blockList[c2].value); - } - } - break; - case "nthmodalpitch": - c1 = this.blocks.blockList[c].connections[1]; - c2 = this.blocks.blockList[c].connections[2]; - if (this.blocks.blockList[c2].name === "number") { - if (this.blocks.blockList[c1].name === "number") { - let degrees = DEGREES.split(" "); - let i = this.blocks.blockList[c1].value - 1; - if (i > 0 && i < degrees.length) { - return (degrees[i] + " " + - this.blocks.blockList[c2].value); + // and the blocks inside the clamp. + if (this.connections[2] !== null) { + this.blocks.findDragGroup(this.connections[2]); + for (let b = 0; b < this.blocks.dragGroup.length; b++) { + let blk = this.blocks.dragGroup[b]; + // Look to see if the local parent block is collapsed. + let parent = this.blocks.insideInlineCollapsibleBlock(blk); + if (parent === null || + !this.blocks.blockList[parent].collapsed) { + this.blocks.blockList[blk].container.visible = collapse; + if (collapse) { + this.blocks.blockList[blk].inCollapsed = false; + } else { + this.blocks.blockList[blk].inCollapsed = true; + } } else { - return (this.blocks.blockList[c1].value + " " + - this.blocks.blockList[c2].value); + // Parent is collapsed, so keep hidden. + this.blocks.blockList[blk].container.visible = false; + this.blocks.blockList[blk].inCollapsed = true; } } } - break; - case "hertz": - c1 = this.blocks.blockList[c].connections[0]; - if (this.blocks.blockList[c1].name === "number") { - return this.blocks.blockList[c1].value + "HZ"; - } - break; - case "steppitch": - c1 = this.blocks.blockList[c].connections[1]; - if (this.blocks.blockList[c1].name === "number" && - this.blocks.blockList[c1].value < 0) { - //.TRANS: scalar step - return (_("down") + " " + Math.abs( - this.blocks.blockList[c1].value)); - } else return _("up") + " " + this.blocks.blockList[c1].value; - break; - case "pitchnumber": - c1 = this.blocks.blockList[c].connections[1]; - if (this.blocks.blockList[c1].name === "number") { - //.TRANS: pitch number - return _("pitch") + " " + this.blocks.blockList[c1].value; - } - break; - case "playdrum": - return _("drum"); - break; - case "rest2": - return _("silence"); - break; - default: - return ""; - } - }; - this._toggle_inline = function(thisBlock, collapse) { - // Toggle the collapsed state of blocks inside of a note (or - // interval) block and reposition any blocks below - // it. Finally, resize any surrounding clamps. - - // Set collapsed state of note value arg blocks... - if (this.connections[1] !== null) { - this.blocks.findDragGroup(this.connections[1]); - for (let b = 0; b < this.blocks.dragGroup.length; b++) { - let blk = this.blocks.dragGroup[b]; - this.blocks.blockList[blk].container.visible = collapse; + // Reposition the blocks below. + if (this.connections[3] != null) { + // The last connection is flow. The second to last + // connection is child flow. FIX ME: This will not work + // if there is more than one arg, e.g. n > 4. + let n = this.docks.length, dy; if (collapse) { - this.blocks.blockList[blk].inCollapsed = false; + dy = this.blocks.blockList[thisBlock].docks[n - 1][1] - + this.blocks.blockList[thisBlock].docks[n - 2][1]; } else { - this.blocks.blockList[blk].inCollapsed = true; + dy = this.blocks.blockList[thisBlock].docks[n - 2][1] - + this.blocks.blockList[thisBlock].docks[n - 1][1]; } - } - } - // and the blocks inside the clamp. - if (this.connections[2] !== null) { - this.blocks.findDragGroup(this.connections[2]); - for (let b = 0; b < this.blocks.dragGroup.length; b++) { - let blk = this.blocks.dragGroup[b]; - // Look to see if the local parent block is collapsed. - let parent = this.blocks.insideInlineCollapsibleBlock(blk); - if (parent === null || - !this.blocks.blockList[parent].collapsed) { - this.blocks.blockList[blk].container.visible = collapse; - if (collapse) { - this.blocks.blockList[blk].inCollapsed = false; - } else { - this.blocks.blockList[blk].inCollapsed = true; - } - } else { - // Parent is collapsed, so keep hidden. - this.blocks.blockList[blk].container.visible = false; - this.blocks.blockList[blk].inCollapsed = true; + this.blocks.findDragGroup(this.connections[3]); + for (let b = 0; b < this.blocks.dragGroup.length; b++) { + this.blocks.moveBlockRelative(this.blocks.dragGroup[b], 0, dy); } - } - } - // Reposition the blocks below. - if (this.connections[3] != null) { - // The last connection is flow. The second to last - // connection is child flow. FIX ME: This will not work - // if there is more than one arg, e.g. n > 4. - let n = this.docks.length, dy; - if (collapse) { - dy = this.blocks.blockList[thisBlock].docks[n - 1][1] - - this.blocks.blockList[thisBlock].docks[n - 2][1]; - } else { - dy = this.blocks.blockList[thisBlock].docks[n - 2][1] - - this.blocks.blockList[thisBlock].docks[n - 1][1]; + this.blocks.adjustDocks(thisBlock, true); } - this.blocks.findDragGroup(this.connections[3]); - for (let b = 0; b < this.blocks.dragGroup.length; b++) { - this.blocks.moveBlockRelative(this.blocks.dragGroup[b], 0, dy); + // Look to see if we are in a clamp block. If so, readjust. + let clampList = []; + this.blocks.findNestedClampBlocks(thisBlock, clampList); + if (clampList.length > 0) { + this.blocks.clampBlocksToCheck = clampList; + this.blocks.adjustExpandableClampBlock(); } - this.blocks.adjustDocks(thisBlock, true); - } + this.blocks.refreshCanvas(); + }; - // Look to see if we are in a clamp block. If so, readjust. - let clampList = []; - this.blocks.findNestedClampBlocks(thisBlock, clampList); - if (clampList.length > 0) { - this.blocks.clampBlocksToCheck = clampList; - this.blocks.adjustExpandableClampBlock(); - } + /* + * Position any addition text on a block + * @param-blockscale is used to scale the text + * @return{void} + * @private + */ + this._positionText = function (blockScale) { + this.text.textBaseline = "alphabetic"; + this.text.textAlign = "right"; + let fontSize = 10 * blockScale; + this.text.font = fontSize + "px Sans"; + this.text.x = Math.floor((TEXTX * blockScale) / 2 + 0.5); + this.text.y = Math.floor((TEXTY * blockScale) / 2 + 0.5); + + // Some special cases + if (SPECIALINPUTS.indexOf(this.name) !== -1) { + this.text.textAlign = "center"; + this.text.x = Math.floor((VALUETEXTX * blockScale) / 2 + 0.5); + if (EXTRAWIDENAMES.indexOf(this.name) !== -1) { + this.text.x *= 3.0; + } else if (WIDENAMES.indexOf(this.name) !== -1) { + this.text.x = Math.floor(this.text.x * 1.75 + 0.5); + } else if (this.name === "text") { + this.text.x = Math.floor(this.width / 2 + 0.5); + } + } else if (this.name === "nameddo") { + this.text.textAlign = "center"; + this.text.x = Math.floor(this.width / 2 + 0.5); + } else if (this.protoblock.args === 0) { + let bounds = this.container.getBounds(); + this.text.x = Math.floor(this.width - 25 + 0.5); + } else if (this.isCollapsible()) { + this.text.x += Math.floor(15 * blockScale); + } else { + this.text.textAlign = "left"; + if (this.docks[0][2] === "booleanout") { + this.text.y = Math.floor(this.docks[0][1] + 0.5); + } + } - this.blocks.refreshCanvas(); - }; + // Ensure text is on top. + let z = this.container.children.length - 1; + this.container.setChildIndex(this.text, z); + this.updateCache(); + }; - /* - * Position any addition text on a block - * @param-blockscale is used to scale the text - * @return{void} - * @private - */ - this._positionText = function(blockScale) { - this.text.textBaseline = "alphabetic"; - this.text.textAlign = "right"; - let fontSize = 10 * blockScale; - this.text.font = fontSize + "px Sans"; - this.text.x = Math.floor((TEXTX * blockScale) / 2 + 0.5); - this.text.y = Math.floor((TEXTY * blockScale) / 2 + 0.5); - - // Some special cases - if (SPECIALINPUTS.indexOf(this.name) !== -1) { - this.text.textAlign = "center"; - this.text.x = Math.floor((VALUETEXTX * blockScale) / 2 + 0.5); - if (EXTRAWIDENAMES.indexOf(this.name) !== -1) { - this.text.x *= 3.0; - } else if (WIDENAMES.indexOf(this.name) !== -1) { - this.text.x = Math.floor(this.text.x * 1.75 + 0.5); - } else if (this.name === "text") { - this.text.x = Math.floor(this.width / 2 + 0.5); + /* + * Position media artwork on a block. + * @param-bitmap - image + * @param-width-width of canvas + * @param-height-height of canvas + * @param-blockscale-scale + * Position inserted media + * @return{void} + * @private + */ + this._positionMedia = function (bitmap, width, height, blockScale) { + if (width > height) { + bitmap.scaleX = bitmap.scaleY = bitmap.scale = + ((MEDIASAFEAREA[2] / width) * blockScale) / 2; + } else { + bitmap.scaleX = bitmap.scaleY = bitmap.scale = + ((MEDIASAFEAREA[3] / height) * blockScale) / 2; } - } else if (this.name === "nameddo") { - this.text.textAlign = "center"; - this.text.x = Math.floor(this.width / 2 + 0.5); - } else if (this.protoblock.args === 0) { - let bounds = this.container.getBounds(); - this.text.x = Math.floor(this.width - 25 + 0.5); - } else if (this.isCollapsible()) { - this.text.x += Math.floor(15 * blockScale); - } else { - this.text.textAlign = "left"; - if (this.docks[0][2] === "booleanout") { - this.text.y = Math.floor(this.docks[0][1] + 0.5); + bitmap.x = ((MEDIASAFEAREA[0] - 10) * blockScale) / 2; + bitmap.y = (MEDIASAFEAREA[1] * blockScale) / 2; + }; + + /* + * Position the label for a collapsed block + * @param-blockscale-scale + * @return{void} + * @private + */ + this._positionCollapseLabel = function (blockScale) { + if (this.isInlineCollapsible()) { + this.collapseText.x = Math.floor( + ((COLLAPSETEXTX + STANDARDBLOCKHEIGHT) * blockScale) / 2 + 0.5 + ); + this.collapseText.y = Math.floor( + ((COLLAPSETEXTY - 8) * blockScale) / 2 + 0.5 + ); + } else { + this.collapseText.x = Math.floor( + ((COLLAPSETEXTX + 30) * blockScale) / 2 + 0.5 + ); + this.collapseText.y = Math.floor( + (COLLAPSETEXTY * blockScale) / 2 + 0.5 + ); } - } - // Ensure text is on top. - z = this.container.children.length - 1; - this.container.setChildIndex(this.text, z); - this.updateCache(); - }; + // Ensure text is on top. + let z = this.container.children.length - 1; + this.container.setChildIndex(this.collapseText, z); + }; - /* - * Position media artwork on a block. - * @param-bitmap - image - * @param-width-width of canvas - * @param-height-height of canvas - * @param-blockscale-scale - * Position inserted media - * @return{void} - * @private - */ - this._positionMedia = function(bitmap, width, height, blockScale) { - if (width > height) { - bitmap.scaleX = bitmap.scaleY = bitmap.scale = - ((MEDIASAFEAREA[2] / width) * blockScale) / 2; - } else { - bitmap.scaleX = bitmap.scaleY = bitmap.scale = - ((MEDIASAFEAREA[3] / height) * blockScale) / 2; - } - bitmap.x = ((MEDIASAFEAREA[0] - 10) * blockScale) / 2; - bitmap.y = (MEDIASAFEAREA[1] * blockScale) / 2; - }; + /* + * Determine the hit area for a block + * DEPRECATED + * @return{void} + * @private + */ + this._calculateBlockHitArea = function () { + let hitArea = new createjs.Shape(); + hitArea.graphics + .beginFill("platformColor.hitAreaGraphicsBeginFill") + .drawRect(0, 0, this.width, this.hitHeight); + this.container.hitArea = hitArea; + }; - /* - * Position the label for a collapsed block - * @param-blockscale-scale - * @return{void} - * @private - */ - this._positionCollapseLabel = function(blockScale) { - if (this.isInlineCollapsible()) { - this.collapseText.x = Math.floor( - ((COLLAPSETEXTX + STANDARDBLOCKHEIGHT) * blockScale) / 2 + 0.5 - ); - this.collapseText.y = Math.floor( - ((COLLAPSETEXTY - 8) * blockScale) / 2 + 0.5 - ); - } else { - this.collapseText.x = Math.floor( - ((COLLAPSETEXTX + 30) * blockScale) / 2 + 0.5 - ); - this.collapseText.y = Math.floor( - (COLLAPSETEXTY * blockScale) / 2 + 0.5 - ); - } + /* + * These are the event handlers for block containers. + * @return{void} + * @private + */ + this._loadEventHandlers = function () { + let that = this; + let thisBlock = this.blocks.blockList.indexOf(this); - // Ensure text is on top. - z = this.container.children.length - 1; - this.container.setChildIndex(this.collapseText, z); - }; + this._calculateBlockHitArea(); - /* - * Determine the hit area for a block - * DEPRECATED - * @return{void} - * @private - */ - this._calculateBlockHitArea = function() { - let hitArea = new createjs.Shape(); - hitArea.graphics - .beginFill("platformColor.hitAreaGraphicsBeginFill") - .drawRect(0, 0, this.width, this.hitHeight); - this.container.hitArea = hitArea; - }; + this.container.on("mouseover", function (event) { + docById("contextWheelDiv").style.display = "none"; - /* - * These are the event handlers for block containers. - * @return{void} - * @private - */ - this._loadEventHandlers = function() { - let that = this; - let thisBlock = this.blocks.blockList.indexOf(this); - - this._calculateBlockHitArea(); - - this.container.on("mouseover", function(event) { - docById("contextWheelDiv").style.display = "none"; - - if (!that.blocks.logo.runningLilypond) { - document.body.style.cursor = "pointer"; - } - - that.blocks.highlight(thisBlock, true); - that.blocks.activeBlock = thisBlock; - // that.blocks.refreshCanvas(); - }); - - let haveClick = false; - let moved = false; - let locked = false; - let getInput = window.hasMouse; - - this.container.on("click", function(event) { - // We might be able to check which button was clicked. - if ("nativeEvent" in event) { - if ("button" in event.nativeEvent && - event.nativeEvent.button == 2) { - that.blocks.stageClick = true; - docById("wheelDiv").style.display = "none"; - piemenuBlockContext(that); - return; - } else if ("ctrlKey" in event.nativeEvent && - event.nativeEvent.ctrlKey) { - piemenuBlockContext(that); - return; - } else if ("shiftKey" in event.nativeEvent && - event.nativeEvent.shiftKey) { - if (that.blocks.turtles.running()) { - that.blocks.logo.doStopTurtles(); + if (!that.blocks.logo.runningLilypond) { + document.body.style.cursor = "pointer"; + } + + that.blocks.highlight(thisBlock, true); + that.blocks.activeBlock = thisBlock; + // that.blocks.refreshCanvas(); + }); + + let haveClick = false; + let moved = false; + let locked = false; + let getInput = window.hasMouse; + + this.container.on("click", function (event) { + // We might be able to check which button was clicked. + if ("nativeEvent" in event) { + if ("button" in event.nativeEvent && + event.nativeEvent.button == 2) { + that.blocks.stageClick = true; + docById("wheelDiv").style.display = "none"; + piemenuBlockContext(that); + return; + } else if ("ctrlKey" in event.nativeEvent && + event.nativeEvent.ctrlKey) { + piemenuBlockContext(that); + return; + } else if ("shiftKey" in event.nativeEvent && + event.nativeEvent.shiftKey) { + if (that.blocks.turtles.running()) { + that.blocks.logo.doStopTurtles(); - setTimeout(function() { + setTimeout(function () { + that.blocks.logo.runLogoCommands(topBlock); + }, 250); + } else { that.blocks.logo.runLogoCommands(topBlock); - }, 250); - } else { - that.blocks.logo.runLogoCommands(topBlock); + } + + return; } + } + if (that.blocks.getLongPressStatus()) { return; } - } - if (that.blocks.getLongPressStatus()) { - return; - } + that.blocks.activeBlock = thisBlock; + haveClick = true; - that.blocks.activeBlock = thisBlock; - haveClick = true; + if (locked) { + return; + } - if (locked) { - return; - } + locked = true; + setTimeout(function () { + locked = false; + }, 500); - locked = true; - setTimeout(function() { - locked = false; - }, 500); + hideDOMLabel(); + that._checkWidgets(false); - hideDOMLabel(); - that._checkWidgets(false); + let topBlk; - let topBlk; + let dx = event.stageX / that.blocks.getStageScale() - that.container.x; + if (!moved && that.isCollapsible() && + dx < (30 / that.blocks.getStageScale())) { + that.collapseToggle(); + } else if ((!window.hasMouse && getInput) || + (window.hasMouse && !moved)) { + if (that.name === "media") { + that._doOpenMedia(thisBlock); + } else if (that.name === "loadFile") { + that._doOpenMedia(thisBlock); + } else if (SPECIALINPUTS.indexOf(that.name) !== -1) { + if (!that.trash) { + if (that._triggerLongPress) { + that._triggerLongPress = false; + } else { + that._changeLabel(); + } + } + } else { + if (!that.blocks.getLongPressStatus() && + !that.blocks.stageClick) { + topBlk = that.blocks.findTopBlock(thisBlock); + console.debug("running from " + + that.blocks.blockList[topBlk].name); + if (_THIS_IS_MUSIC_BLOCKS_) { + that.blocks.logo.synth.resume(); + } - dx = event.stageX / that.blocks.getStageScale() - that.container.x; - if (!moved && that.isCollapsible() && - dx < (30 / that.blocks.getStageScale())) { - that.collapseToggle(); - } else if ((!window.hasMouse && getInput) || - (window.hasMouse && !moved)) { - if (that.name === "media") { - that._doOpenMedia(thisBlock); - } else if (that.name === "loadFile") { - that._doOpenMedia(thisBlock); - } else if (SPECIALINPUTS.indexOf(that.name) !== -1) { - if (!that.trash) { - if (that._triggerLongPress) { - that._triggerLongPress = false; - } else { - that._changeLabel(); + if (that.blocks.turtles.running()) { + that.blocks.logo.doStopTurtles(); + + setTimeout(function () { + that.blocks.logo.runLogoCommands(topBlk); + }, 250); + } else { + that.blocks.logo.runLogoCommands(topBlk); + } } } - } else { + } else if (!moved) { if (!that.blocks.getLongPressStatus() && !that.blocks.stageClick) { topBlk = that.blocks.findTopBlock(thisBlock); console.debug("running from " + - that.blocks.blockList[topBlk].name); + that.blocks.blockList[topBlk].name); if (_THIS_IS_MUSIC_BLOCKS_) { that.blocks.logo.synth.resume(); } @@ -2515,7 +2519,7 @@ function Block(protoblock, blocks, overrideName) { if (that.blocks.turtles.running()) { that.blocks.logo.doStopTurtles(); - setTimeout(function() { + setTimeout(function () { that.blocks.logo.runLogoCommands(topBlk); }, 250); } else { @@ -2523,1065 +2527,1075 @@ function Block(protoblock, blocks, overrideName) { } } } - } else if (!moved) { - if (!that.blocks.getLongPressStatus() && - !that.blocks.stageClick) { - topBlk = that.blocks.findTopBlock(thisBlock); - console.debug("running from " + - that.blocks.blockList[topBlk].name); - if (_THIS_IS_MUSIC_BLOCKS_) { - that.blocks.logo.synth.resume(); - } - - if (that.blocks.turtles.running()) { - that.blocks.logo.doStopTurtles(); - - setTimeout(function() { - that.blocks.logo.runLogoCommands(topBlk); - }, 250); - } else { - that.blocks.logo.runLogoCommands(topBlk); - } - } - } - }); + }); - this.container.on("mousedown", function(event) { - docById("contextWheelDiv").style.display = "none"; + this.container.on("mousedown", function (event) { + docById("contextWheelDiv").style.display = "none"; - // Track time for detecting long pause... - that.blocks.mouseDownTime = new Date().getTime(); + // Track time for detecting long pause... + that.blocks.mouseDownTime = new Date().getTime(); - that.blocks.longPressTimeout = setTimeout(function() { - that.blocks.activeBlock = that.blocks.blockList.indexOf(that); - that._triggerLongPress = true; - that.blocks.triggerLongPress(); - }, LONGPRESSTIME); + that.blocks.longPressTimeout = setTimeout(function () { + that.blocks.activeBlock = that.blocks.blockList.indexOf(that); + that._triggerLongPress = true; + that.blocks.triggerLongPress(); + }, LONGPRESSTIME); - // Always show the trash when there is a block selected, - trashcan.show(); + // Always show the trash when there is a block selected, + trashcan.show(); - // Raise entire stack to the top. - that.blocks.raiseStackToTop(thisBlock); + // Raise entire stack to the top. + that.blocks.raiseStackToTop(thisBlock); - // And possibly the collapse button. - if (that.collapseContainer != null) { - that.blocks.stage.setChildIndex( - that.collapseContainer, - that.blocks.stage.children.length - 1); - } + // And possibly the collapse button. + if (that.collapseContainer != null) { + that.blocks.stage.setChildIndex( + that.collapseContainer, + that.blocks.stage.children.length - 1); + } - moved = false; - that.original = { - x: event.stageX / that.blocks.getStageScale(), - y: event.stageY / that.blocks.getStageScale() - }; + moved = false; + that.original = { + x: event.stageX / that.blocks.getStageScale(), + y: event.stageY / that.blocks.getStageScale() + }; - that.offset = { - x: Math.round(that.container.x - that.original.x), - y: Math.round(that.container.y - that.original.y) - }; - }); + that.offset = { + x: Math.round(that.container.x - that.original.x), + y: Math.round(that.container.y - that.original.y) + }; + }); - this.container.on("pressmove", function(event) { - // FIXME: More voodoo - event.nativeEvent.preventDefault(); + this.container.on("pressmove", function (event) { + // FIXME: More voodoo + event.nativeEvent.preventDefault(); - // Don't allow silence block to be dragged out of a note. - if (that.name === "rest2") { - return; - } + // Don't allow silence block to be dragged out of a note. + if (that.name === "rest2") { + return; + } - if (window.hasMouse) { - moved = true; - } else { - // Make it eaiser to select text on mobile. - setTimeout(function() { - moved = - Math.abs(event.stageX / that.blocks.getStageScale() - - that.original.x) + - Math.abs(event.stageY / that.blocks.getStageScale() - - that.original.y) > 20 && !window.hasMouse; - getInput = !moved; - }, 200); - } - - let oldX = that.container.x; - let oldY = that.container.y; - - let dx = Math.round(event.stageX / that.blocks.getStageScale() + - that.offset.x - oldX); - let dy = Math.round(event.stageY / that.blocks.getStageScale() + - that.offset.y - oldY); - - let finalPos = oldY + dy; - if (that.blocks.stage.y === 0 && finalPos < 45) { - dy += 45 - finalPos; - } - - // scroll when reached edges. - if (event.stageX < 10 && scrollBlockContainer) - that.blocks.moveAllBlocksExcept(that,10,0); - else if (event.stageX > window.innerWidth-10 && - scrollBlockContainer) - that.blocks.moveAllBlocksExcept(that,-10,0); - else if (event.stageY > window.innerHeight-10) - that.blocks.moveAllBlocksExcept(that,0,-10); - else if (event.stageY < 60) - that.blocks.moveAllBlocksExcept(that,0,10); - - if (that.blocks.longPressTimeout != null) { - clearTimeout(that.blocks.longPressTimeout); - that.blocks.longPressTimeout = null; - that.blocks.clearLongPress(); - } - - if (!moved && that.label != null) { - that.label.style.display = "none"; - } - - that.blocks.moveBlockRelative(thisBlock, dx, dy); - - // If we are over the trash, warn the user. - if (trashcan.overTrashcan( - event.stageX / that.blocks.getStageScale(), - event.stageY / that.blocks.getStageScale())) { - trashcan.startHighlightAnimation(); - } else { - trashcan.stopHighlightAnimation(); - } + if (window.hasMouse) { + moved = true; + } else { + // Make it eaiser to select text on mobile. + setTimeout(function () { + moved = + Math.abs(event.stageX / that.blocks.getStageScale() - + that.original.x) + + Math.abs(event.stageY / that.blocks.getStageScale() - + that.original.y) > 20 && !window.hasMouse; + getInput = !moved; + }, 200); + } + + let oldX = that.container.x; + let oldY = that.container.y; + + let dx = Math.round(event.stageX / that.blocks.getStageScale() + + that.offset.x - oldX); + let dy = Math.round(event.stageY / that.blocks.getStageScale() + + that.offset.y - oldY); + + let finalPos = oldY + dy; + if (that.blocks.stage.y === 0 && finalPos < 45) { + dy += 45 - finalPos; + } + + // scroll when reached edges. + if (event.stageX < 10 && scrollBlockContainer) + that.blocks.moveAllBlocksExcept(that, 10, 0); + else if (event.stageX > window.innerWidth - 10 && + scrollBlockContainer) + that.blocks.moveAllBlocksExcept(that, -10, 0); + else if (event.stageY > window.innerHeight - 10) + that.blocks.moveAllBlocksExcept(that, 0, -10); + else if (event.stageY < 60) + that.blocks.moveAllBlocksExcept(that, 0, 10); + + if (that.blocks.longPressTimeout != null) { + clearTimeout(that.blocks.longPressTimeout); + that.blocks.longPressTimeout = null; + that.blocks.clearLongPress(); + } + + if (!moved && that.label != null) { + that.label.style.display = "none"; + } + + that.blocks.moveBlockRelative(thisBlock, dx, dy); + + // If we are over the trash, warn the user. + if (trashcan.overTrashcan( + event.stageX / that.blocks.getStageScale(), + event.stageY / that.blocks.getStageScale())) { + trashcan.startHighlightAnimation(); + } else { + trashcan.stopHighlightAnimation(); + } - if (that.isValueBlock() && that.name !== "media") { - // Ensure text is on top - that.container.setChildIndex( - that.text, that.container.children.length - 1); - } + if (that.isValueBlock() && that.name !== "media") { + // Ensure text is on top + that.container.setChildIndex( + that.text, that.container.children.length - 1); + } - // ...and move any connected blocks. - that.blocks.findDragGroup(thisBlock); - if (that.blocks.dragGroup.length > 0) { - for (let b = 0; b < that.blocks.dragGroup.length; b++) { - let blk = that.blocks.dragGroup[b]; - if (b !== 0) { - that.blocks.moveBlockRelative(blk, dx, dy); + // ...and move any connected blocks. + that.blocks.findDragGroup(thisBlock); + if (that.blocks.dragGroup.length > 0) { + for (let b = 0; b < that.blocks.dragGroup.length; b++) { + let blk = that.blocks.dragGroup[b]; + if (b !== 0) { + that.blocks.moveBlockRelative(blk, dx, dy); + } } } - } - that.blocks.refreshCanvas(); - }); + that.blocks.refreshCanvas(); + }); - this.container.on("mouseout", function(event) { - if (!that.blocks.getLongPressStatus()) { - that._mouseoutCallback(event, moved, haveClick, false); - } else { - clearTimeout(that.blocks.longPressTimeout); - that.blocks.longPressTimeout = null; - that.blocks.clearLongPress(); - } + this.container.on("mouseout", function (event) { + if (!that.blocks.getLongPressStatus()) { + that._mouseoutCallback(event, moved, haveClick, false); + } else { + clearTimeout(that.blocks.longPressTimeout); + that.blocks.longPressTimeout = null; + that.blocks.clearLongPress(); + } - that.blocks.unhighlight(thisBlock, true); - that.blocks.activeBlock = null; + that.blocks.unhighlight(thisBlock, true); + that.blocks.activeBlock = null; - moved = false; - }); + moved = false; + }); - this.container.on("pressup", function(event) { - if (!that.blocks.getLongPressStatus()) { - that._mouseoutCallback(event, moved, haveClick, false); - } else { - clearTimeout(that.blocks.longPressTimeout); - that.blocks.longPressTimeout = null; - that.blocks.clearLongPress(); - } + this.container.on("pressup", function (event) { + if (!that.blocks.getLongPressStatus()) { + that._mouseoutCallback(event, moved, haveClick, false); + } else { + clearTimeout(that.blocks.longPressTimeout); + that.blocks.longPressTimeout = null; + that.blocks.clearLongPress(); + } - that.blocks.unhighlight(thisBlock, true); - that.blocks.activeBlock = null; + that.blocks.unhighlight(thisBlock, true); + that.blocks.activeBlock = null; - moved = false; - }); - }; + moved = false; + }); + }; - /* - * Common code for processing events - * @param-event- mouse - * @param-moved-cursor moved - * @param-haveClick-when clickd - * @param-hideDOM-hide mouse - * set cursor style to default - * @return {void} - * @private - */ - this._mouseoutCallback = function(event, moved, haveClick, hideDOM) { - let thisBlock = this.blocks.blockList.indexOf(this); - if (!this.blocks.logo.runningLilypond) { - document.body.style.cursor = "default"; - } + /* + * Common code for processing events + * @param-event- mouse + * @param-moved-cursor moved + * @param-haveClick-when clickd + * @param-hideDOM-hide mouse + * set cursor style to default + * @return {void} + * @private + */ + this._mouseoutCallback = function (event, moved, haveClick, hideDOM) { + let thisBlock = this.blocks.blockList.indexOf(this); + if (!this.blocks.logo.runningLilypond) { + document.body.style.cursor = "default"; + } - // Always hide the trash when there is no block selected. - trashcan.hide(); + // Always hide the trash when there is no block selected. + trashcan.hide(); - if (this.blocks.longPressTimeout != null) { - clearTimeout(this.blocks.longPressTimeout); - this.blocks.longPressTimeout = null; - this.blocks.clearLongPress(); - } + if (this.blocks.longPressTimeout != null) { + clearTimeout(this.blocks.longPressTimeout); + this.blocks.longPressTimeout = null; + this.blocks.clearLongPress(); + } - if (moved) { - // Check if block is in the trash. - if (trashcan.overTrashcan( - event.stageX / this.blocks.getStageScale(), - event.stageY / this.blocks.getStageScale())) { - if (trashcan.isVisible) { - this.blocks.sendStackToTrash(this); + if (moved) { + // Check if block is in the trash. + if (trashcan.overTrashcan( + event.stageX / this.blocks.getStageScale(), + event.stageY / this.blocks.getStageScale())) { + if (trashcan.isVisible) { + this.blocks.sendStackToTrash(this); + } + } else { + // Otherwise, process move. + // Also, keep track of the time of the last move. + this.blocks.mouseDownTime = new Date().getTime(); + this.blocks.blockMoved(thisBlock); + + // Just in case the blocks are not properly docked after + // the move (workaround for issue #38 -- Blocks fly + // apart). Still need to get to the root cause. + this.blocks.adjustDocks( + this.blocks.blockList.indexOf(this), + true + ); } - } else { - // Otherwise, process move. - // Also, keep track of the time of the last move. - this.blocks.mouseDownTime = new Date().getTime(); - this.blocks.blockMoved(thisBlock); - - // Just in case the blocks are not properly docked after - // the move (workaround for issue #38 -- Blocks fly - // apart). Still need to get to the root cause. - this.blocks.adjustDocks( - this.blocks.blockList.indexOf(this), - true - ); - } - } else if ( - SPECIALINPUTS.indexOf(this.name) !== -1 || - ["media", "loadFile"].indexOf(this.name) !== -1 - ) { - if (!haveClick) { - // Simulate click on Android. - if (new Date().getTime() - this.blocks.mouseDownTime < 500) { - if (!this.trash) { - this.blocks.mouseDownTime = new Date().getTime(); - if (this.name === "media" || this.name === "loadFile") { - this._doOpenMedia(thisBlock); - } else { - this._changeLabel(); + } else if (SPECIALINPUTS.indexOf(this.name) !== -1 || + ["media", "loadFile"].indexOf(this.name) !== -1) { + if (!haveClick) { + // Simulate click on Android. + if (new Date().getTime() - this.blocks.mouseDownTime < 500) { + if (!this.trash) { + this.blocks.mouseDownTime = new Date().getTime(); + if (this.name === "media" || this.name === "loadFile") { + this._doOpenMedia(thisBlock); + } else { + this._changeLabel(); + } } } } } - } - if (hideDOM) { - // Did the mouse move out off the block? If so, hide the - // label DOM element. - if (event.stageX / this.blocks.getStageScale() < this.container.x || - event.stageX / this.blocks.getStageScale() > - (this.container.x + this.width) || - event.stageY < this.container.y || - event.stageY > (this.container.y + this.hitHeight)) { - // There are lots of special cases where we want to - // use piemenus. Make sure this is not one of them. - if (!this._usePiemenu()) { - this._labelChanged(true, true); - hideDOMLabel(); - this._checkWidgets(false); - } - - this.blocks.unhighlight(null); - this.blocks.refreshCanvas(); + if (hideDOM) { + // Did the mouse move out off the block? If so, hide the + // label DOM element. + if (event.stageX / this.blocks.getStageScale() < this.container.x || + event.stageX / this.blocks.getStageScale() > + (this.container.x + this.width) || + event.stageY < this.container.y || + event.stageY > (this.container.y + this.hitHeight)) { + // There are lots of special cases where we want to + // use piemenus. Make sure this is not one of them. + if (!this._usePiemenu()) { + this._labelChanged(true, true); + hideDOMLabel(); + this._checkWidgets(false); + } + + this.blocks.unhighlight(null); + this.blocks.refreshCanvas(); + } + + this.blocks.activeBlock = null; } + }; - this.blocks.activeBlock = null; - } - }; + this._usePiemenu = function () { + // Check on all the special cases were we want to use a pie menu. + this._check_meter_block = null; - this._usePiemenu = function() { - // Check on all the special cases were we want to use a pie menu. - this._check_meter_block = null; + // Special pie menus + if (PIEMENUS.indexOf(this.name) !== -1) { + return true; + } - // Special pie menus - if (PIEMENUS.indexOf(this.name) !== -1) { - return true; - } + // Numeric pie menus + let blk = this.blocks.blockList.indexOf(this); - // Numeric pie menus - let blk = this.blocks.blockList.indexOf(this); + if (this.blocks.octaveNumber(blk)) { + return true; + } - if (this.blocks.octaveNumber(blk)) { - return true; - } + if (this.blocks.noteValueNumber(blk, 2)) { + return true; + } - if (this.blocks.noteValueNumber(blk, 2)) { - return true; - } + if (this.blocks.noteValueNumber(blk, 1)) { + return true; + } - if (this.blocks.noteValueNumber(blk, 1)) { - return true; - } + if (this.blocks.octaveModifierNumber(blk)) { + return true; + } - if (this.blocks.octaveModifierNumber(blk)) { - return true; - } + if (this.blocks.intervalModifierNumber(blk)) { + return true; + } - if (this.blocks.intervalModifierNumber(blk)) { - return true; - } + if (this._usePieNumberC3()) { + return true; + } - if (this._usePieNumberC3()) { - return true; - } + if (this._usePieNumberC2()) { + return true; + } - if (this._usePieNumberC2()) { - return true; - } + if (this._usePieNumberC1()) { + return true; + } - if(this._usePieNumberC1()) { - return true; - } + return false; + }; - return false; - }; + this._usePieNumberC1 = function () { + // Return true if this number block plugs into Connection 1 of + // a block that uses a pie menu. Add block names to the list + // below and the switch statement in the _changeLabel + // function. + let cblk = this.connections[0]; - this._usePieNumberC1 = function() { - // Return true if this number block plugs into Connection 1 of - // a block that uses a pie menu. Add block names to the list - // below and the switch statement in the _changeLabel - // function. - let cblk = this.connections[0]; + if (cblk === null) { + return false; + } - if (cblk === null) { - return false; - } + if (this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC1.length === 0) { + return false; + } - if (this.blocks.blockList[ - this.connections[0]].protoblock.piemenuValuesC1.length === 0) { - return false; - } + return this.blocks.blockList[cblk].connections[1] === + this.blocks.blockList.indexOf(this); + }; - return this.blocks.blockList[cblk].connections[1] === - this.blocks.blockList.indexOf(this); - }; + this._usePieNumberC2 = function () { + // Return true if this number block plugs into Connection 2 of + // a block that uses a pie menu. Add block names to the list + // below and the switch statement in the _changeLabel + // function. + let cblk = this.connections[0]; - this._usePieNumberC2 = function() { - // Return true if this number block plugs into Connection 2 of - // a block that uses a pie menu. Add block names to the list - // below and the switch statement in the _changeLabel - // function. - let cblk = this.connections[0]; + if (cblk === null) { + return false; + } - if (cblk === null) { - return false; - } + if (this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC2.length === 0) { + return false; + } - if (this.blocks.blockList[ - this.connections[0]].protoblock.piemenuValuesC2.length === 0) { - return false; - } + return this.blocks.blockList[cblk].connections[2] === + this.blocks.blockList.indexOf(this); + }; - return this.blocks.blockList[cblk].connections[2] === - this.blocks.blockList.indexOf(this); - }; + this._usePieNumberC3 = function () { + // Return true if this number block plugs into Connection 3 of + // a block that uses a pie menu. Add block names to the list + // below and the switch statement in the _changeLabel + // function. + let cblk = this.connections[0]; - this._usePieNumberC3 = function() { - // Return true if this number block plugs into Connection 3 of - // a block that uses a pie menu. Add block names to the list - // below and the switch statement in the _changeLabel - // function. - let cblk = this.connections[0]; + if (cblk === null) { + return false; + } - if (cblk === null) { - return false; - } + if (this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC3.length === 0) { + return false; + } - if (this.blocks.blockList[ - this.connections[0]].protoblock.piemenuValuesC3.length === 0) { - return false; - } + return this.blocks.blockList[cblk].connections[3] === + this.blocks.blockList.indexOf(this); + }; - return this.blocks.blockList[cblk].connections[3] === - this.blocks.blockList.indexOf(this); - }; + this._ensureDecorationOnTop = function () { + // Find the turtle decoration and move it to the top. + for (let child = 0; child < this.container.children.length; child++) { + if (this.container.children[child].name === "decoration") { + // Drum block in collapsed state is less wide. + // Deprecated + let dx = 0; + if (this.name === "drum" && this.collapsed) { + dx = (25 * this.protoblock.scale) / 2; + } - this._ensureDecorationOnTop = function() { - // Find the turtle decoration and move it to the top. - for (let child = 0; child < this.container.children.length; child++) { - if (this.container.children[child].name === "decoration") { - // Drum block in collapsed state is less wide. - // Deprecated - let dx = 0; - if (this.name === "drum" && this.collapsed) { - dx = (25 * this.protoblock.scale) / 2; - } - - for (let t = 0; t < this.blocks.turtles.turtleList.length; t++) { - if ( - this.blocks.turtles.turtleList[t].startBlock === this - ) { - this.blocks.turtles.turtleList[t].decorationBitmap.x = - this.width - dx - (30 * this.protoblock.scale) / 2; - break; + for (let t = 0; t < this.blocks.turtles.turtleList.length; t++) { + if (this.blocks.turtles.turtleList[t].startBlock === this) { + this.blocks.turtles.turtleList[t].decorationBitmap.x = + this.width - dx - (30 * this.protoblock.scale) / 2; + break; + } } - } - this.container.setChildIndex( - this.container.children[child], - this.container.children.length - 1 - ); - break; + this.container.setChildIndex( + this.container.children[child], + this.container.children.length - 1 + ); + break; + } } - } - this.container.setChildIndex(this.bitmap, 0); - this.container.setChildIndex(this.highlightBitmap, 0); - if (this.disconnectedBitmap !== null) { - this.container.setChildIndex(this.disconnectedBitmap, 0); - } + this.container.setChildIndex(this.bitmap, 0); + this.container.setChildIndex(this.highlightBitmap, 0); + if (this.disconnectedBitmap !== null) { + this.container.setChildIndex(this.disconnectedBitmap, 0); + } - this.updateCache(); - }; + this.updateCache(); + }; - /* - * Change the label in a parameter block - * @return{void} - * @private - */ - this._changeLabel = function() { - let that = this; - let x = this.container.x; - let y = this.container.y; - - let canvasLeft = - this.blocks.canvas.offsetLeft + 28 * this.blocks.blockScale; - let canvasTop = - this.blocks.canvas.offsetTop + 6 * this.blocks.blockScale; - - let selectorWidth = 150; - - let movedStage = false; - let fromY, labelValue, obj, selectedNote, - selectedAttr, selectedAccidental, selectedMode, - selectedInvert, selectedInterval, selectedDrum, - selectedEffect, selectedVoice, selectedNoise, - selectedTemperament, selectedValue, selectedType; - if (!window.hasMouse && this.blocks.stage.y + y > 75) { - movedStage = true; - fromY = this.blocks.stage.y; - this.blocks.stage.y = -y + 75; - } + /* + * Change the label in a parameter block + * @return{void} + * @private + */ + this._changeLabel = function () { + let that = this; + let x = this.container.x; + let y = this.container.y; + + let canvasLeft = this.blocks.canvas.offsetLeft + 28 * this.blocks.blockScale; + let canvasTop = this.blocks.canvas.offsetTop + 6 * this.blocks.blockScale; + + let selectorWidth = 150; + + let movedStage = false; + let fromY, labelValue, obj, selectedNote, + selectedAttr, selectedAccidental, selectedMode, + selectedInvert, selectedInterval, selectedDrum, + selectedEffect, selectedVoice, selectedNoise, + selectedTemperament, selectedValue, selectedType; + if (!window.hasMouse && this.blocks.stage.y + y > 75) { + movedStage = true; + fromY = this.blocks.stage.y; + this.blocks.stage.y = -y + 75; + } + + // A place in the DOM to put modifiable labels (textareas). + if (this.label != null) { + labelValue = this.label.value; + } else { + labelValue = this.value; + } - // A place in the DOM to put modifiable labels (textareas). - if (this.label != null) { - labelValue = this.label.value; - } else { - labelValue = this.value; - } + let labelElem = docById("labelDiv"); - let labelElem = docById("labelDiv"); - - if (this.name === "text") { - labelElem.innerHTML = - ''; - labelElem.classList.add("hasKeyboard"); - this.label = docById("textLabel"); - } else if (this.name === "solfege") { - obj = splitSolfege(this.value); - // solfnotes_ is used in the interface for internationalization. - //.TRANS: the note names must be separated by single spaces - let solfnotes_ = _("ti la sol fa mi re do").split(" "); - - if (this.piemenuOKtoLaunch()) { - piemenuPitches(this, solfnotes_, SOLFNOTES, SOLFATTRS, obj[0], - obj[1]); - } - } else if (this.name === "scaledegree2") { - obj = splitScaleDegree(this.value); - let scalenotes_ = ("7 6 5 4 3 2 1").split(" "); - if (this.piemenuOKtoLaunch()) { - piemenuPitches(this, scalenotes_, SCALENOTES, SOLFATTRS, - obj[0], obj[1]); - }; - } else if (this.name === "customNote") { - if (!this.blocks.logo.customTemperamentDefined) { - // If custom temperament is not defined by user, - // then custom temperament is supposed to be equal temperament. + if (this.name === "text") { + labelElem.innerHTML = + ''; + labelElem.classList.add("hasKeyboard"); + this.label = docById("textLabel"); + } else if (this.name === "solfege") { obj = splitSolfege(this.value); + // solfnotes_ is used in the interface for internationalization. + //.TRANS: the note names must be separated by single spaces let solfnotes_ = _("ti la sol fa mi re do").split(" "); if (this.piemenuOKtoLaunch()) { - piemenuPitches(this, solfnotes_, SOLFNOTES, SOLFATTRS, - obj[0], obj[1]); + piemenuPitches(this, solfnotes_, SOLFNOTES, SOLFATTRS, obj[0], + obj[1]); } - } else { - let noteLabels = TEMPERAMENT; + } else if (this.name === "scaledegree2") { + obj = splitScaleDegree(this.value); + let scalenotes_ = ("7 6 5 4 3 2 1").split(" "); + if (this.piemenuOKtoLaunch()) { + piemenuPitches(this, scalenotes_, SCALENOTES, SOLFATTRS, + obj[0], obj[1]); + }; + } else if (this.name === "customNote") { + if (!this.blocks.logo.customTemperamentDefined) { + // If custom temperament is not defined by user, + // then custom temperament is supposed to be equal temperament. + obj = splitSolfege(this.value); + let solfnotes_ = _("ti la sol fa mi re do").split(" "); - let customLabels = []; - for (let lab in noteLabels) - if (!(lab in PreDefinedTemperaments)) { - customLabels.push(lab); + if (this.piemenuOKtoLaunch()) { + piemenuPitches(this, solfnotes_, SOLFNOTES, SOLFATTRS, + obj[0], obj[1]); } - - let selectedCustom; - if (this.customID != null) { - selectedCustom = this.customID; } else { - selectedCustom = customLabels[0]; + let noteLabels = TEMPERAMENT; + + let customLabels = []; + for (let lab in noteLabels) + if (!(lab in PreDefinedTemperaments)) { + customLabels.push(lab); + } + + let selectedCustom; + if (this.customID != null) { + selectedCustom = this.customID; + } else { + selectedCustom = customLabels[0]; + } + + if (this.value != null) { + selectedNote = this.value; + } else { + selectedNote = TEMPERAMENT[selectedCustom]["0"][1]; + } + + piemenuCustomNotes(this, noteLabels, customLabels, selectedCustom, + selectedNote); } + } else if (this.name === "eastindiansolfege") { + obj = splitSolfege(this.value); + selectedNote = obj[0]; + selectedAttr = obj[1]; + if (this.piemenuOKtoLaunch()) { + piemenuPitches(this, EASTINDIANSOLFNOTES, SOLFNOTES, SOLFATTRS, + obj[0], obj[1]); + } + } else if (this.name === "notename") { + const NOTENOTES = ["B", "A", "G", "F", "E", "D", "C"]; if (this.value != null) { - selectedNote = this.value; + selectedNote = this.value[0]; + if (this.value.length === 1) { + selectedAttr = "♮"; + } else if (this.value.length === 2) { + selectedAttr = this.value[1]; + } else { + selectedAttr = this.value[1] + this.value[2]; + } } else { - selectedNote = TEMPERAMENT[selectedCustom]["0"][1]; + selectedNote = "G"; + selectedAttr = "♮"; } - piemenuCustomNotes(this, noteLabels, customLabels, selectedCustom, - selectedNote); - } - } else if (this.name === "eastindiansolfege") { - obj = splitSolfege(this.value); - selectedNote = obj[0]; - selectedAttr = obj[1]; - - if (this.piemenuOKtoLaunch()) { - piemenuPitches(this, EASTINDIANSOLFNOTES, SOLFNOTES, SOLFATTRS, - obj[0], obj[1]); - } - } else if (this.name === "notename") { - const NOTENOTES = ["B", "A", "G", "F", "E", "D", "C"]; - if (this.value != null) { - selectedNote = this.value[0]; - if (this.value.length === 1) { + if (selectedAttr === "") { selectedAttr = "♮"; - } else if (this.value.length === 2) { - selectedAttr = this.value[1]; + } + + if (this.piemenuOKtoLaunch()) { + piemenuPitches(this, NOTENOTES, NOTENOTES, SOLFATTRS, + selectedNote, selectedAttr); + } + } else if (this.name === "modename") { + if (this.value != null) { + selectedMode = this.value; } else { - selectedAttr = this.value[1] + this.value[2]; + selectedMode = DEFAULTMODE; } - } else { - selectedNote = "G"; - selectedAttr = "♮"; - } - if (selectedAttr === "") { - selectedAttr = "♮"; - } + piemenuModes(this, selectedMode); + } else if (this.name === "accidentalname") { + if (this.value != null) { + selectedAccidental = this.value; + } else { + selectedAccidental = DEFAULTACCIDENTAL; + } - if (this.piemenuOKtoLaunch()) { - piemenuPitches(this, NOTENOTES, NOTENOTES, SOLFATTRS, - selectedNote, selectedAttr); - } - } else if (this.name === "modename") { - if (this.value != null) { - selectedMode = this.value; - } else { - selectedMode = DEFAULTMODE; - } + if (this.piemenuOKtoLaunch()) { + piemenuAccidentals(this, ACCIDENTALLABELS, ACCIDENTALNAMES, + selectedAccidental); + } + } else if (this.name === "intervalname") { + if (this.value != null) { + selectedInterval = this.value; + } else { + selectedInterval = DEFAULTINTERVAL; + } - piemenuModes(this, selectedMode); - } else if (this.name === "accidentalname") { - if (this.value != null) { - selectedAccidental = this.value; - } else { - selectedAccidental = DEFAULTACCIDENTAL; - } + if (this.piemenuOKtoLaunch()) { + piemenuIntervals(this, selectedInterval); + } + } else if (this.name === "invertmode") { + if (this.value != null) { + selectedInvert = this.value; + } else { + selectedInvert = DEFAULTINVERT; + } - if (this.piemenuOKtoLaunch()) { - piemenuAccidentals(this, ACCIDENTALLABELS, ACCIDENTALNAMES, - selectedAccidental); - } - } else if (this.name === "intervalname") { - if (this.value != null) { - selectedInterval = this.value; - } else { - selectedInterval = DEFAULTINTERVAL; - } + let invertLabels = []; + let invertValues = []; - if (this.piemenuOKtoLaunch()) { - piemenuIntervals(this, selectedInterval); - } - } else if (this.name === "invertmode") { - if (this.value != null) { - selectedInvert = this.value; - } else { - selectedInvert = DEFAULTINVERT; - } + for (let i = 0; i < INVERTMODES.length; i++) { + invertLabels.push(_(INVERTMODES[i][1])); + invertValues.push(INVERTMODES[i][1]); + } - let invertLabels = []; - let invertValues = []; + if (this.piemenuOKtoLaunch()) { + piemenuBasic(this, invertLabels, invertValues, selectedInvert); + } + } else if (this.name === "drumname") { + if (this.value != null) { + selectedDrum = this.value; + } else { + selectedDrum = DEFAULTDRUM; + } + + let drumLabels = []; + let drumValues = []; + let categories = []; + let categoriesList = []; + for (let i = 0; i < DRUMNAMES.length; i++) { + if (EFFECTSNAMES.indexOf(DRUMNAMES[i][1]) === -1) { + let label = _(DRUMNAMES[i][1]); + if (getTextWidth(label, "bold 30pt Sans") > 400) { + drumLabels.push(label.substr(0, 8) + "..."); + } else { + drumLabels.push(label); + } - for (let i = 0; i < INVERTMODES.length; i++) { - invertLabels.push(_(INVERTMODES[i][1])); - invertValues.push(INVERTMODES[i][1]); - } + drumValues.push(DRUMNAMES[i][1]); - if (this.piemenuOKtoLaunch()) { - piemenuBasic(this, invertLabels, invertValues, selectedInvert); - } - } else if (this.name === "drumname") { - if (this.value != null) { - selectedDrum = this.value; - } else { - selectedDrum = DEFAULTDRUM; - } + if (categoriesList.indexOf(DRUMNAMES[i][4]) === -1) { + categoriesList.push(DRUMNAMES[i][4]); + } - let drumLabels = []; - let drumValues = []; - let categories = []; - let categoriesList = []; - for (let i = 0; i < DRUMNAMES.length; i++) { - if (EFFECTSNAMES.indexOf(DRUMNAMES[i][1]) === -1) { - let label = _(DRUMNAMES[i][1]); - if (getTextWidth(label, "bold 30pt Sans") > 400) { - drumLabels.push(label.substr(0, 8) + "..."); - } else { - drumLabels.push(label); + categories.push(categoriesList.indexOf(DRUMNAMES[i][4])); } + } - drumValues.push(DRUMNAMES[i][1]); + piemenuVoices(this, DrumLabels, drumValues, categories, + selectedDrum); + } else if (this.name === "effectsname") { + if (this.value != null) { + selectedDrum = this.value; + } else { + selectedEffect = DEFAULTEFFECT; + } + + let effectLabels = []; + let effectValues = []; + let effectcategories = []; + let effectcategoriesList = []; + for (let i = 0; i < DRUMNAMES.length; i++) { + if (EFFECTSNAMES.indexOf(DRUMNAMES[i][1]) !== -1) { + let label = _(DRUMNAMES[i][1]); + if (getTextWidth(label, "Bold 30pt Sans") > 400) { + effectLabels.push(label.substr(0, 8) + "..."); + } else { + effectLabels.push(label); + } - if (categoriesList.indexOf(DRUMNAMES[i][4]) === -1) { - categoriesList.push(DRUMNAMES[i][4]); - } + effectValues.push(DRUMNAMES[i][1]); - categories.push(categoriesList.indexOf(DRUMNAMES[i][4])); - } - } + if (effectcategoriesList.indexOf(DRUMNAMES[i][4]) === -1) { + effectcategoriesList.push(DRUMNAMES[i][4]); + } - piemenuVoices(this, DrumLabels, drumValues, categories, - selectedDrum); - } else if (this.name === "effectsname") { - if (this.value != null) { - selectedDrum = this.value; - } else { - selectedEffect = DEFAULTEFFECT; - } - - let effectLabels = []; - let effectValues = []; - let effectcategories = []; - let effectcategoriesList = []; - for (let i = 0; i < DRUMNAMES.length; i++) { - if (EFFECTSNAMES.indexOf(DRUMNAMES[i][1]) !== -1) { - let label = _(DRUMNAMES[i][1]); - if (getTextWidth(label, "Bold 30pt Sans") > 400) { - effectLabels.push(label.substr(0, 8) + "..."); - } else { - effectLabels.push(label); + effectcategories.push( + effectcategoriesList.indexOf(DRUMNAMES[i][4]) + ); } + } - effectValues.push(DRUMNAMES[i][1]); + piemenuVoices(this, effectLabels, effectValues, effectcategories, + selectedEffect); + } else if (this.name === "filtertype") { + if (this.value != null) { + selectedType = this.value; + } else { + selectedType = DEFAULTFILTERTYPE; + } - if (effectcategoriesList.indexOf(DRUMNAMES[i][4]) === -1) { - effectcategoriesList.push(DRUMNAMES[i][4]); - } + let filterLabels = []; + let filterValues = []; + for (let i = 0; i < FILTERTYPES.length; i++) { + filterLabels.push(_(FILTERTYPES[i][0])); + filterValues.push(FILTERTYPES[i][1]); + } - effectcategories.push( - effectcategoriesList.indexOf(DRUMNAMES[i][4]) - ); + piemenuBasic(this, filterLabels, filterValues, selectedType, + platformColor.piemenuBasic); + } else if (this.name === "oscillatortype") { + if (this.value != null) { + selectedType = this.value; + } else { + selectedType = DEFAULTOSCILLATORTYPE; } - } - piemenuVoices(this, effectLabels, effectValues, effectcategories, - selectedEffect); - } else if (this.name === "filtertype") { - if (this.value != null) { - selectedType = this.value; - } else { - selectedType = DEFAULTFILTERTYPE; - } + let oscLabels = []; + let oscValues = []; + for (let i = 0; i < OSCTYPES.length; i++) { + oscLabels.push(_(OSCTYPES[i][1])); + oscValues.push(OSCTYPES[i][1]); + } - let filterLabels = []; - let filterValues = []; - for (let i = 0; i < FILTERTYPES.length; i++) { - filterLabels.push(_(FILTERTYPES[i][0])); - filterValues.push(FILTERTYPES[i][1]); - } + piemenuBasic(this, oscLabels, oscValues, selectedType, + platformColor.piemenuBasic); + } else if (this.name === "voicename") { + if (this.value != null) { + selectedVoice = this.value; + } else { + selectedVoice = DEFAULTVOICE; + } - piemenuBasic(this, filterLabels, filterValues, selectedType, - platformColor.piemenuBasic); - } else if (this.name === "oscillatortype") { - if (this.value != null) { - selectedType = this.value; - } else { - selectedType = DEFAULTOSCILLATORTYPE; - } + let voiceLabels = []; + let voiceValues = []; + let categories = []; + let categoriesList = []; + for (let i = 0; i < VOICENAMES.length; i++) { + // Skip custom voice in Beginner Mode. + if (beginnerMode && VOICENAMES[i][1] === "custom") { + continue; + } - let oscLabels = []; - let oscValues = []; - for (let i = 0; i < OSCTYPES.length; i++) { - oscLabels.push(_(OSCTYPES[i][1])); - oscValues.push(OSCTYPES[i][1]); - } + let label = _(VOICENAMES[i][1]); + if (getTextWidth(label, "bold 30pt Sans") > 400) { + voiceLabels.push(label.substr(0, 8) + "..."); + } else { + voiceLabels.push(label); + } - piemenuBasic(this, oscLabels, oscValues, selectedType, - platformColor.piemenuBasic); - } else if (this.name === "voicename") { - if (this.value != null) { - selectedVoice = this.value; - } else { - selectedVoice = DEFAULTVOICE; - } + voiceValues.push(VOICENAMES[i][1]); + + if (categoriesList.indexOf(VOICENAMES[i][3]) === -1) { + categoriesList.push(VOICENAMES[i][3]); + } - let voiceLabels = []; - let voiceValues = []; - let categories = []; - let categoriesList = []; - for (let i = 0; i < VOICENAMES.length; i++) { - // Skip custom voice in Beginner Mode. - if (beginnerMode && VOICENAMES[i][1] === "custom") { - continue; + categories.push(categoriesList.indexOf(VOICENAMES[i][3])); } - let label = _(VOICENAMES[i][1]); - if (getTextWidth(label, "bold 30pt Sans") > 400) { - voiceLabels.push(label.substr(0, 8) + "..."); + piemenuVoices(this, voiceLabels, voiceValues, categories, + selectedVoice); + } else if (this.name === "noisename") { + if (this.value != null) { + selectedNoise = this.value; } else { - voiceLabels.push(label); + selectedNoise = DEFAULTNOISE; } - voiceValues.push(VOICENAMES[i][1]); + let noiseLabels = []; + let noiseValues = []; + let categories = []; + let categoriesList = []; + for (let i = 0; i < NOISENAMES.length; i++) { + let label = NOISENAMES[i][0]; + if (getTextWidth(label, "bold 30pt Sans") > 600) { + noiseLabels.push(label.substr(0, 16) + "..."); + } else { + noiseLabels.push(label); + } - if (categoriesList.indexOf(VOICENAMES[i][3]) === -1) { - categoriesList.push(VOICENAMES[i][3]); - } + noiseValues.push(NOISENAMES[i][1]); - categories.push(categoriesList.indexOf(VOICENAMES[i][3])); - } + if (categoriesList.indexOf(NOISENAMES[i][3]) === -1) { + categoriesList.push(NOISENAMES[i][3]); + } - piemenuVoices(this, voiceLabels, voiceValues, categories, - selectedVoice); - } else if (this.name === "noisename") { - if (this.value != null) { - selectedNoise = this.value; - } else { - selectedNoise = DEFAULTNOISE; - } + categories.push(categoriesList.indexOf(NOISENAMES[i][3])); + } - let noiseLabels = []; - let noiseValues = []; - let categories = []; - let categoriesList = []; - for (let i = 0; i < NOISENAMES.length; i++) { - let label = NOISENAMES[i][0]; - if (getTextWidth(label, "bold 30pt Sans") > 600) { - noiseLabels.push(label.substr(0, 16) + "..."); + piemenuVoices(this, + noiseLabels, + noiseValues, + categories, + selectedNoise, + 90 + ); + } else if (this.name === "temperamentname") { + if (this.value != null) { + selectedTemperament = this.value; } else { - noiseLabels.push(label); + selectedTemperament = DEFAULTTEMPERAMENT; } - noiseValues.push(NOISENAMES[i][1]); + let temperamentLabels = []; + let temperamentValues = []; + for (let i = 0; i < TEMPERAMENTS.length; i++) { + // Skip custom temperament in Beginner Mode. + if (beginnerMode && TEMPERAMENTS[i][1] === "custom") { + continue; + } + + if (TEMPERAMENTS[i][0].length === 0) { + temperamentLabels.push(TEMPERAMENTS[i][2]); + } else { + temperamentLabels.push(TEMPERAMENTS[i][0]); + } + + temperamentValues.push(TEMPERAMENTS[i][1]); + } - if (categoriesList.indexOf(NOISENAMES[i][3]) === -1) { - categoriesList.push(NOISENAMES[i][3]); + piemenuBasic(this, temperamentLabels, temperamentValues, + selectedTemperament, + platformColor.piemenuBasic); + } else if (this.name === "boolean") { + if (this.value != null) { + selectedValue = this.value; + } else { + selectedValue = true; } - categories.push(categoriesList.indexOf(NOISENAMES[i][3])); - } + let booleanLabels = [_("true"), _("false")]; + let booleanValues = [true, false]; - piemenuVoices(this, - noiseLabels, - noiseValues, - categories, - selectedNoise, - 90 - ); - } else if (this.name === "temperamentname") { - if (this.value != null) { - selectedTemperament = this.value; - } else { - selectedTemperament = DEFAULTTEMPERAMENT; - } + piemenuBoolean(this, booleanLabels, booleanValues, selectedValue); + } else if (this.name === "grid") { - let temperamentLabels = []; - let temperamentValues = []; - for (let i = 0; i < TEMPERAMENTS.length; i++) { - // Skip custom temperament in Beginner Mode. - if (beginnerMode && TEMPERAMENTS[i][1] === "custom") { - continue; - } + selectedValue = this.value; - if (TEMPERAMENTS[i][0].length === 0) { - temperamentLabels.push(TEMPERAMENTS[i][2]); + let gridLabels = [_("Cartesian"), + _("polar"), + _("Cartesian+polar"), + _("treble"), + _("grand staff"), + _("mezzo-soprano"), + _("alto"), + _("tenor"), + _("bass"), + _("none") + ]; + let gridValues = gridLabels; + + piemenuBasic(this, gridLabels, gridValues, selectedValue, + platformColor.piemenuBasic); + } else if (this.name === "outputtools") { + selectedValue = this.privateData; + let labels; + if (beginnerMode) { + labels = this.protoblock.extraSearchTerms.slice(0, 5); } else { - temperamentLabels.push(TEMPERAMENTS[i][0]); + labels = this.protoblock.extraSearchTerms; } - temperamentValues.push(TEMPERAMENTS[i][1]); - } - - piemenuBasic(this, temperamentLabels, temperamentValues, - selectedTemperament, - platformColor.piemenuBasic); - } else if (this.name === "boolean") { - if (this.value != null) { - selectedValue = this.value; + let values = labels; + piemenuBasic(this, labels, values, selectedValue, + platformColor.piemenuBasic); } else { - selectedValue = true; - } - - let booleanLabels = [_("true"), _("false")]; - let booleanValues = [true, false]; - - piemenuBoolean(this, booleanLabels, booleanValues, selectedValue); - } else if (this.name === "grid") { - - selectedValue = this.value; - - let gridLabels = [_("Cartesian"), - _("polar"), - _("Cartesian+polar") , - _("treble") , - _("grand staff") , - _("mezzo-soprano") , - _("alto") , - _("tenor"), - _("bass") , - _("none") - ]; - let gridValues = gridLabels ; - - piemenuBasic(this, gridLabels, gridValues, selectedValue, - platformColor.piemenuBasic); - } else if (this.name === "outputtools") { - selectedValue = this.privateData; - let labels; - if (beginnerMode) { - labels = this.protoblock.extraSearchTerms.slice(0, 5); - } else { - labels = this.protoblock.extraSearchTerms; - } - - let values = labels; - piemenuBasic(this, labels, values, selectedValue, - platformColor.piemenuBasic); - } else { - // If the number block is connected to a pitch block, then - // use the pie menu for octaves. Other special cases as well. - let blk = this.blocks.blockList.indexOf(this); - if (this.blocks.octaveNumber(blk)) { - piemenuNumber(this, [8, 7, 6, 5, 4, 3, 2, 1], this.value); - } else if (this.blocks.noteValueNumber(blk, 2)) { - let cblk = this.connections[0]; - if (cblk !== null) { - cblk = this.blocks.blockList[cblk].connections[0]; - if (cblk !== null && - ["rhythm2", "stuplet"].indexOf( - this.blocks.blockList[cblk].name) !== -1) { - piemenuNumber(this, [2, 4, 8, 16], this.value); + // If the number block is connected to a pitch block, then + // use the pie menu for octaves. Other special cases as well. + let blk = this.blocks.blockList.indexOf(this); + if (this.blocks.octaveNumber(blk)) { + piemenuNumber(this, [8, 7, 6, 5, 4, 3, 2, 1], this.value); + } else if (this.blocks.noteValueNumber(blk, 2)) { + let cblk = this.connections[0]; + if (cblk !== null) { + cblk = this.blocks.blockList[cblk].connections[0]; + if (cblk !== null && + ["rhythm2", "stuplet"].indexOf( + this.blocks.blockList[cblk].name) !== -1) { + piemenuNumber(this, [2, 4, 8, 16], this.value); + } else { + piemenuNoteValue(this, this.value); + } } else { piemenuNoteValue(this, this.value); } - } else { - piemenuNoteValue(this, this.value); - } - } else if (this.blocks.noteValueNumber(blk, 1)) { - let d = this.blocks.noteValueValue(blk); - let values; - if (d === 1) { - values = [8, 7, 6, 5, 4, 3, 2, 1]; - } else { - values = []; - for (let i = 0; i < Math.min(d, 16); i++) { - values.push(i + 1); - } - } - - let cblk = this.connections[0]; - if (cblk !== null) { - cblk = this.blocks.blockList[cblk].connections[0]; - if (cblk !== null && - ["neighbor", "neighbor2", "rhythm2", "stuplet"].indexOf( - this.blocks.blockList[cblk].name) !== -1) { - values = [3, 2, 1]; - } - } - - piemenuNumber(this, values, this.value); - } else if (this.blocks.octaveModifierNumber(blk)) { - piemenuNumber(this, [-2, -1, 0, 1, 2], this.value); - } else if (this.blocks.intervalModifierNumber(blk)) { - piemenuNumber(this, this.blocks.blockList[ - this.blocks.blockList[this.connections[0]].connections[0] - ].protoblock.piemenuValuesC1, this.value); - } else if (this._usePieNumberC3()) { - piemenuNumber(this, this.blocks.blockList[ - this.connections[0]].protoblock.piemenuValuesC3, this.value); - } else if (this._usePieNumberC2()) { - piemenuNumber(this, this.blocks.blockList[ - this.connections[0]].protoblock.piemenuValuesC2, this.value); - } else if (this._usePieNumberC1()) { - switch (this.blocks.blockList[this.connections[0]].name) { - case "setcolor": - case "sethue": - case "setshade": - case "settranslucency": - case "setgrey": - piemenuNumber(this, - this.blocks.blockList[ - this.connections[0]].protoblock.piemenuValuesC1, - this.value, - this.blocks.blockList[this.connections[0]].name); - break; - case "pitchnumber": - let temperament; - for (let i = 0; i < this.blocks.blockList.length; i++) { - if (this.blocks.blockList[i].name === "settemperament" && - this.blocks.blockList[i].connections[0] !== null) { - let index = this.blocks.blockList[i].connections[1]; - temperament = this.blocks.blockList[index].value; + } else if (this.blocks.noteValueNumber(blk, 1)) { + let d = this.blocks.noteValueValue(blk); + let values; + if (d === 1) { + values = [8, 7, 6, 5, 4, 3, 2, 1]; + } else { + values = []; + for (let i = 0; i < Math.min(d, 16); i++) { + values.push(i + 1); } } - if (temperament === undefined) { - temperament = "equal"; - } - - if (temperament === "equal") { - piemenuNumber(this, - [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], - this.value); - } else { - let pitchNumbers = []; - for (let i = 0; i < TEMPERAMENT[temperament]["pitchNumber"]; i++) { - pitchNumbers.push(i); + let cblk = this.connections[0]; + if (cblk !== null) { + cblk = this.blocks.blockList[cblk].connections[0]; + if (cblk !== null && + ["neighbor", "neighbor2", "rhythm2", "stuplet"].indexOf( + this.blocks.blockList[cblk].name) !== -1) { + values = [3, 2, 1]; } - piemenuNumber(this, pitchNumbers, this.value); } - break; - default: - piemenuNumber(this, this.blocks.blockList[ - this.connections[0]].protoblock.piemenuValuesC1, - this.value); - break; - } - } else { - labelElem.innerHTML = - ''; - labelElem.classList.add("hasKeyboard"); - this.label = docById("numberLabel"); - } - } - let blk = this.blocks.blockList.indexOf(this); - if (!this._usePiemenu()) { - let focused = false; + piemenuNumber(this, values, this.value); + } else if (this.blocks.octaveModifierNumber(blk)) { + piemenuNumber(this, [-2, -1, 0, 1, 2], this.value); + } else if (this.blocks.intervalModifierNumber(blk)) { + piemenuNumber(this, this.blocks.blockList[this.blocks.blockList[this.connections[0]].connections[0]].protoblock.piemenuValuesC1, this.value); + } else if (this._usePieNumberC3()) { + piemenuNumber(this, this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC3, this.value); + } else if (this._usePieNumberC2()) { + piemenuNumber(this, this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC2, this.value); + } else if (this._usePieNumberC1()) { + switch (this.blocks.blockList[this.connections[0]].name) { + case "setcolor": + case "sethue": + case "setshade": + case "settranslucency": + case "setgrey": + piemenuNumber(this, + this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC1, + this.value, + this.blocks.blockList[this.connections[0]].name); + break; + case "pitchnumber": + let temperament; + for (let i = 0; i < this.blocks.blockList.length; i++) { + if (this.blocks.blockList[i].name === "settemperament" && + this.blocks.blockList[i].connections[0] !== null) { + let index = this.blocks.blockList[i].connections[1]; + temperament = this.blocks.blockList[index].value; + } + } - let __blur = function(event) { - // Not sure why the change in the input is not available - // immediately in FireFox. We need a workaround if hardware - // acceleration is enabled. - if (!focused) { - return; + if (temperament === undefined) { + temperament = "equal"; + } + + if (temperament === "equal") { + piemenuNumber(this, + [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + this.value); + } else { + let pitchNumbers = []; + for (let i = 0; i < TEMPERAMENT[temperament]["pitchNumber"]; i++) { + pitchNumbers.push(i); + } + piemenuNumber(this, pitchNumbers, this.value); + } + break; + default: + piemenuNumber(this, this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC1, + this.value); + break; + } + } else { + labelElem.innerHTML = + ''; + labelElem.classList.add("hasKeyboard"); + this.label = docById("numberLabel"); } + } - that._labelChanged(true, true); + let blk = this.blocks.blockList.indexOf(this); + if (!this._usePiemenu()) { + let focused = false; + + let __blur = function (event) { + // Not sure why the change in the input is not available + // immediately in FireFox. We need a workaround if hardware + // acceleration is enabled. + if (!focused) { + return; + } - event.preventDefault(); + that._labelChanged(true, true); - labelElem.classList.remove("hasKeyboard"); + event.preventDefault(); - window.scroll(0, 0); - that.label.removeEventListener("keypress", __keypress); + labelElem.classList.remove("hasKeyboard"); - if (movedStage) { - that.blocks.stage.y = fromY; - that.blocks.updateStage(); - } - }; + window.scroll(0, 0); + that.label.removeEventListener("keypress", __keypress); - let __input = function(event) { - that._labelChanged(false, true); - }; + if (movedStage) { + that.blocks.stage.y = fromY; + that.blocks.updateStage(); + } + }; - if (this.name === "text" || this.name === "number") { - this.label.addEventListener("blur", __blur); - this.label.addEventListener("input", __input); - } + let __input = function (event) { + that._labelChanged(false, true); + }; - let __keypress = function(event) { - if ([13, 10, 9].indexOf(event.keyCode) !== -1) { - __blur(event); + if (this.name === "text" || this.name === "number") { + this.label.addEventListener("blur", __blur); + this.label.addEventListener("input", __input); } - }; - this.label.addEventListener("keypress", __keypress); + let __keypress = function (event) { + if ([13, 10, 9].indexOf(event.keyCode) !== -1) { + __blur(event); + } + }; + + this.label.addEventListener("keypress", __keypress); - this.label.addEventListener("change", function() { - that._labelChanged(false, true); - }); + this.label.addEventListener("change", function () { + that._labelChanged(false, true); + }); - this.label.style.left = Math.round( - (x + this.blocks.stage.x) * + this.label.style.left = Math.round( + (x + this.blocks.stage.x) * this.blocks.getStageScale() + canvasLeft) + "px"; - this.label.style.top = Math.round( - (y + this.blocks.stage.y) * + this.label.style.top = Math.round( + (y + this.blocks.stage.y) * this.blocks.getStageScale() + canvasTop) + "px"; - this.label.style.width = Math.round( - selectorWidth * this.blocks.blockScale * this.protoblock.scale / 2) + "px"; + this.label.style.width = Math.round( + selectorWidth * this.blocks.blockScale * this.protoblock.scale / 2) + "px"; - this.label.style.fontSize = Math.round( - 20 * this.blocks.blockScale * this.protoblock.scale / 2) + "px"; - this.label.style.display = ""; - this.label.focus(); - if (this.labelattr != null) { - this.labelattr.style.display = ""; + this.label.style.fontSize = Math.round( + 20 * this.blocks.blockScale * this.protoblock.scale / 2) + "px"; + this.label.style.display = ""; + this.label.focus(); + if (this.labelattr != null) { + this.labelattr.style.display = ""; + } + + // Firefox fix + setTimeout(function () { + that.label.style.display = ""; + that.label.focus(); + focused = true; + }, 100); + } + }; + + /** + * Keypress handler. Handles exit key (Tab and Enter) press. + * @param{Event} KeyPress event object + * @returns{void} + * @private + */ + this._exitKeyPressed = function (event) { + if ([13, 10, 9].indexOf(event.keyCode) !== -1) { + this._labelChanged(true, false); + event.preventDefault(); + this.label.removeEventListener("keypress", this._exitKeyPressed); + } + }; + /* + * Check if pie menu is ok to launch + * @return{void} + * @public + */ + this.piemenuOKtoLaunch = function () { + if (this._piemenuExitTime === null) { + return true; } - // Firefox fix - setTimeout(function() { - that.label.style.display = ""; - that.label.focus(); - focused = true; - }, 100); - } - }; + return new Date().getTime() - this._piemenuExitTime > 200; + }; - /** - * Keypress handler. Handles exit key (Tab and Enter) press. - * @param{Event} KeyPress event object - * @returns{void} - * @private - */ - this._exitKeyPressed = function(event) { - if ([13, 10, 9].indexOf(event.keyCode) !== -1) { - this._labelChanged(true, false); - event.preventDefault(); - this.label.removeEventListener("keypress", this._exitKeyPressed); - } - }; - /* - * Check if pie menu is ok to launch - * @return{void} - * @public - */ - this.piemenuOKtoLaunch = function() { - if (this._piemenuExitTime === null) { - return true; - } + this._noteValueNumber = function (c) { + // Is this a number block being used as a note value + // denominator argument? + let dblk = this.connections[0]; + // Are we connected to a divide block? + if (this.name === "number" && dblk !== null && + this.blocks.blockList[dblk].name === "divide") { + // Are we the denominator (c == 2) or numerator (c == 1)? + if (this.blocks.blockList[dblk].connections[c] === + this.blocks.blockList.indexOf(this)) { + // Is the divide block connected to a note value block? + cblk = this.blocks.blockList[dblk].connections[0]; + if (cblk !== null) { + // Is it the first or second arg? + switch (this.blocks.blockList[cblk].name) { + case "newnote": + case "pickup": + case "tuplet4": + case "newstaccato": + case "newslur": + case "elapsednotes2": + return this.blocks.blockList[cblk].connections[1] === dblk; + break; + case "meter": + this._check_meter_block = cblk; + case "setbpm2": + case "setmasterbpm2": + case "stuplet": + case "rhythm2": + case "newswing2": + case "vibrato": + case "neighbor": + case "neighbor2": + return this.blocks.blockList[cblk].connections[2] === dblk; + break; + default: + return false; + break; + } + } + } + } - return new Date().getTime() - this._piemenuExitTime > 200; - }; + return false; + }; - this._noteValueNumber = function(c) { - // Is this a number block being used as a note value - // denominator argument? - let dblk = this.connections[0]; - // Are we connected to a divide block? - if (this.name === "number" && dblk !== null && - this.blocks.blockList[dblk].name === "divide") { - // Are we the denominator (c == 2) or numerator (c == 1)? - if (this.blocks.blockList[dblk].connections[c] === - this.blocks.blockList.indexOf(this)) { - // Is the divide block connected to a note value block? - cblk = this.blocks.blockList[dblk].connections[0]; - if (cblk !== null) { - // Is it the first or second arg? - switch (this.blocks.blockList[cblk].name) { + this._noteValueValue = function () { + // Return the number block value being used as a note value + // denominator argument. + let dblk = this.connections[0]; + // We are connected to a divide block. + // Is the divide block connected to a note value block? + cblk = this.blocks.blockList[dblk].connections[0]; + if (cblk !== null) { + // Is it the first or second arg? + switch (this.blocks.blockList[cblk].name) { case "newnote": case "pickup": case "tuplet4": case "newstaccato": case "newslur": case "elapsednotes2": - return this.blocks.blockList[cblk].connections[1] === dblk; + if (this.blocks.blockList[cblk].connections[1] === dblk) { + cblk = this.blocks.blockList[dblk].connections[2]; + return this.blocks.blockList[cblk].value; + } else { + return 1; + } break; case "meter": this._check_meter_block = cblk; @@ -3593,190 +3607,164 @@ function Block(protoblock, blocks, overrideName) { case "vibrato": case "neighbor": case "neighbor2": - return this.blocks.blockList[cblk].connections[2] === dblk; + if (this.blocks.blockList[cblk].connections[2] === dblk) { + if (this.blocks.blockList[cblk].connections[1] === dblk) { + cblk = this.blocks.blockList[dblk].connections[2]; + return this.blocks.blockList[cblk].value; + } else { + return 1; + } + } else { + return 1; + } break; default: - return false; - break; - } - } - } - } - - return false; - }; - - this._noteValueValue = function() { - // Return the number block value being used as a note value - // denominator argument. - let dblk = this.connections[0]; - // We are connected to a divide block. - // Is the divide block connected to a note value block? - cblk = this.blocks.blockList[dblk].connections[0]; - if (cblk !== null) { - // Is it the first or second arg? - switch (this.blocks.blockList[cblk].name) { - case "newnote": - case "pickup": - case "tuplet4": - case "newstaccato": - case "newslur": - case "elapsednotes2": - if (this.blocks.blockList[cblk].connections[1] === dblk) { - cblk = this.blocks.blockList[dblk].connections[2]; - return this.blocks.blockList[cblk].value; - } else { - return 1; - } - break; - case "meter": - this._check_meter_block = cblk; - case "setbpm2": - case "setmasterbpm2": - case "stuplet": - case "rhythm2": - case "newswing2": - case "vibrato": - case "neighbor": - case "neighbor2": - if (this.blocks.blockList[cblk].connections[2] === dblk) { - if (this.blocks.blockList[cblk].connections[1] === dblk) { - cblk = this.blocks.blockList[dblk].connections[2]; - return this.blocks.blockList[cblk].value; - } else { return 1; - } - } else { - return 1; + break; } - break; - default: - return 1; - break; } - } - return 1; - }; + return 1; + }; - this._octaveNumber = function() { - // Is this a number block being used as an octave argument? - return (this.name === "number" && this.connections[0] !== null && + this._octaveNumber = function () { + // Is this a number block being used as an octave argument? + return (this.name === "number" && this.connections[0] !== null && ["pitch", "setpitchnumberoffset", "invert1", "tofrequency", "nthmodalpitch" ].indexOf(this.blocks.blockList[this.connections[0]].name) !== -1 && this.blocks.blockList[this.connections[0]].connections[2] === this.blocks.blockList.indexOf(this)); - }; + }; - this._checkWidgets = function(closeInput) { - // Detect if label is changed, then reinit widget windows - // if they are open. - let thisBlock = this.blocks.blockList.indexOf(this); - let topBlock = this.blocks.findTopBlock(thisBlock); - let widgetTitle = document.getElementsByClassName("wftTitle"); - let lockInit = false; - if (closeInput === false) { - for (let i = 0; i < widgetTitle.length; i++) { - if (lockInit === false) { - switch (widgetTitle[i].innerHTML) { - case "oscilloscope": - case "tempo": - case "rhythm maker": - case "pitch slider": - case "pitch staircase": - case "status": - case "phrase maker": - case "custom mode": - case "music keyboard": - case "pitch drum": - case "meter": - case "temperament": - case "mode": - case "timbre": - lockInit = true; - if (this.blocks.blockList[topBlock].protoblock.staticLabels[0] == widgetTitle[i].innerHTML) { - this.blocks.reInitWidget(topBlock, 1500); - } - break; + this._checkWidgets = function (closeInput) { + // Detect if label is changed, then reinit widget windows + // if they are open. + let thisBlock = this.blocks.blockList.indexOf(this); + let topBlock = this.blocks.findTopBlock(thisBlock); + let widgetTitle = document.getElementsByClassName("wftTitle"); + let lockInit = false; + if (closeInput === false) { + for (let i = 0; i < widgetTitle.length; i++) { + if (lockInit === false) { + switch (widgetTitle[i].innerHTML) { + case "oscilloscope": + case "tempo": + case "rhythm maker": + case "pitch slider": + case "pitch staircase": + case "status": + case "phrase maker": + case "custom mode": + case "music keyboard": + case "pitch drum": + case "meter": + case "temperament": + case "mode": + case "timbre": + lockInit = true; + if (this.blocks.blockList[topBlock].protoblock.staticLabels[0] == widgetTitle[i].innerHTML) { + this.blocks.reInitWidget(topBlock, 1500); + } + break; + } } } } - } - }; - - this._labelChanged = function(closeInput, notPieMenu) { - // Update the block values as they change in the DOM label. + }; - // Instead, we do this when we hide the DOM element. - // this._checkWidgets(closeInput); + this._labelChanged = function (closeInput, notPieMenu) { + // Update the block values as they change in the DOM label. + // Instead, we do this when we hide the DOM element. + // this._checkWidgets(closeInput); + if (this === null || this.label === null) { + this._labelLock = false; + return; + } - if (this === null || this.label === null) { - this._labelLock = false; - return; - } + this._labelLock = true; - this._labelLock = true; + if (closeInput) { + this.label.style.display = "none"; + if (this.labelattr != null) { + this.labelattr.style.display = "none"; + } + docById("wheelDiv").style.display = "none"; + } - if (closeInput) { - this.label.style.display = "none"; - if (this.labelattr != null) { - this.labelattr.style.display = "none"; + // The pie menu may be visible too, so hide it. + if (notPieMenu === undefined) { + docById("wheelDiv").style.display = "none"; } - docById("wheelDiv").style.display = "none"; - } - // The pie menu may be visible too, so hide it. - if (notPieMenu === undefined) { - docById("wheelDiv").style.display = "none"; - } + let oldValue = this.value; + let newValue = this.label.value; - let oldValue = this.value; - let newValue = this.label.value; - - if (this.labelattr != null) { - let attrValue = this.labelattr.value; - switch (attrValue) { - case "𝄪": - case "♯": - case "𝄫": - case "♭": - newValue = newValue + attrValue; - break; - default: - break; + if (this.labelattr != null) { + let attrValue = this.labelattr.value; + switch (attrValue) { + case "𝄪": + case "♯": + case "𝄫": + case "♭": + newValue = newValue + attrValue; + break; + default: + break; + } } - } - let c = this.connections[0]; + let c = this.connections[0]; - if (oldValue === newValue) { - // Nothing to do in this case. - this._labelLock = false; - if ( - this.name !== "text" || - c === null || - this.blocks.blockList[c].name !== "storein" - ) { - return; + if (oldValue === newValue) { + // Nothing to do in this case. + this._labelLock = false; + if (this.name !== "text" || + c === null || + this.blocks.blockList[c].name !== "storein") { + return; + } } - } - c = this.connections[0]; - if (this.name === "text" && c != null) { - let cblock = this.blocks.blockList[c]; - let uniqueValue; - switch (cblock.name) { - case "action": - let that = this; + c = this.connections[0]; + if (this.name === "text" && c != null) { + let cblock = this.blocks.blockList[c]; + let uniqueValue; + switch (cblock.name) { + case "action": + let that = this; - that.blocks.palettes.removeActionPrototype(oldValue); + that.blocks.palettes.removeActionPrototype(oldValue); - // Ensure new name is unique. - uniqueValue = this.blocks.findUniqueActionName( - newValue - ); - if (uniqueValue !== newValue) { + // Ensure new name is unique. + uniqueValue = this.blocks.findUniqueActionName( + newValue + ); + if (uniqueValue !== newValue) { + newValue = uniqueValue; + this.value = newValue; + let label = this.value.toString(); + if (getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { + label = label.substr(0, STRINGLEN) + "..."; + } + this.text.text = label; + this.label.value = newValue; + this.updateCache(); + } + break; + case "pitch": + // In case of custom temperament + uniqueValue = this.blocks.findUniqueCustomName( + newValue + ); newValue = uniqueValue; + for (let pitchNumber in TEMPERAMENT["custom"]) { + if (pitchNumber !== "pitchNumber") { + if (oldValue == + TEMPERAMENT["custom"][pitchNumber][1]) { + TEMPERAMENT["custom"][pitchNumber][1] = newValue; + } + } + } this.value = newValue; let label = this.value.toString(); if (getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { @@ -3785,237 +3773,210 @@ function Block(protoblock, blocks, overrideName) { this.text.text = label; this.label.value = newValue; this.updateCache(); - } - break; - case "pitch": - // In case of custom temperament - uniqueValue = this.blocks.findUniqueCustomName( - newValue - ); - newValue = uniqueValue; - for (let pitchNumber in TEMPERAMENT["custom"]) { - if (pitchNumber !== "pitchNumber") { - if ( - oldValue == - TEMPERAMENT["custom"][pitchNumber][1] - ) { - TEMPERAMENT["custom"][ - pitchNumber - ][1] = newValue; - } - } - } - this.value = newValue; - let label = this.value.toString(); - if (getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { - label = label.substr(0, STRINGLEN) + "..."; - } - this.text.text = label; - this.label.value = newValue; - this.updateCache(); - break; - default: - break; + break; + default: + break; + } } - } - // Update the block value and block text. - if (this.name === "number") { - let cblk1 = this.connections[0]; - let cblk2; + // Update the block value and block text. + if (this.name === "number") { + let cblk1 = this.connections[0]; + let cblk2; - if (cblk1 !== null) { - cblk2 = this.blocks.blockList[cblk1].connections[0]; - } else { - cblk2 = null; - } + if (cblk1 !== null) { + cblk2 = this.blocks.blockList[cblk1].connections[0]; + } else { + cblk2 = null; + } - if (this.value === "-") { - this.value = -1; - } else if ((cblk2 !== null) && (newValue < 0) && (this.blocks.blockList[cblk1].name === 'newnote' || this.blocks.blockList[cblk2].name == 'newnote')) { - this.label.value = 0; - this.value = 0; - } - else { - this.value = Number(newValue); - } + if (this.value === "-") { + this.value = -1; + } else if ((cblk2 !== null) && (newValue < 0) && (this.blocks.blockList[cblk1].name === 'newnote' || this.blocks.blockList[cblk2].name == 'newnote')) { + this.label.value = 0; + this.value = 0; + } + else { + this.value = Number(newValue); + } - if (isNaN(this.value)) { - let thisBlock = this.blocks.blockList.indexOf(this); - this.blocks.errorMsg( - newValue + ": " + _("Not a number"), - thisBlock - ); - this.blocks.refreshCanvas(); - this.value = oldValue; + if (isNaN(this.value)) { + let thisBlock = this.blocks.blockList.indexOf(this); + this.blocks.errorMsg( + newValue + ": " + _("Not a number"), + thisBlock + ); + this.blocks.refreshCanvas(); + this.value = oldValue; + } + } else { + this.value = newValue; } - } else { - this.value = newValue; - } - let obj; - let label; - let attr; + let obj; + let label; + let attr; - if (this.name === "solfege") { - obj = splitSolfege(this.value); - label = i18nSolfege(obj[0]); - attr = obj[1]; + if (this.name === "solfege") { + obj = splitSolfege(this.value); + label = i18nSolfege(obj[0]); + attr = obj[1]; - if (attr !== "♮") { - label += attr; - } - } else if (this.name === "eastindiansolfege") { - obj = splitSolfege(this.value); - label = WESTERN2EISOLFEGENAMES[obj[0]]; - attr = obj[1]; + if (attr !== "♮") { + label += attr; + } + } else if (this.name === "eastindiansolfege") { + obj = splitSolfege(this.value); + label = WESTERN2EISOLFEGENAMES[obj[0]]; + attr = obj[1]; - if (attr !== "♮") { - label += attr; + if (attr !== "♮") { + label += attr; + } + } else if (this.name === "modename") { + label = this.value + " " + getModeNumbers(this.value); + } else { + label = this.value.toString(); } - } else if (this.name === "modename") { - label = this.value + " " + getModeNumbers(this.value); - } else { - label = this.value.toString(); - } - if (WIDENAMES.indexOf(this.name) === -1 && - getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { - let slen = label.length - 5; - let nlabel = "" + label.substr(0, slen) + "..."; - while (getTextWidth(nlabel, "bold 20pt Sans") > TEXTWIDTH) { - slen -= 1; - nlabel = "" + label.substr(0, slen) + "..."; - let foo = getTextWidth(nlabel, "bold 20pt Sans"); - if (slen <= STRINGLEN) { - break; + if (WIDENAMES.indexOf(this.name) === -1 && + getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { + let slen = label.length - 5; + let nlabel = "" + label.substr(0, slen) + "..."; + while (getTextWidth(nlabel, "bold 20pt Sans") > TEXTWIDTH) { + slen -= 1; + nlabel = "" + label.substr(0, slen) + "..."; + let foo = getTextWidth(nlabel, "bold 20pt Sans"); + if (slen <= STRINGLEN) { + break; + } } + + label = nlabel; } - label = nlabel; - } + this.text.text = label; - this.text.text = label; + if (closeInput) { + // and hide the DOM textview... + this.label.style.display = "none"; + docById("wheelDiv").style.display = "none"; + } - if (closeInput) { - // and hide the DOM textview... - this.label.style.display = "none"; - docById("wheelDiv").style.display = "none"; - } + // Make sure text is on top. + this.container.setChildIndex(this.text, this.container.children.length - 1); + this.updateCache(); - // Make sure text is on top. - this.container.setChildIndex(this.text, this.container.children.length - 1); - this.updateCache(); + if (this.name === "text" && c != null) { + let cblock = this.blocks.blockList[c]; + switch (cblock.name) { + case "action": + // If the label was the name of an action, update the + // associated run this.blocks and the palette buttons + // Rename both do <- name and nameddo blocks. + this.blocks.renameDos(oldValue, newValue); - if (this.name === "text" && c != null) { - let cblock = this.blocks.blockList[c]; - switch (cblock.name) { - case "action": - // If the label was the name of an action, update the - // associated run this.blocks and the palette buttons - // Rename both do <- name and nameddo blocks. - this.blocks.renameDos(oldValue, newValue); + if (oldValue === _("action")) { + this.blocks.newNameddoBlock( + newValue, + this.blocks.actionHasReturn(c), + this.blocks.actionHasArgs(c) + ); + this.blocks.setActionProtoVisiblity(false); + } - if (oldValue === _("action")) { this.blocks.newNameddoBlock( newValue, this.blocks.actionHasReturn(c), this.blocks.actionHasArgs(c) ); - this.blocks.setActionProtoVisiblity(false); - } - - this.blocks.newNameddoBlock( - newValue, - this.blocks.actionHasReturn(c), - this.blocks.actionHasArgs(c) - ); - let blockPalette = this.blocks.palettes.dict["action"]; - for (let blk = 0; blk < blockPalette.protoList.length; blk++) { - let block = blockPalette.protoList[blk]; - if (oldValue === _("action")) { - if (block.name === "nameddo" && block.defaults.length === 0) { - block.hidden = true; - } - } else { - if (block.name === "nameddo" && - block.defaults[0] === oldValue) { - blockPalette.remove(block, oldValue); + let blockPalette = this.blocks.palettes.dict["action"]; + for (let blk = 0; blk < blockPalette.protoList.length; blk++) { + let block = blockPalette.protoList[blk]; + if (oldValue === _("action")) { + if (block.name === "nameddo" && block.defaults.length === 0) { + block.hidden = true; + } + } else { + if (block.name === "nameddo" && + block.defaults[0] === oldValue) { + blockPalette.remove(block, oldValue); + } } } - } - if (oldValue === _("action")) { - this.blocks.newNameddoBlock( - newValue, this.blocks.actionHasReturn(c), - this.blocks.actionHasArgs(c)); - this.blocks.setActionProtoVisiblity(false); - } - this.blocks.renameNameddos(oldValue, newValue); - this.blocks.palettes.hide(); - this.blocks.palettes.updatePalettes("action"); - this.blocks.palettes.show(); - break; - case "storein": - // Check to see which connection we are using in - // cblock. We only do something if blk is attached to - // the name connection (1). - blk = this.blocks.blockList.indexOf(this); - if (cblock.connections[1] === blk && closeInput) { - // If the label was the name of a storein, update the - // associated box this.blocks and the palette buttons. - if (this.value !== "box") { - this.blocks.newStoreinBlock(this.value); - this.blocks.newStorein2Block(this.value); - this.blocks.newNamedboxBlock(this.value); + if (oldValue === _("action")) { + this.blocks.newNameddoBlock( + newValue, this.blocks.actionHasReturn(c), + this.blocks.actionHasArgs(c)); + this.blocks.setActionProtoVisiblity(false); } - - // Rename both box <- name and namedbox blocks. - this.blocks.renameBoxes(oldValue, newValue); - this.blocks.renameNamedboxes(oldValue, newValue); - this.blocks.renameStoreinBoxes(oldValue, newValue); - this.blocks.renameStorein2Boxes(oldValue, newValue); - + this.blocks.renameNameddos(oldValue, newValue); this.blocks.palettes.hide(); - this.blocks.palettes.updatePalettes("boxes"); + this.blocks.palettes.updatePalettes("action"); this.blocks.palettes.show(); - } - break; - case "setdrum": - case "playdrum": - if (_THIS_IS_MUSIC_BLOCKS_) { - if (newValue.slice(0, 4) === "http") { - this.blocks.logo.synth.loadSynth(0, newValue); + break; + case "storein": + // Check to see which connection we are using in + // cblock. We only do something if blk is attached to + // the name connection (1). + blk = this.blocks.blockList.indexOf(this); + if (cblock.connections[1] === blk && closeInput) { + // If the label was the name of a storein, update the + // associated box this.blocks and the palette buttons. + if (this.value !== "box") { + this.blocks.newStoreinBlock(this.value); + this.blocks.newStorein2Block(this.value); + this.blocks.newNamedboxBlock(this.value); + } + + // Rename both box <- name and namedbox blocks. + this.blocks.renameBoxes(oldValue, newValue); + this.blocks.renameNamedboxes(oldValue, newValue); + this.blocks.renameStoreinBoxes(oldValue, newValue); + this.blocks.renameStorein2Boxes(oldValue, newValue); + + this.blocks.palettes.hide(); + this.blocks.palettes.updatePalettes("boxes"); + this.blocks.palettes.show(); } - } - break; - case "temperament1": - let temptemperament = TEMPERAMENT[oldValue]; - delete TEMPERAMENT[oldValue]; - TEMPERAMENT[newValue] = temptemperament; - updateTemperaments(); - break; - default: - break; + break; + case "setdrum": + case "playdrum": + if (_THIS_IS_MUSIC_BLOCKS_) { + if (newValue.slice(0, 4) === "http") { + this.blocks.logo.synth.loadSynth(0, newValue); + } + } + break; + case "temperament1": + let temptemperament = TEMPERAMENT[oldValue]; + delete TEMPERAMENT[oldValue]; + TEMPERAMENT[newValue] = temptemperament; + updateTemperaments(); + break; + default: + break; + } } - } - // We are done changing the label, so unlock. - this._labelLock = false; + // We are done changing the label, so unlock. + this._labelLock = false; - if (_THIS_IS_MUSIC_BLOCKS_) { - // Load the synth for the selected drum. - if (this.name === "drumname") { - this.blocks.logo.synth.loadSynth(0, getDrumSynthName(this.value)); - } else if (this.name === "effectsname") { - this.blocks.logo.synth.loadSynth(0, getDrumSynthName(this.value)); - } else if (this.name === "voicename") { - this.blocks.logo.synth.loadSynth(0, getVoiceSynthName(this.value)); - } else if (this.name === "noisename") { - this.blocks.logo.synth.loadSynth(0, getNoiseSynthName(this.value)); + if (_THIS_IS_MUSIC_BLOCKS_) { + // Load the synth for the selected drum. + if (this.name === "drumname") { + this.blocks.logo.synth.loadSynth(0, getDrumSynthName(this.value)); + } else if (this.name === "effectsname") { + this.blocks.logo.synth.loadSynth(0, getDrumSynthName(this.value)); + } else if (this.name === "voicename") { + this.blocks.logo.synth.loadSynth(0, getVoiceSynthName(this.value)); + } else if (this.name === "noisename") { + this.blocks.logo.synth.loadSynth(0, getNoiseSynthName(this.value)); + } } - } - }; + }; + } } /* From 5250b5f4375327c30bd1630682d5d695ff834d74 Mon Sep 17 00:00:00 2001 From: kushal khare Date: Tue, 1 Dec 2020 13:48:12 +0530 Subject: [PATCH 2/3] fixing spaces --- js/block.js | 119 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 41 deletions(-) diff --git a/js/block.js b/js/block.js index 9580be6b60..5bc4fc129c 100644 --- a/js/block.js +++ b/js/block.js @@ -114,15 +114,12 @@ class Block { this.text = null; // A dynamically generated text label on block itself. this.value = null; // Value for number, text, and media blocks. this.privateData = null; // A block may have some private data, - - // e.g., nameboxes use this field to store // the box name associated with the block. this.image = protoblock.image; // The file path of the image. this.imageBitmap = null; this.controller = null; // Note blocks get a controller - // All blocks have at a container and least one bitmap. this.container = null; this.bounds = null; @@ -848,7 +845,7 @@ class Block { that.container.uncache(); } - const __callback = function (that, firstTime) { + const __callback = function(that, firstTime) { that.blocks.refreshCanvas(); let thisBlock = that.blocks.blockList.indexOf(that); @@ -912,8 +909,10 @@ class Block { .replace("block_label", safeSVG(block_label)); } else { artwork = that.artwork - .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[that.protoblock.palette.name]) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[ + that.protoblock.palette.name]) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ + that.protoblock.palette.name]) .replace("block_label", safeSVG(block_label)); } @@ -949,8 +948,10 @@ class Block { .replace("block_label", safeSVG(block_label)); } else { artwork = that.artwork - .replace(/fill_color/g, platformColor.paletteColors[that.protoblock.palette.name][3]) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace(/fill_color/g, platformColor.paletteColors[ + that.protoblock.palette.name][3]) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ + that.protoblock.palette.name]) .replace("block_label", safeSVG(block_label)); } @@ -985,7 +986,8 @@ class Block { } else { artwork = that.artwork .replace(/fill_color/g, platformColor.disconnected) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ + that.protoblock.palette.name]) .replace("block_label", safeSVG(block_label)); } @@ -1007,8 +1009,10 @@ class Block { } else { block_label = this.overrideName; } - } else if (this.protoblock.staticLabels.length > 0 && - !this.protoblock.image) { + } else if ( + this.protoblock.staticLabels.length > 0 && + !this.protoblock.image + ) { // Label should be defined inside _(). block_label = this.protoblock.staticLabels[0]; } @@ -1040,8 +1044,10 @@ class Block { .replace("block_label", safeSVG(block_label)); } else { artwork = this.artwork - .replace(/fill_color/g, PALETTEFILLCOLORS[this.protoblock.palette.name]) - .replace(/stroke_color/g, PALETTESTROKECOLORS[this.protoblock.palette.name]) + .replace(/fill_color/g, PALETTEFILLCOLORS[ + this.protoblock.palette.name]) + .replace(/stroke_color/g, PALETTESTROKECOLORS[ + this.protoblock.palette.name]) .replace("block_label", safeSVG(block_label)); } @@ -1453,8 +1459,10 @@ class Block { // Save the collapsed block artwork for export. that.blocks.blockCollapseArt[that.blocks.blockList.indexOf(that)] = that.collapseArtwork - .replace(/fill_color/g, PALETTEFILLCOLORS[that.protoblock.palette.name]) - .replace(/stroke_color/g, PALETTESTROKECOLORS[that.protoblock.palette.name]) + .replace(/fill_color/g, PALETTEFILLCOLORS[ + that.protoblock.palette.name]) + .replace(/stroke_color/g, PALETTESTROKECOLORS[ + that.protoblock.palette.name]) .replace("block_label", safeSVG(that.collapseText.text)); __processExpandButton(that); @@ -1484,8 +1492,10 @@ class Block { }; let artwork = this.collapseArtwork - .replace(/fill_color/g, PALETTEFILLCOLORS[this.protoblock.palette.name]) - .replace(/stroke_color/g, PALETTESTROKECOLORS[this.protoblock.palette.name]) + .replace(/fill_color/g, PALETTEFILLCOLORS[ + this.protoblock.palette.name]) + .replace(/stroke_color/g, PALETTESTROKECOLORS[ + this.protoblock.palette.name]) .replace("block_label", ""); _blockMakeBitmap(artwork, __processCollapseBitmap, this); }; @@ -1536,7 +1546,8 @@ class Block { } if (this.blocks.blockList[last(this.connections)].name === "hidden") { - if (last(this.blocks.blockList[last(this.connections)].connections) === null) { + if (last(this.blocks.blockList[ + last(this.connections)].connections) === null) { return true; } } @@ -1699,6 +1710,7 @@ class Block { image.onload = function () { // Before adding new artwork, remove any old artwork. // that.removeChildBitmap("media"); + let bitmap = new createjs.Bitmap(image); bitmap.name = "media"; @@ -2060,15 +2072,18 @@ class Block { if (this.blocks.blockList[c].name === "divide") { let c1 = this.blocks.blockList[c].connections[1]; let c2 = this.blocks.blockList[c].connections[2]; - if (c1 !== null && + if ( + c1 !== null && c2 !== null && - this.blocks.blockList[c2].name === "divide") { + this.blocks.blockList[c2].name === "divide" + ) { let ci = this.blocks.blockList[c2].connections[1]; let cii = this.blocks.blockList[c2].connections[2]; if (ci !== null && cii !== null && this.blocks.blockList[ci].name === "number" && - this.blocks.blockList[cii].name === "number") { + this.blocks.blockList[cii].name === "number" + ) { v = (this.blocks.blockList[c1].value / this.blocks.blockList[ci].value) * this.blocks.blockList[cii].value; @@ -2184,8 +2199,7 @@ class Block { //.TRANS: scalar step return (_("down") + " " + Math.abs( this.blocks.blockList[c1].value)); - } else - return _("up") + " " + this.blocks.blockList[c1].value; + } else return _("up") + " " + this.blocks.blockList[c1].value; break; case "pitchnumber": c1 = this.blocks.blockList[c].connections[1]; @@ -2209,6 +2223,7 @@ class Block { // Toggle the collapsed state of blocks inside of a note (or // interval) block and reposition any blocks below // it. Finally, resize any surrounding clamps. + // Set collapsed state of note value arg blocks... if (this.connections[1] !== null) { this.blocks.findDragGroup(this.connections[1]); @@ -2732,8 +2747,10 @@ class Block { true ); } - } else if (SPECIALINPUTS.indexOf(this.name) !== -1 || - ["media", "loadFile"].indexOf(this.name) !== -1) { + } else if ( + SPECIALINPUTS.indexOf(this.name) !== -1 || + ["media", "loadFile"].indexOf(this.name) !== -1 + ) { if (!haveClick) { // Simulate click on Android. if (new Date().getTime() - this.blocks.mouseDownTime < 500) { @@ -2831,7 +2848,8 @@ class Block { return false; } - if (this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC1.length === 0) { + if (this.blocks.blockList[ + this.connections[0]].protoblock.piemenuValuesC1.length === 0) { return false; } @@ -2850,7 +2868,8 @@ class Block { return false; } - if (this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC2.length === 0) { + if (this.blocks.blockList[ + this.connections[0]].protoblock.piemenuValuesC2.length === 0) { return false; } @@ -2869,7 +2888,8 @@ class Block { return false; } - if (this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC3.length === 0) { + if (this.blocks.blockList[ + this.connections[0]].protoblock.piemenuValuesC3.length === 0) { return false; } @@ -2889,7 +2909,9 @@ class Block { } for (let t = 0; t < this.blocks.turtles.turtleList.length; t++) { - if (this.blocks.turtles.turtleList[t].startBlock === this) { + if ( + this.blocks.turtles.turtleList[t].startBlock === this + ) { this.blocks.turtles.turtleList[t].decorationBitmap.x = this.width - dx - (30 * this.protoblock.scale) / 2; break; @@ -2923,8 +2945,10 @@ class Block { let x = this.container.x; let y = this.container.y; - let canvasLeft = this.blocks.canvas.offsetLeft + 28 * this.blocks.blockScale; - let canvasTop = this.blocks.canvas.offsetTop + 6 * this.blocks.blockScale; + let canvasLeft = + this.blocks.canvas.offsetLeft + 28 * this.blocks.blockScale; + let canvasTop = + this.blocks.canvas.offsetTop + 6 * this.blocks.blockScale; let selectorWidth = 150; @@ -3371,11 +3395,15 @@ class Block { } else if (this.blocks.octaveModifierNumber(blk)) { piemenuNumber(this, [-2, -1, 0, 1, 2], this.value); } else if (this.blocks.intervalModifierNumber(blk)) { - piemenuNumber(this, this.blocks.blockList[this.blocks.blockList[this.connections[0]].connections[0]].protoblock.piemenuValuesC1, this.value); + piemenuNumber(this, this.blocks.blockList[ + this.blocks.blockList[this.connections[0] + ].connections[0]].protoblock.piemenuValuesC1, this.value); } else if (this._usePieNumberC3()) { - piemenuNumber(this, this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC3, this.value); + piemenuNumber(this, this.blocks.blockList[ + this.connections[0]].protoblock.piemenuValuesC3, this.value); } else if (this._usePieNumberC2()) { - piemenuNumber(this, this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC2, this.value); + piemenuNumber(this, this.blocks.blockList[ + this.connections[0]].protoblock.piemenuValuesC2, this.value); } else if (this._usePieNumberC1()) { switch (this.blocks.blockList[this.connections[0]].name) { case "setcolor": @@ -3384,7 +3412,8 @@ class Block { case "settranslucency": case "setgrey": piemenuNumber(this, - this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC1, + this.blocks.blockList[ + this.connections[0]].protoblock.piemenuValuesC1, this.value, this.blocks.blockList[this.connections[0]].name); break; @@ -3415,7 +3444,8 @@ class Block { } break; default: - piemenuNumber(this, this.blocks.blockList[this.connections[0]].protoblock.piemenuValuesC1, + piemenuNumber(this, this.blocks.blockList[ + this.connections[0]].protoblock.piemenuValuesC1, this.value); break; } @@ -3674,6 +3704,7 @@ class Block { this._labelChanged = function (closeInput, notPieMenu) { // Update the block values as they change in the DOM label. + // Instead, we do this when we hide the DOM element. // this._checkWidgets(closeInput); if (this === null || this.label === null) { @@ -3718,9 +3749,11 @@ class Block { if (oldValue === newValue) { // Nothing to do in this case. this._labelLock = false; - if (this.name !== "text" || + if ( + this.name !== "text" || c === null || - this.blocks.blockList[c].name !== "storein") { + this.blocks.blockList[c].name !== "storein" + ) { return; } } @@ -3759,9 +3792,13 @@ class Block { newValue = uniqueValue; for (let pitchNumber in TEMPERAMENT["custom"]) { if (pitchNumber !== "pitchNumber") { - if (oldValue == - TEMPERAMENT["custom"][pitchNumber][1]) { - TEMPERAMENT["custom"][pitchNumber][1] = newValue; + if ( + oldValue == + TEMPERAMENT["custom"][pitchNumber][1] + ) { + TEMPERAMENT["custom"][ + pitchNumber + ][1] = newValue; } } } From 1171aa7b9dfa889500cda43c4ce966f705cfe512 Mon Sep 17 00:00:00 2001 From: kushal khare Date: Tue, 1 Dec 2020 13:51:49 +0530 Subject: [PATCH 3/3] minor spacing fixes --- js/block.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/js/block.js b/js/block.js index 5bc4fc129c..cc5d1d5a70 100644 --- a/js/block.js +++ b/js/block.js @@ -1485,8 +1485,10 @@ class Block { let artwork = that.collapseArtwork; _blockMakeBitmap( artwork - .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[that.protoblock.palette.name]) - .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[that.protoblock.palette.name]) + .replace(/fill_color/g, PALETTEHIGHLIGHTCOLORS[ + that.protoblock.palette.name]) + .replace(/stroke_color/g, HIGHLIGHTSTROKECOLORS[ + that.protoblock.palette.name]) .replace("block_label", ""), __processHighlightCollapseBitmap, that); }; @@ -2079,7 +2081,8 @@ class Block { ) { let ci = this.blocks.blockList[c2].connections[1]; let cii = this.blocks.blockList[c2].connections[2]; - if (ci !== null && + if ( + ci !== null && cii !== null && this.blocks.blockList[ci].name === "number" && this.blocks.blockList[cii].name === "number" @@ -3396,8 +3399,8 @@ class Block { piemenuNumber(this, [-2, -1, 0, 1, 2], this.value); } else if (this.blocks.intervalModifierNumber(blk)) { piemenuNumber(this, this.blocks.blockList[ - this.blocks.blockList[this.connections[0] - ].connections[0]].protoblock.piemenuValuesC1, this.value); + this.blocks.blockList[this.connections[0]].connections[0] + ].protoblock.piemenuValuesC1, this.value); } else if (this._usePieNumberC3()) { piemenuNumber(this, this.blocks.blockList[ this.connections[0]].protoblock.piemenuValuesC3, this.value); @@ -3707,6 +3710,7 @@ class Block { // Instead, we do this when we hide the DOM element. // this._checkWidgets(closeInput); + if (this === null || this.label === null) { this._labelLock = false; return;