From 64b25fed5b147e3f863fbfc00862c3e780ccac27 Mon Sep 17 00:00:00 2001 From: kushal khare Date: Sat, 28 Nov 2020 20:05:01 +0530 Subject: [PATCH 01/26] adding classes to palette.js --- js/palette.js | 2192 +++++++++++++++++++++++++------------------------ 1 file changed, 1099 insertions(+), 1093 deletions(-) diff --git a/js/palette.js b/js/palette.js index 53c5092a1c..24d7015610 100644 --- a/js/palette.js +++ b/js/palette.js @@ -34,72 +34,73 @@ function paletteBlockButtonPush(blocks, name, arg) { // loadPaletteMenuItemHandler is the event handler for the palette menu. const NPALETTES = 3; -function Palettes() { - this.blocks = null; - this.cellSize = null; - this.paletteWidth = 55 * PALETTE_WIDTH_FACTOR; - this.scrollDiff = 0; - this.originalSize = 55; // this is the original svg size - this.firstTime = true; - this.background = null; - this.mouseOver = false; - this.activePalette = null; - this.paletteObject = null; - this.paletteVisible = false; - this.pluginsDeleteStatus = false; - this.visible = true; - this.scale = 1.0; - this.mobile = false; - // Top of the palette - this.top = 55 + 20 + LEADING; - this.current = DEFAULTPALETTE; - this.x = []; // We track x and y for each of the multipalettes - this.y = []; - this.showSearchWidget = null; - this.hideSearchWidget = null; - - this.pluginMacros = {}; // some macros are defined in plugins - - if (sugarizerCompatibility.isInsideSugarizer()) { - storage = sugarizerCompatibility.data; - } else { - storage = localStorage; - } - - // The collection of palettes. - this.dict = {}; - this.selectorButtonsOff = []; // Select between palettes - this.selectorButtonsOn = []; // Select between palettes in their on state - this.buttons = {}; // The toolbar button for each palette. - this.labels = {}; // The label for each button. - this.pluginPalettes = []; // List of palettes not in multipalette list - - this.init = function() { - this.halfCellSize = Math.floor(this.cellSize / 2); - }; - - this.init_selectors = function() { - for (let i = 0; i < MULTIPALETTES.length; i++) { - this._makeSelectorButton(i); - } - }; - - this.deltaY = function(dy) { - let curr = parseInt(document.getElementById("palette").style.top); - document.getElementById("palette").style.top = curr + dy +"px" - }; - - this._makeSelectorButton = function(i) { - console.debug("makeSelectorButton " + i); - - if (!document.getElementById("palette")){ - let element = document.createElement("div"); - element.setAttribute("id","palette"); - element.setAttribute("class","disable_highlighting"); - element.setAttribute("style",'position: fixed; display: none ; left :0px; top:'+this.top+'px'); - element.innerHTML ='
' - document.body.appendChild(element); +class Palettes { + constructor() { + this.blocks = null; + this.cellSize = null; + this.paletteWidth = 55 * PALETTE_WIDTH_FACTOR; + this.scrollDiff = 0; + this.originalSize = 55; // this is the original svg size + this.firstTime = true; + this.background = null; + this.mouseOver = false; + this.activePalette = null; + this.paletteObject = null; + this.paletteVisible = false; + this.pluginsDeleteStatus = false; + this.visible = true; + this.scale = 1.0; + this.mobile = false; + // Top of the palette + this.top = 55 + 20 + LEADING; + this.current = DEFAULTPALETTE; + this.x = []; // We track x and y for each of the multipalettes + this.y = []; + this.showSearchWidget = null; + this.hideSearchWidget = null; + + this.pluginMacros = {}; // some macros are defined in plugins + + if (sugarizerCompatibility.isInsideSugarizer()) { + storage = sugarizerCompatibility.data; + } else { + storage = localStorage; } + + // The collection of palettes. + this.dict = {}; + this.selectorButtonsOff = []; // Select between palettes + this.selectorButtonsOn = []; // Select between palettes in their on state + this.buttons = {}; // The toolbar button for each palette. + this.labels = {}; // The label for each button. + this.pluginPalettes = []; // List of palettes not in multipalette list + + this.init = function() { + this.halfCellSize = Math.floor(this.cellSize / 2); + }; + + this.init_selectors = function() { + for (let i = 0; i < MULTIPALETTES.length; i++) { + this._makeSelectorButton(i); + } + }; + + this.deltaY = function(dy) { + let curr = parseInt(document.getElementById("palette").style.top); + document.getElementById("palette").style.top = curr + dy +"px" + }; + + this._makeSelectorButton = function(i) { + console.debug("makeSelectorButton " + i); + + if (!document.getElementById("palette")){ + let element = document.createElement("div"); + element.setAttribute("id","palette"); + element.setAttribute("class","disable_highlighting"); + element.setAttribute("style",'position: fixed; display: none ; left :0px; top:'+this.top+'px'); + element.innerHTML ='
'; + document.body.appendChild(element); + } let palette = document.getElementById("palette"); let tr = palette.children[0].children[0].children[0].children[0]; let td = tr.insertCell(); @@ -111,1159 +112,1164 @@ function Palettes() { platformColor.selectorBackground ) .replace(/stroke_color/g, platformColor.ruleColor) - .replace(/fill_color/g, platformColor.background) - ,1.5*this.cellSize - ,1.5*this.cellSize)) + .replace(/fill_color/g, platformColor.background), + 1.5*this.cellSize, + 1.5*this.cellSize)); td.onmouseover = (evt) =>{ this.showSelection(i,tr); this.makePalettes(i); } - }; - - this.showSelection = (i,tr) => { - //selector menu design. - for (let j = 0; j < MULTIPALETTES.length ; j++) { - let img; - if (j === i) { - img = makePaletteIcons(PALETTEICONS[MULTIPALETTEICONS[j]] - .replace( - "background_fill_color", - platformColor.selectorSelected - ) - .replace(/stroke_color/g, platformColor.ruleColor) - .replace(/fill_color/g, platformColor.background) - ,this.cellSize - ,this.cellSize); - } else { - img = makePaletteIcons(PALETTEICONS[MULTIPALETTEICONS[j]] - .replace( - "background_fill_color", - platformColor.selectorBackground - ) - .replace(/stroke_color/g, platformColor.ruleColor) - .replace(/fill_color/g, platformColor.background) - ,this.cellSize - ,this.cellSize); + }; + + this.showSelection = (i,tr) => { + //selector menu design. + for (let j = 0; j < MULTIPALETTES.length ; j++) { + let img; + if (j === i) { + img = makePaletteIcons(PALETTEICONS[MULTIPALETTEICONS[j]] + .replace( + "background_fill_color", + platformColor.selectorSelected + ) + .replace(/stroke_color/g, platformColor.ruleColor) + .replace(/fill_color/g, platformColor.background) + ,this.cellSize + ,this.cellSize); + } else { + img = makePaletteIcons(PALETTEICONS[MULTIPALETTEICONS[j]] + .replace( + "background_fill_color", + platformColor.selectorBackground + ) + .replace(/stroke_color/g, platformColor.ruleColor) + .replace(/fill_color/g, platformColor.background) + ,this.cellSize + ,this.cellSize); + } + tr.children[j].children[0].src= img.src; } - tr.children[j].children[0].src= img.src; } - } - this.setSize = function(size) { - this.cellSize = Math.floor(size * PALETTE_SCALE_FACTOR + 0.5); - return this; - }; + this.setSize = function(size) { + this.cellSize = Math.floor(size * PALETTE_SCALE_FACTOR + 0.5); + return this; + }; - this.setMobile = function(mobile) { - this.mobile = mobile; - if (mobile) { - this._hideMenus(); - } + this.setMobile = function(mobile) { + this.mobile = mobile; + if (mobile) { + this._hideMenus(); + } - return this; - }; + return this; + }; - this.setBlocksContainer= function(bloc) { - this.blocksContainer = bloc ; - return this; - }; - - // We need access to the macro dictionary because we load them. - this.setMacroDictionary = function(obj) { - this.macroDict = obj; - return this; - }; + this.setBlocksContainer= function(bloc) { + this.blocksContainer = bloc ; + return this; + }; - this.setSearch = function(show, hide) { - this.showSearchWidget = show; - this.hideSearchWidget = hide; - return this; - }; - - this.getSearchPos = function() { - return [this.cellSize, this.top + this.cellSize * 1.75]; - }; - - this.getPluginMacroExpansion = function(blkname, x, y) { - console.debug(this.pluginMacros[blkname]); - let obj = this.pluginMacros[blkname]; - if (obj != null) { - obj[0][2] = x; - obj[0][3] = y; - } + // We need access to the macro dictionary because we load them. + this.setMacroDictionary = function(obj) { + this.macroDict = obj; + return this; + }; - return obj; - }; + this.setSearch = function(show, hide) { + this.showSearchWidget = show; + this.hideSearchWidget = hide; + return this; + }; + + this.getSearchPos = function() { + return [this.cellSize, this.top + this.cellSize * 1.75]; + }; - this.countProtoBlocks = function(name) { - // How many protoblocks are in palette name? - let n = 0; - for (let b in this.blocks.protoBlockDict) { - if (this.blocks.protoBlockDict[b].palette !== null && - this.blocks.protoBlockDict[b].palette.name === name) { - n += 1; + this.getPluginMacroExpansion = function(blkname, x, y) { + console.debug(this.pluginMacros[blkname]); + let obj = this.pluginMacros[blkname]; + if (obj != null) { + obj[0][2] = x; + obj[0][3] = y; } - } - return n; - }; - - this.getProtoNameAndPalette = function(name) { - for (let b in this.blocks.protoBlockDict) { - // Don't return deprecated blocks. - if (name === this.blocks.protoBlockDict[b].name && - !this.blocks.protoBlockDict[b].hidden) { - return [b, this.blocks.protoBlockDict[b].palette.name, - this.blocks.protoBlockDict[b].name]; - } else if (name === b && !this.blocks.protoBlockDict[b].hidden) { - return [b, this.blocks.protoBlockDict[b].palette.name, - this.blocks.protoBlockDict[b].name]; + return obj; + }; + + this.countProtoBlocks = function(name) { + // How many protoblocks are in palette name? + let n = 0; + for (let b in this.blocks.protoBlockDict) { + if (this.blocks.protoBlockDict[b].palette !== null && + this.blocks.protoBlockDict[b].palette.name === name) { + n += 1; + } } - } - return [null, null, null]; - }; - - this.makePalettes = function(i) { - let palette = docById("palette"); - let listBody = palette.children[0].children[1].children[1]; - listBody.parentNode.removeChild(listBody); - listBody = palette.children[0].children[1].appendChild( - document.createElement("tbody")); - // Make an icon/button for each palette - this.makeButton("search", - makePaletteIcons(PALETTEICONS["search"], this.cellSize, - this.cellSize), listBody); - for (let name of MULTIPALETTES[i]) { - if (beginnerMode && SKIPPALETTES.indexOf(name) !== -1) { - continue; + return n; + }; + + this.getProtoNameAndPalette = function(name) { + for (let b in this.blocks.protoBlockDict) { + // Don't return deprecated blocks. + if (name === this.blocks.protoBlockDict[b].name && + !this.blocks.protoBlockDict[b].hidden) { + return [b, this.blocks.protoBlockDict[b].palette.name, + this.blocks.protoBlockDict[b].name]; + } else if (name === b && !this.blocks.protoBlockDict[b].hidden) { + return [b, this.blocks.protoBlockDict[b].palette.name, + this.blocks.protoBlockDict[b].name]; + } } - if (name ==="myblocks" ) { - let n = this.countProtoBlocks("myblocks"); - if (n === 0) { + + return [null, null, null]; + }; + + this.makePalettes = function(i) { + let palette = docById("palette"); + let listBody = palette.children[0].children[1].children[1]; + listBody.parentNode.removeChild(listBody); + listBody = palette.children[0].children[1].appendChild( + document.createElement("tbody")); + // Make an icon/button for each palette + this.makeButton("search", + makePaletteIcons(PALETTEICONS["search"], this.cellSize, + this.cellSize), listBody); + for (let name of MULTIPALETTES[i]) { + if (beginnerMode && SKIPPALETTES.indexOf(name) !== -1) { continue; } + if (name ==="myblocks" ) { + let n = this.countProtoBlocks("myblocks"); + if (n === 0) { + continue; + } + } + this.makeButton(name, + makePaletteIcons(PALETTEICONS[name], this.cellSize, + this.cellSize), listBody); + } + }; + + this.makeButton = function (name,icon,listBody){ + let row = listBody.insertRow(-1); + let img = row.insertCell(-1); + let label = row.insertCell(-1); + img.appendChild(icon); + // Add tooltip for palette buttons + row.setAttribute("style","width: 126px"); + if (localStorage.kanaPreference === "kana") { + label.textContent = toTitleCase(_(name)) ; + label.setAttribute( + "style", "font-size: 12px; color:platformColor.paletteText"); + } else { + label.textContent = toTitleCase(_(name)) ; + label.setAttribute( + "style", "font-size: 16px; color:platformColor.paletteText"); } - this.makeButton(name, - makePaletteIcons(PALETTEICONS[name], this.cellSize, - this.cellSize), listBody); - } - }; - - this.makeButton = function (name,icon,listBody){ - let row = listBody.insertRow(-1); - let img = row.insertCell(-1); - let label = row.insertCell(-1); - img.appendChild(icon); - // Add tooltip for palette buttons - row.setAttribute("style","width: 126px"); - if (localStorage.kanaPreference === "kana") { - label.textContent = toTitleCase(_(name)) ; - label.setAttribute( - "style", "font-size: 12px; color:platformColor.paletteText"); - } else { - label.textContent = toTitleCase(_(name)) ; - label.setAttribute( - "style", "font-size: 16px; color:platformColor.paletteText"); - } - this._loadPaletteButtonHandler(name,row); - }; + this._loadPaletteButtonHandler(name,row); + }; - this.showPalette = function(name) { - if (this.mobile) { - return; - } + this.showPalette = function(name) { + if (this.mobile) { + return; + } - this.hideSearchWidget(true); - this.dict[name].showMenu(true); - }; + this.hideSearchWidget(true); + this.dict[name].showMenu(true); + }; - this._showMenus = function() { - }; + this._showMenus = function() { + }; - this._hideMenus = function() { - // Hide the menu buttons and the palettes themselves. + this._hideMenus = function() { + // Hide the menu buttons and the palettes themselves. - this.hideSearchWidget(true); + this.hideSearchWidget(true); - if (docById("PaletteBody")) - docById("PaletteBody").parentNode.removeChild(docById("PaletteBody")); - - }; + if (docById("PaletteBody")) + docById("PaletteBody").parentNode.removeChild(docById("PaletteBody")); - this.getInfo = function() { - for (let key in this.dict) { - console.debug(this.dict[key].getInfo()); - } - }; - - this.updatePalettes = function(showPalette) { - if (showPalette != null) { - // Show the action palette after adding/deleting new - // nameddo blocks. - if (showPalette in this.dict){ - let wasOpen = false; - if (docById("PaletteBody")) { - wasOpen = true; - } + }; - this.dict[showPalette].hideMenu(); + this.getInfo = function() { + for (let key in this.dict) { + console.debug(this.dict[key].getInfo()); + } + }; + + this.updatePalettes = function(showPalette) { + if (showPalette != null) { + // Show the action palette after adding/deleting new + // nameddo blocks. + if (showPalette in this.dict){ + let wasOpen = false; + if (docById("PaletteBody")) { + wasOpen = true; + } + + this.dict[showPalette].hideMenu(); - if (wasOpen) { - this.dict[showPalette].show(); + if (wasOpen) { + this.dict[showPalette].show(); + } } } - } - if (this.mobile) { - this.hide(); - } - }; + if (this.mobile) { + this.hide(); + } + }; - this.hide = function() { - docById("palette").style.visibility = "hidden"; - }; + this.hide = function() { + docById("palette").style.visibility = "hidden"; + }; - this.show = function() { - docById("palette").style.visibility = "visible"; - }; + this.show = function() { + docById("palette").style.visibility = "visible"; + }; - this.setBlocks = function(blocks) { - this.blocks = blocks; - return this; - }; + this.setBlocks = function(blocks) { + this.blocks = blocks; + return this; + }; - this.add = function(name) { - this.dict[name] = new Palette(this, name); - return this; - }; + this.add = function(name) { + this.dict[name] = new Palette(this, name); + return this; + }; - // Palette Button event handlers - this._loadPaletteButtonHandler = function(name,row) { - row.onmouseover = (evt) => { - document.body.style.cursor = "pointer"; - } - row.onclick = (evt) => { - if (name == "search") { - this.showSearchWidget(); - } else { - this.showPalette(name) + // Palette Button event handlers + this._loadPaletteButtonHandler = function(name, row) { + row.onmouseover = (evt) => { + document.body.style.cursor = "pointer"; + } + row.onclick = (evt) => { + if (name == "search") { + this.showSearchWidget(); + } else { + this.showPalette(name) + } + } + row.onmouseup = (evt) => { + document.body.style.cursor = "default"; + } + row.onmouseleave = (evt) => { + document.body.style.cursor = "default"; } - } - row.onmouseup = (evt) => { - document.body.style.cursor = "default"; - } - row.onmouseleave = (evt) => { - document.body.style.cursor = "default"; - } - }; - - this.removeActionPrototype = function(actionName) { - let blockRemoved = false; - for (let blk = 0; blk < this.dict["action"].protoList.length; blk++) { - let actionBlock = this.dict["action"].protoList[blk]; - if (["nameddo", "namedcalc", "nameddoArg", "namedcalcArg"].indexOf( - actionBlock.name) !== -1 && - actionBlock.defaults[0] === actionName) { - // Remove the palette protoList entry for this block. - this.dict["action"].remove(actionBlock, actionName); - - // And remove it from the protoBlock dictionary. - if (this.blocks.protoBlockDict["myDo_" + actionName]) { - delete this.blocks.protoBlockDict["myDo_" + actionName]; - } else if (this.blocks.protoBlockDict["myCalc_" + actionName]) { - delete this.blocks.protoBlockDict["myCalc_" + actionName]; - } else if (this.blocks.protoBlockDict[ - "myDoArg_" + actionName]) { - delete this.blocks.protoBlockDict["myDoArg_" + actionName]; - } else if (this.blocks.protoBlockDict[ - "myCalcArg_" + actionName]) { - delete this.blocks.protoBlockDict[ - "myCalcArg_" + actionName]; + }; + + this.removeActionPrototype = function(actionName) { + let blockRemoved = false; + for (let blk = 0; blk < this.dict["action"].protoList.length; blk++) { + let actionBlock = this.dict["action"].protoList[blk]; + if (["nameddo", "namedcalc", "nameddoArg", "namedcalcArg"].indexOf( + actionBlock.name) !== -1 && + actionBlock.defaults[0] === actionName) { + // Remove the palette protoList entry for this block. + this.dict["action"].remove(actionBlock, actionName); + + // And remove it from the protoBlock dictionary. + if (this.blocks.protoBlockDict["myDo_" + actionName]) { + delete this.blocks.protoBlockDict["myDo_" + actionName]; + } else if (this.blocks.protoBlockDict["myCalc_" + actionName]) { + delete this.blocks.protoBlockDict["myCalc_" + actionName]; + } else if (this.blocks.protoBlockDict[ + "myDoArg_" + actionName]) { + delete this.blocks.protoBlockDict["myDoArg_" + actionName]; + } else if (this.blocks.protoBlockDict[ + "myCalcArg_" + actionName]) { + delete this.blocks.protoBlockDict[ + "myCalcArg_" + actionName]; + } + blockRemoved = true; + break; } - blockRemoved = true; - break; } - } - // Force an update if a block was removed. - if (blockRemoved) { - this.updatePalettes("action"); - } - }; + // Force an update if a block was removed. + if (blockRemoved) { + this.updatePalettes("action"); + } + }; - return this; + return this; + } } // Kind of a model, but it only keeps a list of SVGs -function PaletteModel(palette, palettes, name) { - this.palette = palette; - this.palettes = palettes; - this.name = name; - this.blocks = []; - - this.update = function() { +class PaletteModel { + constructor(palette, palettes, name) { + this.palette = palette; + this.palettes = palettes; + this.name = name; this.blocks = []; - for (let blk in this.palette.protoList) { - let block = this.palette.protoList[blk]; - // Don't show hidden blocks on the menus - // But we still make them. - // if (block.hidden) { - // continue; - // } - - // Create a proto block for each palette entry. - this.blocks.push(this.makeBlockInfo(blk, block, block.name, - block.name)); - } - }; - - this.makeBlockInfo = function(blk, block, blkname, modname) { - let arg; - switch (blkname) { - // Use the name of the action in the label - case "storein": - modname = "store in " + block.defaults[0]; - arg = block.defaults[0]; - break; - case "storein2": - modname = "store in2 " + block.staticLabels[0]; - arg = block.staticLabels[0]; - break; - case "box": - modname = block.defaults[0]; - arg = block.defaults[0]; - break; - case "namedbox": - if (block.defaults[0] === undefined) { - modname = "namedbox"; - arg = _("box"); - } else { - modname = block.defaults[0]; - arg = block.defaults[0]; - } - break; - case "namedarg": - if (block.defaults[0] === undefined) { - modname = "namedarg"; - arg = "1"; - } else { - modname = block.defaults[0]; - arg = block.defaults[0]; - } - break; - case "nameddo": - if (block.defaults[0] === undefined) { - modname = "nameddo"; - arg = _("action"); - } else { - modname = block.defaults[0]; - arg = block.defaults[0]; - } - break; - case "nameddoArg": - if (block.defaults[0] === undefined) { - modname = "nameddoArg"; - arg = _("action"); - } else { - modname = block.defaults[0]; - arg = block.defaults[0]; - } - break; - case "namedcalc": - if (block.defaults[0] === undefined) { - modname = "namedcalc"; - arg = _("action"); - } else { - modname = block.defaults[0]; - arg = block.defaults[0]; - } - break; - case "namedcalcArg": - if (block.defaults[0] === undefined) { - modname = "namedcalcArg"; - arg = _("action"); - } else { - modname = block.defaults[0]; - arg = block.defaults[0]; - } - break; - } - let protoBlock = this.palettes.blocks.protoBlockDict[blkname]; - if (protoBlock === null) { - console.debug("Could not find block " + blkname); - } + this.update = function() { + this.blocks = []; + for (let blk in this.palette.protoList) { + let block = this.palette.protoList[blk]; + // Don't show hidden blocks on the menus + // But we still make them. + // if (block.hidden) { + // continue; + // } + + // Create a proto block for each palette entry. + this.blocks.push(this.makeBlockInfo(blk, block, block.name, + block.name)); + } + }; - let label = ""; - switch (protoBlock.name) { - case "grid": - label = _("grid"); - break; - case "text": - label = _("text"); - break; - case "drumname": - label = _("drum"); - break; - case "effectsname": - label = _("effect"); - break; - case "solfege": - label = i18nSolfege("sol"); - break; - case "eastindiansolfege": - label = _("sargam"); - break; - case "scaledegree2": - label = _("scale degree"); - break; - case "modename": - label = _("mode name"); - break; - case "invertmode": - label = _("invert mode"); - break; - case "voicename": - label = _("voice name"); - break; - case "customNote": - label = _("custom pitch"); - break; - case "temperamentname": - //TRANS: https://en.wikipedia.org/wiki/Musical_temperament - label = _("temperament"); - break; - case "accidentalname": - //TRANS: accidental refers to sharps, flats, etc. - label = _("accidental"); - break; - case "notename": - label = "G"; - break; - case "intervalname": - label = _("interval name"); - break; - case "boolean": - label = _("true"); - break; - case "number": - label = NUMBERBLOCKDEFAULT.toString(); - break; - case "less": - case "greater": - case "equal": - // Label should be inside _() when defined. - label = protoBlock.staticLabels[0]; - break; - case "namedarg": - label = "arg " + arg; - break; - case "outputtools": - label = _("pitch converter"); - break; - default: - if (blkname != modname) { - // Override label for do, storein, box, and namedarg - if (blkname === "storein" && block.defaults[0] === _("box")) { - label = _("store in"); - } else if (blkname === "storein2") { - if (block.staticLabels[0] === _("store in box")) { - label = _("store in box"); + this.makeBlockInfo = function(blk, block, blkname, modname) { + let arg; + switch (blkname) { + // Use the name of the action in the label + case "storein": + modname = "store in " + block.defaults[0]; + arg = block.defaults[0]; + break; + case "storein2": + modname = "store in2 " + block.staticLabels[0]; + arg = block.staticLabels[0]; + break; + case "box": + modname = block.defaults[0]; + arg = block.defaults[0]; + break; + case "namedbox": + if (block.defaults[0] === undefined) { + modname = "namedbox"; + arg = _("box"); } else { - label = _("store in") + " " + block.staticLabels[0]; + modname = block.defaults[0]; + arg = block.defaults[0]; } - } else { - label = block.defaults[0]; - } - } else if (protoBlock.staticLabels.length > 0) { - label = protoBlock.staticLabels[0]; - if (label === "") { - if (blkname === "loadFile") { - label = _("open file"); + break; + case "namedarg": + if (block.defaults[0] === undefined) { + modname = "namedarg"; + arg = "1"; + } else { + modname = block.defaults[0]; + arg = block.defaults[0]; + } + break; + case "nameddo": + if (block.defaults[0] === undefined) { + modname = "nameddo"; + arg = _("action"); + } else { + modname = block.defaults[0]; + arg = block.defaults[0]; + } + break; + case "nameddoArg": + if (block.defaults[0] === undefined) { + modname = "nameddoArg"; + arg = _("action"); + } else { + modname = block.defaults[0]; + arg = block.defaults[0]; + } + break; + case "namedcalc": + if (block.defaults[0] === undefined) { + modname = "namedcalc"; + arg = _("action"); + } else { + modname = block.defaults[0]; + arg = block.defaults[0]; + } + break; + case "namedcalcArg": + if (block.defaults[0] === undefined) { + modname = "namedcalcArg"; + arg = _("action"); + } else { + modname = block.defaults[0]; + arg = block.defaults[0]; + } + break; + } + + let protoBlock = this.palettes.blocks.protoBlockDict[blkname]; + if (protoBlock === null) { + console.debug("Could not find block " + blkname); + } + + let label = ""; + switch (protoBlock.name) { + case "grid": + label = _("grid"); + break; + case "text": + label = _("text"); + break; + case "drumname": + label = _("drum"); + break; + case "effectsname": + label = _("effect"); + break; + case "solfege": + label = i18nSolfege("sol"); + break; + case "eastindiansolfege": + label = _("sargam"); + break; + case "scaledegree2": + label = _("scale degree"); + break; + case "modename": + label = _("mode name"); + break; + case "invertmode": + label = _("invert mode"); + break; + case "voicename": + label = _("voice name"); + break; + case "customNote": + label = _("custom pitch"); + break; + case "temperamentname": + //TRANS: https://en.wikipedia.org/wiki/Musical_temperament + label = _("temperament"); + break; + case "accidentalname": + //TRANS: accidental refers to sharps, flats, etc. + label = _("accidental"); + break; + case "notename": + label = "G"; + break; + case "intervalname": + label = _("interval name"); + break; + case "boolean": + label = _("true"); + break; + case "number": + label = NUMBERBLOCKDEFAULT.toString(); + break; + case "less": + case "greater": + case "equal": + // Label should be inside _() when defined. + label = protoBlock.staticLabels[0]; + break; + case "namedarg": + label = "arg " + arg; + break; + case "outputtools": + label = _("pitch converter"); + break; + default: + if (blkname != modname) { + // Override label for do, storein, box, and namedarg + if (blkname === "storein" && block.defaults[0] === _("box")) { + label = _("store in"); + } else if (blkname === "storein2") { + if (block.staticLabels[0] === _("store in box")) { + label = _("store in box"); + } else { + label = _("store in") + " " + block.staticLabels[0]; + } + } else { + label = block.defaults[0]; + } + } else if (protoBlock.staticLabels.length > 0) { + label = protoBlock.staticLabels[0]; + if (label === "") { + if (blkname === "loadFile") { + label = _("open file"); + } else { + label = blkname; + } + } } else { label = blkname; } - } - } else { - label = blkname; } - } - if (["do", - "nameddo", - "namedbox", - "namedcalc", - "doArg", - "calcArg", - "nameddoArg", - "namedcalcArg"].indexOf(protoBlock.name) != -1 && label != null) { - if (getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { - label = label.substr(0, STRINGLEN) + "..."; + if (["do", + "nameddo", + "namedbox", + "namedcalc", + "doArg", + "calcArg", + "nameddoArg", + "namedcalcArg"].indexOf(protoBlock.name) != -1 && label != null) { + if (getTextWidth(label, "bold 20pt Sans") > TEXTWIDTH) { + label = label.substr(0, STRINGLEN) + "..."; + } } - } - // Don't display the label on image blocks. - if (protoBlock.image) { - label = ""; - } + // Don't display the label on image blocks. + if (protoBlock.image) { + label = ""; + } - let saveScale = protoBlock.scale; - protoBlock.scale = DEFAULTBLOCKSCALE; - - // Finally, the SVGs! - let svg; - let artwork; - let docks; - let height; - switch (protoBlock.name) { - case "namedbox": - case "namedarg": - // so the label will fit - svg = new SVG(); - svg.init(); - svg.setScale(protoBlock.scale); - svg.setExpand(60, 0, 0, 0); - svg.setOutie(true); - artwork = svg.basicBox(); - docks = svg.docks; - height = svg.getHeight(); - break; - case "nameddo": - // so the label will fit - svg = new SVG(); - svg.init(); - svg.setScale(protoBlock.scale); - svg.setExpand(60, 0, 0, 0); - artwork = svg.basicBlock(); - docks = svg.docks; - height = svg.getHeight(); - break; - default: - let obj = protoBlock.generator(); - artwork = obj[0]; - docks = obj[1]; - height = obj[3]; - break; - } + let saveScale = protoBlock.scale; + protoBlock.scale = DEFAULTBLOCKSCALE; + + // Finally, the SVGs! + let svg; + let artwork; + let docks; + let height; + switch (protoBlock.name) { + case "namedbox": + case "namedarg": + // so the label will fit + svg = new SVG(); + svg.init(); + svg.setScale(protoBlock.scale); + svg.setExpand(60, 0, 0, 0); + svg.setOutie(true); + artwork = svg.basicBox(); + docks = svg.docks; + height = svg.getHeight(); + break; + case "nameddo": + // so the label will fit + svg = new SVG(); + svg.init(); + svg.setScale(protoBlock.scale); + svg.setExpand(60, 0, 0, 0); + artwork = svg.basicBlock(); + docks = svg.docks; + height = svg.getHeight(); + break; + default: + let obj = protoBlock.generator(); + artwork = obj[0]; + docks = obj[1]; + height = obj[3]; + break; + } - protoBlock.scale = saveScale; + protoBlock.scale = saveScale; - if (protoBlock.disabled) { - artwork = artwork - .replace(/fill_color/g, DISABLEDFILLCOLOR) - .replace(/stroke_color/g, DISABLEDSTROKECOLOR) - .replace("block_label", safeSVG(label)); - } else { - artwork = artwork - .replace(/fill_color/g, - PALETTEFILLCOLORS[protoBlock.palette.name]) - .replace(/stroke_color/g, - PALETTESTROKECOLORS[protoBlock.palette.name]) - .replace("block_label", safeSVG(label)); - } + if (protoBlock.disabled) { + artwork = artwork + .replace(/fill_color/g, DISABLEDFILLCOLOR) + .replace(/stroke_color/g, DISABLEDSTROKECOLOR) + .replace("block_label", safeSVG(label)); + } else { + artwork = artwork + .replace(/fill_color/g, + PALETTEFILLCOLORS[protoBlock.palette.name]) + .replace(/stroke_color/g, + PALETTESTROKECOLORS[protoBlock.palette.name]) + .replace("block_label", safeSVG(label)); + } - for (let i = 0; i <= protoBlock.args; i++) { - artwork = artwork.replace("arg_label_" + i, - protoBlock.staticLabels[i] || ""); - } + for (let i = 0; i <= protoBlock.args; i++) { + artwork = artwork.replace("arg_label_" + i, + protoBlock.staticLabels[i] || ""); + } - return { - blk, - blkname, - modname, - height: STANDARDBLOCKHEIGHT, - actualHeight: height, - label, - artwork, - artwork64: "data:image/svg+xml;base64," + - window.btoa(unescape(encodeURIComponent(artwork))), - docks, - image: block.image, - scale: block.scale, - palettename: this.palette.name, - hidden: block.hidden + return { + blk, + blkname, + modname, + height: STANDARDBLOCKHEIGHT, + actualHeight: height, + label, + artwork, + artwork64: "data:image/svg+xml;base64," + + window.btoa(unescape(encodeURIComponent(artwork))), + docks, + image: block.image, + scale: block.scale, + palettename: this.palette.name, + hidden: block.hidden + }; }; } } // Define objects for individual palettes. -function Palette(palettes, name) { - this.palettes = palettes; - this.name = name; - this.model = new PaletteModel(this, palettes, name); - this.visible = false; - this.menuContainer = null; - this.protoList = []; - this.protoContainers = {}; - this.protoHeights = {}; - this.background = null; - this.size = 0; - this.columns = 0; - this.draggingProtoBlock = false; - this.mouseHandled = false; - this.upButton = null; - this.downButton = null; - this.fadedUpButton = null; - this.fadedDownButton = null; - this.count = 0; - - this.hide = function() { - this.hideMenu(); - }; - - this.show = function() { - this.showMenu(true); - }; - - this.hideMenu = function() { - this._hideMenuItems(); - }; - - this.showMenu = function(createHeader) { - - let palDiv = docById("palette"); - if (docById("PaletteBody")) - palDiv.removeChild(docById("PaletteBody")); - let x = document.createElement("table"); - x.setAttribute("id","PaletteBody") - x.setAttribute("bgcolor","white"); - x.setAttribute("style","float: left"); - x.innerHTML= '' - palDiv.appendChild(x) - - let buttonContainers = document.createDocumentFragment(); - let down = makePaletteIcons(DOWNICON,15,15); - down.style.position = "relative"; - down.style.left = "-10px"; - down.style.top = (window.innerHeight-this.palettes.top-this.palettes.cellSize-20)+"px"; - buttonContainers.appendChild(down); - - this.menuContainer=x ; - docById("PaletteBody_items").onscroll = () => { - let list = docById("PaletteBody_items"); - if( list.scrollTop >= (list.scrollHeight - list.offsetHeight)){ - down.style.visibility = "hidden"; - } else { - down.style.visibility = "visible"; - } - } - - if (createHeader) { - let header = this.menuContainer.children[0]; - header = header.insertRow(); - header.style.background = platformColor.selectorSelected; - header.innerHTML=''; - header = header.children[0]; - let closeImg = makePaletteIcons( - CLOSEICON.replace("fill_color", platformColor.selectorSelected), - this.palettes.cellSize, - this.palettes.cellSize, - ); - closeImg.onclick = () => { - palDiv.removeChild(x); - } - let labelImg = makePaletteIcons( - PALETTEICONS[name], - this.palettes.cellSize, - this.palettes.cellSize, - ); - closeImg.onmouseover = (evt) => { - document.body.style.cursor = "pointer"; - } - closeImg.onmouseleave = (evt) => { - document.body.style.cursor = "default"; - } - header.appendChild(labelImg); - - let label = document.createElement("span"); - label.textContent = toTitleCase(_(this.name)); - header.appendChild(label); +class Palette { + constructor(palettes, name) { + this.palettes = palettes; + this.name = name; + this.model = new PaletteModel(this, palettes, name); + this.visible = false; + this.menuContainer = null; + this.protoList = []; + this.protoContainers = {}; + this.protoHeights = {}; + this.background = null; + this.size = 0; + this.columns = 0; + this.draggingProtoBlock = false; + this.mouseHandled = false; + this.upButton = null; + this.downButton = null; + this.fadedUpButton = null; + this.fadedDownButton = null; + this.count = 0; + + this.hide = function() { + this.hideMenu(); + }; - let closeDownImg = document.createElement("span"); - closeDownImg.appendChild(closeImg); - closeDownImg.appendChild(buttonContainers) ; - closeDownImg.style = "float: right;"; + this.show = function() { + this.showMenu(true); + }; - header.appendChild(closeDownImg) - } + this.hideMenu = function() { + this._hideMenuItems(); + }; - this._showMenuItems(); - }; + this.showMenu = function(createHeader) { + + let palDiv = docById("palette"); + if (docById("PaletteBody")) + palDiv.removeChild(docById("PaletteBody")); + let x = document.createElement("table"); + x.setAttribute("id","PaletteBody"); + x.setAttribute("bgcolor","white"); + x.setAttribute("style","float: left"); + x.innerHTML = ''; + palDiv.appendChild(x); + + let buttonContainers = document.createDocumentFragment(); + let down = makePaletteIcons(DOWNICON,15,15); + down.style.position = "relative"; + down.style.left = "-10px"; + down.style.top = (window.innerHeight-this.palettes.top-this.palettes.cellSize-20)+"px"; + buttonContainers.appendChild(down); + + this.menuContainer=x ; + docById("PaletteBody_items").onscroll = () => { + let list = docById("PaletteBody_items"); + if( list.scrollTop >= (list.scrollHeight - list.offsetHeight)){ + down.style.visibility = "hidden"; + } else { + down.style.visibility = "visible"; + } + } - this._hideMenuItems = function() { - if (this.name === "search" && this.palettes.hideSearchWidget !== null) { - this.palettes.hideSearchWidget(true); - } - if (docById("PaletteBody")) - docById("palette").removeChild(docById("PaletteBody")); - }; + if (createHeader) { + let header = this.menuContainer.children[0]; + header = header.insertRow(); + header.style.background = platformColor.selectorSelected; + header.innerHTML=''; + header = header.children[0]; + let closeImg = makePaletteIcons( + CLOSEICON.replace("fill_color", platformColor.selectorSelected), + this.palettes.cellSize, + this.palettes.cellSize, + ); + closeImg.onclick = () => { + palDiv.removeChild(x); + } + let labelImg = makePaletteIcons( + PALETTEICONS[name], + this.palettes.cellSize, + this.palettes.cellSize, + ); + closeImg.onmouseover = (evt) => { + document.body.style.cursor = "pointer"; + } + closeImg.onmouseleave = (evt) => { + document.body.style.cursor = "default"; + } + header.appendChild(labelImg); - this._showMenuItems = function() { + let label = document.createElement("span"); + label.textContent = toTitleCase(_(this.name)); + header.appendChild(label); - this.model.update(); - let paletteList = docById("PaletteBody_items"); - let padding = paletteList.insertRow(); - padding.style.height = "7px"; + let closeDownImg = document.createElement("span"); + closeDownImg.appendChild(closeImg); + closeDownImg.appendChild(buttonContainers) ; + closeDownImg.style = "float: right;"; - this.setupGrabScroll(paletteList); + header.appendChild(closeDownImg) + } - let blocks = this.model.blocks; - blocks.reverse(); - let protoListScope = [...this.protoList] ; - if (last(blocks).blkname != last(protoListScope).name) - protoListScope.reverse(); - for (let blk in blocks) { - let b = blocks[blk]; + this._showMenuItems(); + }; - if (b.hidden) { - continue; - } - let itemRow = paletteList.insertRow(); - let itemCell = itemRow.insertCell(); - let right = itemRow.insertCell() - right.innerHTML ="   " - let that = this ; - let img = makePaletteIcons( - b.artwork - ); - - // Use artwork.js strings as images for: - // cameraPALETTE, videoPALETTE, mediaPALETTE - if (b.image){ - img = makePaletteIcons(eval(b.blkname+"PALETTE")); + this._hideMenuItems = function() { + if (this.name === "search" && this.palettes.hideSearchWidget !== null) { + this.palettes.hideSearchWidget(true); } + if (docById("PaletteBody")) + docById("palette").removeChild(docById("PaletteBody")); + }; - img.onmouseover = (evt) => { - document.body.style.cursor = "pointer"; - } + this._showMenuItems = function() { - img.onmouseleave = (evt) => { - document.body.style.cursor = "default"; - } + this.model.update(); + let paletteList = docById("PaletteBody_items"); + let padding = paletteList.insertRow(); + padding.style.height = "7px"; - // Image Drag initiates a browser defined drag, - // which needs to be stoped. - img.ondragstart = function() { - return false; - }; + this.setupGrabScroll(paletteList); + + let blocks = this.model.blocks; + blocks.reverse(); + let protoListScope = [...this.protoList] ; + if (last(blocks).blkname != last(protoListScope).name) + protoListScope.reverse(); + for (let blk in blocks) { + let b = blocks[blk]; - let down = function(event){ - // (1) prepare to moving: make absolute and on top by z-index - let posit = img.style.position ; - let zInd = img.style.zIndex ; - img.style.position = 'absolute'; - img.style.zIndex = 1000; - - // move it out of any current parents directly into body - // to make it positioned relative to the body - document.body.appendChild(img); - - // centers the img at (pageX, pageY) coordinates - moveAt = (pageX, pageY) => { - img.style.left = pageX - img.offsetWidth / 2 + 'px'; - img.style.top = pageY - img.offsetHeight / 2 + 'px'; + if (b.hidden) { + continue; } - - let onMouseMove = (e) => { - let x, y; - if (e.type === "touchmove"){ - x = e.touches[0].clientX; - y = e.touches[0].clientY; - } else { - x = e.pageX; - y = e.pageY; - } - moveAt(x, y); + let itemRow = paletteList.insertRow(); + let itemCell = itemRow.insertCell(); + let right = itemRow.insertCell(); + right.innerHTML ="   "; + let that = this ; + let img = makePaletteIcons( + b.artwork + ); + + // Use artwork.js strings as images for: + // cameraPALETTE, videoPALETTE, mediaPALETTE + if (b.image){ + img = makePaletteIcons(eval(b.blkname+"PALETTE")); } - onMouseMove(event) - - document.addEventListener('touchmove', onMouseMove); - document.addEventListener('mousemove', onMouseMove); - - let up = function (event) { - document.body.style.cursor = "default"; - document.removeEventListener('mousemove', onMouseMove); - img.onmouseup = null; - - let x, y; - x = parseInt (img.style.left); - y = parseInt (img.style.top); - - img.style.position = posit; - img.style.zIndex = zInd; - document.body.removeChild(img); - itemCell.appendChild(img); - - if (!x || !y) return; - - that._makeBlockFromProtoblock( - protoListScope[blk], - true, - b.modname, - event, - x - that.palettes.blocksContainer.x, - y - that.palettes.blocksContainer.y - ); - }; - img.ontouchend = up; - img.onmouseup = up; - }; + img.onmouseover = (evt) => { + document.body.style.cursor = "pointer"; + } - img.ontouchstart = down; - img.onmousedown = down; - - itemCell.setAttribute("style","width: "+img.width+"px "); - itemCell.appendChild(img) - } + img.onmouseleave = (evt) => { + document.body.style.cursor = "default"; + } - if (this.palettes.mobile) { - this.hide(); - } + // Image Drag initiates a browser defined drag, + // which needs to be stoped. + img.ondragstart = function() { + return false; + }; - }; + let down = function(event){ + // (1) prepare to moving: make absolute and on top by z-index + let posit = img.style.position ; + let zInd = img.style.zIndex ; + img.style.position = 'absolute'; + img.style.zIndex = 1000; + + // move it out of any current parents directly into body + // to make it positioned relative to the body + document.body.appendChild(img); + + // centers the img at (pageX, pageY) coordinates + const moveAt = (pageX, pageY) => { + img.style.left = pageX - img.offsetWidth / 2 + 'px'; + img.style.top = pageY - img.offsetHeight / 2 + 'px'; + } - this.setupGrabScroll = (paletteList) => { - let posY,top; - - let mouseUpGrab = (evt) => { - paletteList.onmousemove= null ; - document.body.style.cursor = "default"; - }; - let mouseMoveGrab = (evt) => { - let dy = evt.clientY - posY; - paletteList.scrollTop = top - dy; - document.body.style.cursor = "grabbing"; - }; - let mouseDownGrab = (evt) => { - posY = evt.clientY - top = paletteList.scrollTop; + let onMouseMove = (e) => { + let x, y; + if (e.type === "touchmove"){ + x = e.touches[0].clientX; + y = e.touches[0].clientY; + } else { + x = e.pageX; + y = e.pageY; + } + moveAt(x, y); + } + onMouseMove(event); + + document.addEventListener('touchmove', onMouseMove); + document.addEventListener('mousemove', onMouseMove); + + let up = function (event) { + document.body.style.cursor = "default"; + document.removeEventListener('mousemove', onMouseMove); + img.onmouseup = null; + + let x, y; + x = parseInt (img.style.left); + y = parseInt (img.style.top); + + img.style.position = posit; + img.style.zIndex = zInd; + document.body.removeChild(img); + itemCell.appendChild(img); + + if (!x || !y) return; + + that._makeBlockFromProtoblock( + protoListScope[blk], + true, + b.modname, + event, + x - that.palettes.blocksContainer.x, + y - that.palettes.blocksContainer.y + ); + }; + + img.ontouchend = up; + img.onmouseup = up; + }; - paletteList.onmousemove = mouseMoveGrab; - paletteList.onmouseup = mouseUpGrab; - paletteList.onmouseleave = mouseUpGrab; - }; - paletteList.onmousedown = mouseDownGrab; - } + img.ontouchstart = down; + img.onmousedown = down; - this.getInfo = function() { - let returnString = this.name + " palette:"; - for (let thisBlock in this.protoList) { - returnString += " " + this.protoList[thisBlock].name; - } - return returnString; - }; - - this.remove = function(protoblock, name) { - // Remove the protoblock and its associated artwork container. - let i = this.protoList.indexOf(protoblock); - if (i !== -1) { - this.protoList.splice(i, 1); - } + itemCell.setAttribute("style","width: "+img.width+"px "); + itemCell.appendChild(img); + } - for (let i = 0; i < this.model.blocks.length; i++) { - if (["nameddo", "nameddoArg", "namedcalc", "namedcalcArg"].indexOf( - this.model.blocks[i].blkname) !== -1 && - this.model.blocks[i].modname === name) { - this.model.blocks.splice(i, 1); - break; - } else if ( - ["storein"].indexOf(this.model.blocks[i].blkname) !== -1 && - this.model.blocks[i].modname === _("store in") + " " + name) { - this.model.blocks.splice(i, 1); - break; + if (this.palettes.mobile) { + this.hide(); } - } - }; + }; - this.add = function(protoblock, top) { - // Add a new palette entry to the end of the list (default) or - // to the top. - if (this.protoList.indexOf(protoblock) === -1) { - if (top)this.protoList.push(protoblock); - else this.protoList.push(protoblock); - } - return this; - }; + this.setupGrabScroll = (paletteList) => { + let posY,top; - this.makeBlockFromSearch = function(protoblk, blkname, callback) { - this._makeBlockFromPalette(protoblk, blkname, callback); - this.palettes.hideSearchWidget(); - }; + let mouseUpGrab = (evt) => { + paletteList.onmousemove= null ; + document.body.style.cursor = "default"; + }; + let mouseMoveGrab = (evt) => { + let dy = evt.clientY - posY; + paletteList.scrollTop = top - dy; + document.body.style.cursor = "grabbing"; + }; + let mouseDownGrab = (evt) => { + posY = evt.clientY; + top = paletteList.scrollTop; - this._makeBlockFromPalette = function(protoblk, blkname, callback) { - if (protoblk === null) { - console.debug("null protoblk?"); - return; + paletteList.onmousemove = mouseMoveGrab; + paletteList.onmouseup = mouseUpGrab; + paletteList.onmouseleave = mouseUpGrab; + }; + paletteList.onmousedown = mouseDownGrab; } - let newBlk; - let arg; - switch (protoblk.name) { - case "do": - blkname = "do " + protoblk.defaults[0]; - newBlk = protoblk.name; - arg = protoblk.defaults[0]; - break; - case "storein": - // Use the name of the box in the label - blkname = "store in " + protoblk.defaults[0]; - newBlk = protoblk.name; - arg = protoblk.defaults[0]; - break; - case "storein2": - // Use the name of the box in the label - console.debug("storein2" + " " + protoblk.defaults[0] + " " + - protoblk.staticLabels[0]); - blkname = "store in2 " + protoblk.defaults[0]; - newBlk = protoblk.name; - arg = protoblk.staticLabels[0]; - break; - case "box": - // Use the name of the box in the label - blkname = protoblk.defaults[0]; - newBlk = protoblk.name; - arg = protoblk.defaults[0]; - break; - case "namedbox": - // Use the name of the box in the label - if (protoblk.defaults[0] === undefined) { - blkname = "namedbox"; - arg = _("box"); - } else { - console.debug(protoblk.defaults[0]); - blkname = protoblk.defaults[0]; - arg = protoblk.defaults[0]; + this.getInfo = function() { + let returnString = this.name + " palette:"; + for (let thisBlock in this.protoList) { + returnString += " " + this.protoList[thisBlock].name; } - newBlk = protoblk.name; - break; - case "namedarg": - // Use the name of the arg in the label - if (protoblk.defaults[0] === undefined) { - blkname = "namedarg"; - arg = "1"; - } else { - blkname = protoblk.defaults[0]; - arg = protoblk.defaults[0]; + return returnString; + }; + + this.remove = function(protoblock, name) { + // Remove the protoblock and its associated artwork container. + let i = this.protoList.indexOf(protoblock); + if (i !== -1) { + this.protoList.splice(i, 1); } - newBlk = protoblk.name; - break; - case "nameddo": - // Use the name of the action in the label - if (protoblk.defaults[0] === undefined) { - blkname = "nameddo"; - arg = _("action"); - } else { - blkname = protoblk.defaults[0]; - arg = protoblk.defaults[0]; + + for (let i = 0; i < this.model.blocks.length; i++) { + if (["nameddo", "nameddoArg", "namedcalc", "namedcalcArg"].indexOf( + this.model.blocks[i].blkname) !== -1 && + this.model.blocks[i].modname === name) { + this.model.blocks.splice(i, 1); + break; + } else if ( + ["storein"].indexOf(this.model.blocks[i].blkname) !== -1 && + this.model.blocks[i].modname === _("store in") + " " + name) { + this.model.blocks.splice(i, 1); + break; + } } - newBlk = protoblk.name; - break; - case "nameddoArg": - // Use the name of the action in the label - if (protoblk.defaults[0] === undefined) { - blkname = "nameddoArg"; - arg = _("action"); - } else { - blkname = protoblk.defaults[0]; - arg = protoblk.defaults[0]; + + }; + + this.add = function(protoblock, top) { + // Add a new palette entry to the end of the list (default) or + // to the top. + if (this.protoList.indexOf(protoblock) === -1) { + if (top)this.protoList.push(protoblock); + else this.protoList.push(protoblock); } - newBlk = protoblk.name; - break; - case "namedcalc": - // Use the name of the action in the label - if (protoblk.defaults[0] === undefined) { - blkname = "namedcalc"; - arg = _("action"); - } else { - blkname = protoblk.defaults[0]; - arg = protoblk.defaults[0]; + return this; + }; + + this.makeBlockFromSearch = function(protoblk, blkname, callback) { + this._makeBlockFromPalette(protoblk, blkname, callback); + this.palettes.hideSearchWidget(); + }; + + this._makeBlockFromPalette = function(protoblk, blkname, callback) { + if (protoblk === null) { + console.debug("null protoblk?"); + return; } - newBlk = protoblk.name; - break; - case "namedcalcArg": - // Use the name of the action in the label - if (protoblk.defaults[0] === undefined) { - blkname = "namedcalcArg"; - arg = _("action"); - } else { - blkname = protoblk.defaults[0]; - arg = protoblk.defaults[0]; + + let newBlk; + let arg; + switch (protoblk.name) { + case "do": + blkname = "do " + protoblk.defaults[0]; + newBlk = protoblk.name; + arg = protoblk.defaults[0]; + break; + case "storein": + // Use the name of the box in the label + blkname = "store in " + protoblk.defaults[0]; + newBlk = protoblk.name; + arg = protoblk.defaults[0]; + break; + case "storein2": + // Use the name of the box in the label + console.debug("storein2" + " " + protoblk.defaults[0] + " " + + protoblk.staticLabels[0]); + blkname = "store in2 " + protoblk.defaults[0]; + newBlk = protoblk.name; + arg = protoblk.staticLabels[0]; + break; + case "box": + // Use the name of the box in the label + blkname = protoblk.defaults[0]; + newBlk = protoblk.name; + arg = protoblk.defaults[0]; + break; + case "namedbox": + // Use the name of the box in the label + if (protoblk.defaults[0] === undefined) { + blkname = "namedbox"; + arg = _("box"); + } else { + console.debug(protoblk.defaults[0]); + blkname = protoblk.defaults[0]; + arg = protoblk.defaults[0]; + } + newBlk = protoblk.name; + break; + case "namedarg": + // Use the name of the arg in the label + if (protoblk.defaults[0] === undefined) { + blkname = "namedarg"; + arg = "1"; + } else { + blkname = protoblk.defaults[0]; + arg = protoblk.defaults[0]; + } + newBlk = protoblk.name; + break; + case "nameddo": + // Use the name of the action in the label + if (protoblk.defaults[0] === undefined) { + blkname = "nameddo"; + arg = _("action"); + } else { + blkname = protoblk.defaults[0]; + arg = protoblk.defaults[0]; + } + newBlk = protoblk.name; + break; + case "nameddoArg": + // Use the name of the action in the label + if (protoblk.defaults[0] === undefined) { + blkname = "nameddoArg"; + arg = _("action"); + } else { + blkname = protoblk.defaults[0]; + arg = protoblk.defaults[0]; + } + newBlk = protoblk.name; + break; + case "namedcalc": + // Use the name of the action in the label + if (protoblk.defaults[0] === undefined) { + blkname = "namedcalc"; + arg = _("action"); + } else { + blkname = protoblk.defaults[0]; + arg = protoblk.defaults[0]; + } + newBlk = protoblk.name; + break; + case "namedcalcArg": + // Use the name of the action in the label + if (protoblk.defaults[0] === undefined) { + blkname = "namedcalcArg"; + arg = _("action"); + } else { + blkname = protoblk.defaults[0]; + arg = protoblk.defaults[0]; + } + newBlk = protoblk.name; + break; + case "outputtools": + if (protoblk.defaults[0] === undefined) { + blkname = "outputtools"; + arg = "letter class"; + } else { + blkname = protoblk.defaults[0]; + arg = protoblk.defaults[0]; + } + newBlk = protoblk.name; + break; + default: + if (blkname === "nameddo") { + arg = _("action"); + } else { + arg = "__NOARG__"; + } + + newBlk = blkname; + break; } - newBlk = protoblk.name; - break; - case "outputtools": - if (protoblk.defaults[0] === undefined) { - blkname = "outputtools"; - arg = "letter class"; + + let lastBlock = this.palettes.blocks.blockList.length; + + if (["namedbox", + "nameddo", + "namedcalc", + "nameddoArg", + "namedcalcArg"].indexOf(protoblk.name) === -1 && + blockIsMacro(blkname)) { + this._makeBlockFromProtoblock( + protoblk, + true, + blkname, + null, + 100, + 100 + ); + callback(lastBlock); + } else if (["namedbox", + "nameddo", + "namedcalc", + "nameddoArg", + "namedcalcArg"].indexOf(protoblk.name) === -1 && + blkname in this.palettes.pluginMacros) { + this._makeBlockFromProtoblock( + protoblk, + true, + blkname, + null, + 100, + 100 + ); + callback(lastBlock); } else { - blkname = protoblk.defaults[0]; - arg = protoblk.defaults[0]; + let newBlock = paletteBlockButtonPush( + this.palettes.blocks, + newBlk, + arg + ); + callback(newBlock); } - newBlk = protoblk.name; - break; - default: - if (blkname === "nameddo") { - arg = _("action"); - } else { - arg = "__NOARG__"; + }; + + this._makeBlockFromProtoblock = function( + protoblk, moved, blkname, event, saveX, saveY) { + let that = this; + let newBlock; + + function __myCallback(newBlock) { + // Move the drag group under the cursor. + that.palettes.blocks.findDragGroup(newBlock); + for (let i in that.palettes.blocks.dragGroup) { + that.palettes.blocks.moveBlockRelative( + that.palettes.blocks.dragGroup[i], saveX, saveY); + } + // Dock with other blocks if needed + that.palettes.blocks.blockMoved(newBlock); + that.palettes.blocks.checkBounds(); } - newBlk = blkname; - break; - } + if (moved) { + moved = false; + this.draggingProtoBlock = false; - let lastBlock = this.palettes.blocks.blockList.length; - - if (["namedbox", - "nameddo", - "namedcalc", - "nameddoArg", - "namedcalcArg"].indexOf(protoblk.name) === -1 && - blockIsMacro(blkname)) { - this._makeBlockFromProtoblock( - protoblk, - true, - blkname, - null, - 100, - 100 - ); - callback(lastBlock); - } else if (["namedbox", + let macroExpansion = null; + if (["namedbox", "nameddo", "namedcalc", "nameddoArg", - "namedcalcArg"].indexOf(protoblk.name) === -1 && - blkname in this.palettes.pluginMacros) { - this._makeBlockFromProtoblock( - protoblk, - true, - blkname, - null, - 100, - 100 - ); - callback(lastBlock); - } else { - let newBlock = paletteBlockButtonPush( - this.palettes.blocks, - newBlk, - arg - ); - callback(newBlock); - } - }; - - this._makeBlockFromProtoblock = function( - protoblk, moved, blkname, event, saveX, saveY) { - let that = this; - let newBlock; - - function __myCallback(newBlock) { - // Move the drag group under the cursor. - that.palettes.blocks.findDragGroup(newBlock); - for (let i in that.palettes.blocks.dragGroup) { - that.palettes.blocks.moveBlockRelative( - that.palettes.blocks.dragGroup[i], saveX, saveY); - } - // Dock with other blocks if needed - that.palettes.blocks.blockMoved(newBlock); - that.palettes.blocks.checkBounds(); - } - - if (moved) { - moved = false; - this.draggingProtoBlock = false; - - let macroExpansion = null; - if (["namedbox", - "nameddo", - "namedcalc", - "nameddoArg", - "namedcalcArg"].indexOf(protoblk.name) === -1) { - macroExpansion = getMacroExpansion(blkname, saveX, saveY); - if (macroExpansion === null) { - // Maybe it is a plugin macro? - if (blkname in this.palettes.pluginMacros) { - macroExpansion = this.palettes.getPluginMacroExpansion( - blkname, saveX, saveY); + "namedcalcArg"].indexOf(protoblk.name) === -1) { + macroExpansion = getMacroExpansion(blkname, saveX, saveY); + if (macroExpansion === null) { + // Maybe it is a plugin macro? + if (blkname in this.palettes.pluginMacros) { + macroExpansion = this.palettes.getPluginMacroExpansion( + blkname, saveX, saveY); + } } } - } - if (macroExpansion !== null) { - this.palettes.blocks.loadNewBlocks(macroExpansion); - let thisBlock = this.palettes.blocks.blockList.length - 1; - let topBlk = this.palettes.blocks.findTopBlock(thisBlock); - } else if (this.name === "myblocks") { - // If we are on the myblocks palette, it is a macro. - let macroName = blkname.replace("macro_", ""); - - // We need to copy the macro data so it is not overwritten. - let obj = []; - for (let b = 0; b < this.palettes.macroDict[macroName].length; - b++) { - let valueEntry = this.palettes.macroDict[macroName][b][1]; - let newValue = []; - if (typeof valueEntry === "string") { - newValue = valueEntry; - } else if (typeof valueEntry[1] === "string") { - if (valueEntry[0] === "number") { - newValue = [valueEntry[0], Number(valueEntry[1])]; + if (macroExpansion !== null) { + this.palettes.blocks.loadNewBlocks(macroExpansion); + let thisBlock = this.palettes.blocks.blockList.length - 1; + let topBlk = this.palettes.blocks.findTopBlock(thisBlock); + } else if (this.name === "myblocks") { + // If we are on the myblocks palette, it is a macro. + let macroName = blkname.replace("macro_", ""); + + // We need to copy the macro data so it is not overwritten. + let obj = []; + for (let b = 0; b < this.palettes.macroDict[macroName].length; + b++) { + let valueEntry = this.palettes.macroDict[macroName][b][1]; + let newValue = []; + if (typeof valueEntry === "string") { + newValue = valueEntry; + } else if (typeof valueEntry[1] === "string") { + if (valueEntry[0] === "number") { + newValue = [valueEntry[0], Number(valueEntry[1])]; + } else { + newValue = [valueEntry[0], valueEntry[1]]; + } + } else if (typeof valueEntry[1] === "number") { + if (valueEntry[0] === "number") { + newValue = [valueEntry[0], valueEntry[1]]; + } else { + newValue = [valueEntry[0], + valueEntry[1].toString()]; + } } else { - newValue = [valueEntry[0], valueEntry[1]]; - } - } else if (typeof valueEntry[1] === "number") { - if (valueEntry[0] === "number") { - newValue = [valueEntry[0], valueEntry[1]]; - } else { - newValue = [valueEntry[0], - valueEntry[1].toString()]; - } - } else { - if (valueEntry[0] === "number") { - newValue = [valueEntry[0], + if (valueEntry[0] === "number") { + newValue = [valueEntry[0], Number(valueEntry[1]["value"])]; - } else { - newValue = [valueEntry[0], - {value: valueEntry[1]["value"]}]; + } else { + newValue = [valueEntry[0], + {value: valueEntry[1]["value"]}]; + } } + + newBlock = [ + this.palettes.macroDict[macroName][b][0], + newValue, + this.palettes.macroDict[macroName][b][2], + this.palettes.macroDict[macroName][b][3], + this.palettes.macroDict[macroName][b][4] + ]; + obj.push(newBlock); } - newBlock = [ - this.palettes.macroDict[macroName][b][0], - newValue, - this.palettes.macroDict[macroName][b][2], - this.palettes.macroDict[macroName][b][3], - this.palettes.macroDict[macroName][b][4] - ]; - obj.push(newBlock); + // Set the position of the top block in the stack + // before loading. + obj[0][2] = saveX + obj[0][3] = saveY + this.palettes.blocks.loadNewBlocks(obj); + + // Ensure collapse state of new stack is set properly. + let thisBlock = this.palettes.blocks.blockList.length - 1; + let topBlk = this.palettes.blocks.findTopBlock(thisBlock); + setTimeout(function() { + this.palettes.blocks.blockList[topBlk].collapseToggle(); + }, 500); + } else { + newBlock = this._makeBlockFromPalette( + protoblk, blkname, __myCallback); } - - // Set the position of the top block in the stack - // before loading. - obj[0][2] = saveX - obj[0][3] = saveY - this.palettes.blocks.loadNewBlocks(obj); - - // Ensure collapse state of new stack is set properly. - let thisBlock = this.palettes.blocks.blockList.length - 1; - let topBlk = this.palettes.blocks.findTopBlock(thisBlock); - setTimeout(function() { - this.palettes.blocks.blockList[topBlk].collapseToggle(); - }, 500); - } else { - newBlock = this._makeBlockFromPalette( - protoblk, blkname, __myCallback); } - } - }; + }; - return this; + return this; + } } async function initPalettes(palettes) { From 3c389cf64d6ed433f79fc0f6aefe891657629dcc Mon Sep 17 00:00:00 2001 From: kushal khare Date: Sat, 28 Nov 2020 20:14:59 +0530 Subject: [PATCH 02/26] adding classes to protoblocks.js --- js/protoblocks.js | 2668 ++++++++++++++++++++++----------------------- 1 file changed, 1334 insertions(+), 1334 deletions(-) diff --git a/js/protoblocks.js b/js/protoblocks.js index 52797311e4..c5b59f698d 100644 --- a/js/protoblocks.js +++ b/js/protoblocks.js @@ -17,1397 +17,1397 @@ // Protoblock contain generic information about blocks and some // methods common to all blocks. -function ProtoBlock(name) { - // Name is used run-dictionary index, and palette label. - this.name = name; - // The palette to which this block is assigned. - this.palette = null; - // The graphic style used by the block. - this.style = null; - // The generator function used to create the artwork - this.generator = null; - // Does the block expand (or collapse) when other blocks are - // attached? e.g., start, repeat... - this.expandable = false; - // Is this block a parameter? Parameters have their labels - // overwritten with their current value. - this.parameter = false; - // How many "non-flow" arguments does a block have? (flow is - // vertical down a stack; args are horizontal. The pendown block - // has 0 args; the forward block has 1 arg; the setxy block has 2 - // args. - this.args = 0; - // Default values for block parameters, e.g., forward 100 or right 90. - this.defaults = []; - // What is the size of the block prior to any expansion? - this.size = 1.0; - // Dock types are a list of the types associated with the docking points. - this.dockTypes = []; - // Static labels are generated as part of the inline SVG. - this.staticLabels = []; - // Default fontsize used for static labels. - this.fontsize = null; - // Extra block width for long labels - this.extraWidth = 0; - // Block scale - this.scale = DEFAULTBLOCKSCALE; - // The filepath of the image. - this.image = null; - // Hidden: don't show on any palette - this.hidden = false; - // Disabled: use inactive colors - this.disabled = false; - // Deprecated - this.deprecated = false; - //Stores the width of the text component - this.textWidth = 0; - this.labelOffset = 0; - this.beginnerModeBlock = false; - - this.adjustWidthToLabel = function() { - if (this.staticLabels.length === 0) { - return; - } - let c = new createjs.Container(); - let text = new createjs.Text( - this.staticLabels[0], - this.fontSize + "px Sans", - "#000000" - ); - c.addChild(text); - let b = c.getBounds(); - this.textWidth = b.width; - this.extraWidth += Math.max(b.width - 30, 0); - }; - - // What follows are the initializations for different block - // styles. - - // The generator methods return the svg artwork, the dock - // positions, and the width and height, and the height used to - // calculate the hit area for the block. (Note that clamp blocks - // only extend their hit area to the top of the clamp.) - - // E.g., penup, pendown - this.zeroArgBlock = function() { - this.args = 0; - this.dockTypes.push("out"); - this.dockTypes.push("in"); - this.generator = this.zeroArgBlockGenerator; - }; - - this.zeroArgBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., hidden (used at end of clamp) - this.hiddenBlockFlow = function() { - this.args = 0; - this.size = 0; - this.dockTypes.push("out"); - this.dockTypes.push("in"); - this.generator = this.hiddenBlockFlowGenerator; - }; - - // E.g., hidden (used at end of no flow clamp) - this.hiddenBlockNoFlow = function() { - this.args = 0; - this.size = 0; - this.dockTypes.push("out"); - this.dockTypes.push("unavailable"); - this.generator = this.hiddenBlockFlowGenerator; - }; - - this.hiddenBlockFlowGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setSlot(true); - svg.setTab(true); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } - // We need to generate the artwork in order to generate the dock. - let artwork = svg.basicBlock(); - // Then we replace the artwork with a single pixel. - artwork = - 'block_label'; - // And bring the last dock position to the top. - svg.docks[1][1] = svg.docks[0][1]; - return [artwork, svg.docks, 0, 0, 0]; - }; - - // E.g., break - this.basicBlockNoFlow = function() { +class ProtoBlock { + constructor(name) { + // Name is used run-dictionary index, and palette label. + this.name = name; + // The palette to which this block is assigned. + this.palette = null; + // The graphic style used by the block. + this.style = null; + // The generator function used to create the artwork + this.generator = null; + // Does the block expand (or collapse) when other blocks are + // attached? e.g., start, repeat... + this.expandable = false; + // Is this block a parameter? Parameters have their labels + // overwritten with their current value. + this.parameter = false; + // How many "non-flow" arguments does a block have? (flow is + // vertical down a stack; args are horizontal. The pendown block + // has 0 args; the forward block has 1 arg; the setxy block has 2 + // args. this.args = 0; - this.dockTypes.push("out"); - this.dockTypes.push("unavailable"); - this.generator = this.basicBlockNoFlowGenerator; - }; - - this.basicBlockNoFlowGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setSlot(true); - svg.setTail(true); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // Default values for block parameters, e.g., forward 100 or right 90. + this.defaults = []; + // What is the size of the block prior to any expansion? + this.size = 1.0; + // Dock types are a list of the types associated with the docking points. + this.dockTypes = []; + // Static labels are generated as part of the inline SVG. + this.staticLabels = []; + // Default fontsize used for static labels. + this.fontsize = null; + // Extra block width for long labels + this.extraWidth = 0; + // Block scale + this.scale = DEFAULTBLOCKSCALE; + // The filepath of the image. + this.image = null; + // Hidden: don't show on any palette + this.hidden = false; + // Disabled: use inactive colors + this.disabled = false; + // Deprecated + this.deprecated = false; + //Stores the width of the text component + this.textWidth = 0; + this.labelOffset = 0; + this.beginnerModeBlock = false; + + this.adjustWidthToLabel = function () { + if (this.staticLabels.length === 0) { + return; + } + let c = new createjs.Container(); + let text = new createjs.Text( + this.staticLabels[0], + this.fontSize + "px Sans", + "#000000" + ); + c.addChild(text); + let b = c.getBounds(); + this.textWidth = b.width; + this.extraWidth += Math.max(b.width - 30, 0); + }; + + // What follows are the initializations for different block + // styles. + // The generator methods return the svg artwork, the dock + // positions, and the width and height, and the height used to + // calculate the hit area for the block. (Note that clamp blocks + // only extend their hit area to the top of the clamp.) + // E.g., penup, pendown + this.zeroArgBlock = function () { + this.args = 0; + this.dockTypes.push("out"); + this.dockTypes.push("in"); + this.generator = this.zeroArgBlockGenerator; + }; + + this.zeroArgBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., hidden (used at end of clamp) + this.hiddenBlockFlow = function () { + this.args = 0; + this.size = 0; + this.dockTypes.push("out"); + this.dockTypes.push("in"); + this.generator = this.hiddenBlockFlowGenerator; + }; + + // E.g., hidden (used at end of no flow clamp) + this.hiddenBlockNoFlow = function () { + this.args = 0; + this.size = 0; + this.dockTypes.push("out"); + this.dockTypes.push("unavailable"); + this.generator = this.hiddenBlockFlowGenerator; + }; + + this.hiddenBlockFlowGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setSlot(true); + svg.setTab(true); + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + // We need to generate the artwork in order to generate the dock. + let artwork = svg.basicBlock(); + // Then we replace the artwork with a single pixel. + artwork = + 'block_label'; + // And bring the last dock position to the top. + svg.docks[1][1] = svg.docks[0][1]; + return [artwork, svg.docks, 0, 0, 0]; + }; + + // E.g., break + this.basicBlockNoFlow = function () { + this.args = 0; + this.dockTypes.push("out"); + this.dockTypes.push("unavailable"); + this.generator = this.basicBlockNoFlowGenerator; + }; + + this.basicBlockNoFlowGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setSlot(true); + svg.setTail(true); + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., collapsed + this.basicBlockCollapsed = function () { + this.args = 0; + this.dockTypes.push("unavailable"); + this.dockTypes.push("unavailable"); + this.generator = this.basicBlockCollapsedGenerator; + }; + + this.basicBlockCollapsedGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setCap(true); + svg.setTail(true); + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., forward, right + this.oneArgBlock = function () { + this.args = 1; + this.dockTypes.push("out"); + this.dockTypes.push("numberin"); + this.dockTypes.push("in"); + this.generator = this.oneArgBlockGenerator; + }; + + this.oneArgBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setInnies([true]); + svg.setSlot(true); + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., wait for + this.oneBooleanArgBlock = function () { + this.args = 1; + this.size = 1; + this.dockTypes.push("out"); + this.dockTypes.push("booleanin"); + this.dockTypes.push("in"); + this.generator = this.oneBooleanArgBlockGenerator; + }; + + this.oneBooleanArgBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setBoolean(true); + svg.setClampCount(0); + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., setxy. These are expandable. + this.twoArgBlock = function () { + this.expandable = true; + this.style = "twoarg"; + this.size = 2; + this.args = 2; + this.dockTypes.push("out"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("in"); + this.generator = this.twoArgBlockGenerator; + }; + + this.twoArgBlockGenerator = function (expandY) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setInnies([true, true]); + svg.setSlot(true); + + if (expandY) { + svg.setExpand( + 30 + this.extraWidth, + ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); + } else { + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., ??? These are expandable. + this.threeArgBlock = function () { + this.expandable = true; + this.style = "twoarg"; + this.size = 3; + this.args = 3; + this.dockTypes.push("out"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("in"); + this.generator = this.threeArgBlockGenerator; + }; + + this.threeArgBlockGenerator = function (expandY) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setInnies([true, true, true]); + svg.setSlot(true); + + if (expandY) { + svg.setExpand( + 30 + this.extraWidth, + ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); + } else { + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + this.fourArgBlock = function () { + this.expandable = true; + this.style = "twoarg"; + this.size = 4; + this.args = 4; + this.dockTypes.push("out"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("in"); + this.generator = this.fourArgBlockGenerator; + }; + + this.fourArgBlockGenerator = function (expandY) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setInnies([true, true, true, true]); + svg.setSlot(true); + + if (expandY) { + svg.setExpand( + 30 + this.extraWidth, + ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); + } else { + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., sqrt, box + this.oneArgMathBlock = function () { + this.style = "arg"; + this.size = 1; + this.args = 1; + this.parameter = true; + this.dockTypes.push("numberout"); + this.dockTypes.push("numberin"); + this.generator = this.oneArgMathBlockGenerator; + }; + + this.oneArgMathBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setSlot(false); + svg.setInnies([true]); + svg.setOutie(true); + svg.setTab(false); + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., plus, minus, multiply, divide, power,distance. These are also expandable. + this.twoArgMathBlock = function () { + this.expandable = true; + this.style = "arg"; + this.size = 2; + this.args = 2; + this.parameter = true; + this.dockTypes.push("numberout"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.generator = this.twoArgMathBlockGenerator; + }; + + this.twoArgMathBlockGenerator = function (expandY) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setSlot(false); + svg.setInnies([true, true]); + svg.setOutie(true); + svg.setTab(false); + + if (expandY) { + svg.setExpand( + 30 + this.extraWidth, + ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); + } else { + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // + this.threeArgMathBlock = function () { + this.expandable = true; + this.style = "arg"; + this.size = 3; + this.args = 3; + this.parameter = true; + this.dockTypes.push("numberout"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.generator = this.threeArgMathBlockGenerator; + }; + + this.threeArgMathBlockGenerator = function (expandY) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setSlot(false); + svg.setInnies([true, true, true]); + svg.setOutie(true); + svg.setTab(false); + + if (expandY) { + svg.setExpand( + 30 + this.extraWidth, + ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); + } else { + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + // E.g., distance . Distance block will calculate geometrical distance between two pointa + // by default (cursor x ,cursor y ) and x and y + this.fourArgMathBlock = function () { + this.expandable = true; + this.style = "arg"; + this.size = 4; + this.args = 4; + this.parameter = true; + this.dockTypes.push("numberout"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.generator = this.fourArgMathBlockGenerator; + }; + + this.fourArgMathBlockGenerator = function (expandY) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setSlot(false); + svg.setInnies([true, true, true, true]); + svg.setOutie(true); + svg.setTab(false); + + if (expandY) { + svg.setExpand( + 30 + this.extraWidth, + ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); + } else { + svg.setExpand(30 + this.extraWidth, 0, 0, 0); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBlock(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., number, string. Value blocks get DOM textareas associated + // with them so their values can be edited by the user. + this.valueBlock = function () { + this.style = "value"; + this.size = 1; + this.args = 0; + this.dockTypes.push("numberout"); + this.generator = this.valueBlockGenerator; + }; + + this.valueBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + // Extra room for parameter label + svg.setExpand(60 + this.extraWidth, 0, 0, 0); + svg.setOutie(true); + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBox(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., media. Media blocks invoke a chooser and a thumbnail + // image is overlayed to represent the data associated with the + // block. + this.mediaBlock = function () { + this.style = "value"; + this.size = 2; + this.args = 0; + this.dockTypes.push("mediaout"); + this.generator = this.mediaBlockGenerator; + }; + + this.mediaBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + // Extra room for graphics + svg.setExpand(60 + this.extraWidth, 23, 0, 0); + svg.setOutie(true); + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicBox(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + + // E.g., start. A "child" flow is docked in an expandable clamp. + // There are no additional arguments and no flow above or below. + this.stackClampZeroArgBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 3; + this.args = 1; + this.dockTypes.push("unavailable"); + this.dockTypes.push("in"); + this.dockTypes.push("unavailable"); + this.generator = this.stackClampZeroArgBlockGenerator; + }; + + this.stackClampZeroArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setCap(true); + svg.setTail(true); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + svg.setLabelOffset(this.labelOffset); + + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[1][1] + ]; + }; + + // E.g., emptyclamp. Unlike start, there is a flow above and below. + this.flowClampBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 2; + this.args = 1; + this.dockTypes.push("out"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.generator = this.flowClampBlockGenerator; + }; + + this.flowClampBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + + svg.setSlot(true); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[1][1] + ]; + }; + + // E.g., repeat. Unlike action, there is a flow above and below. + this.flowClampOneArgBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 2; + this.args = 2; + this.dockTypes.push("out"); + this.dockTypes.push("numberin"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.generator = this.flowClampOneArgBlockGenerator; + }; + + this.flowClampOneArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setInnies([true]); + svg.setLabelOffset(this.labelOffset); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[2][1] + ]; + }; + + // E.g., tuplet, which takes two args plus an interior flow. + // There is a flow above and below. + this.flowClampTwoArgBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 3; + this.args = 3; + this.dockTypes.push("out"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.generator = this.flowClampTwoArgBlockGenerator; + }; + + this.flowClampTwoArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setInnies([true, true]); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[3][1] + ]; + }; + + this.flowClampThreeArgBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 4; + this.args = 4; + this.dockTypes.push("out"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.dockTypes.push("textin"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.generator = this.flowClampThreeArgBlockGenerator; + }; + + this.flowClampThreeArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setInnies([true, true, true]); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[4][1] + ]; + }; + + // E.g., do with args: innies instead of interior slots. + this.argClampOneArgBlock = function () { + this.style = "argclamp"; + this.expandable = true; + this.size = 3; + this.args = 2; + this.dockTypes.push("out"); + this.dockTypes.push("textin"); + this.dockTypes.push("anyin"); + this.dockTypes.push("in"); + this.generator = this.argClampOneArgBlockGenerator; + }; + + this.argClampOneArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setInnies([true]); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, [1]); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + // The hit area extends halfway between the label dock and the + // first innie arg dock. + return [ + svg.argClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + (svg.docks[1][1] + svg.docks[2][1]) / 2 + ]; + }; + + // E.g., calculate with args: innies instead of interior slots. + this.argClampOneArgMathBlock = function () { + this.style = "argclamparg"; + this.expandable = true; + this.size = 3; + this.args = 2; + this.dockTypes.push("anyout"); + this.dockTypes.push("textin"); + this.dockTypes.push("anyin"); + this.generator = this.argClampOneArgMathBlockGenerator; + }; + + this.argClampOneArgMathBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setInnies([true]); + svg.setOutie(true); + svg.setTab(false); + svg.setSlot(false); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, [1]); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + // The hit area extends halfway between the label dock and the + // first innie arg dock. + return [ + svg.argClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + (svg.docks[1][1] + svg.docks[2][1]) / 2 + ]; + }; + + // E.g., named do with args: innies instead of interior slots. + this.argClampBlock = function () { + this.style = "argclamp"; + this.expandable = true; + this.size = 3; + this.args = 1; + this.dockTypes.push("out"); + this.dockTypes.push("anyin"); + this.dockTypes.push("in"); + this.generator = this.argClampBlockGenerator; + }; + + this.argClampBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, [1]); + } + + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } + + return [ + svg.argClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + (svg.docks[1][1] * 2) / 3 + ]; + }; + + // E.g., named calculate with args: innies instead of interior slots. + this.argClampMathBlock = function () { + this.style = "argclamparg"; + this.expandable = true; + this.size = 3; + this.args = 1; + this.dockTypes.push("anyout"); + this.dockTypes.push("anyin"); + this.generator = this.argClampMathBlockGenerator; + }; - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., collapsed - this.basicBlockCollapsed = function() { - this.args = 0; - this.dockTypes.push("unavailable"); - this.dockTypes.push("unavailable"); - this.generator = this.basicBlockCollapsedGenerator; - }; - - this.basicBlockCollapsedGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setCap(true); - svg.setTail(true); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + this.argClampMathBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setOutie(true); + svg.setTab(false); + svg.setSlot(false); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., forward, right - this.oneArgBlock = function() { - this.args = 1; - this.dockTypes.push("out"); - this.dockTypes.push("numberin"); - this.dockTypes.push("in"); - this.generator = this.oneArgBlockGenerator; - }; - - this.oneArgBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setInnies([true]); - svg.setSlot(true); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, [1]); + } - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., wait for - this.oneBooleanArgBlock = function() { - this.args = 1; - this.size = 1; - this.dockTypes.push("out"); - this.dockTypes.push("booleanin"); - this.dockTypes.push("in"); - this.generator = this.oneBooleanArgBlockGenerator; - }; - - this.oneBooleanArgBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setBoolean(true); - svg.setClampCount(0); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., setxy. These are expandable. - this.twoArgBlock = function() { - this.expandable = true; - this.style = "twoarg"; - this.size = 2; - this.args = 2; - this.dockTypes.push("out"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("in"); - this.generator = this.twoArgBlockGenerator; - }; - - this.twoArgBlockGenerator = function(expandY) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setInnies([true, true]); - svg.setSlot(true); - - if (expandY) { - svg.setExpand( - 30 + this.extraWidth, - ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); - } else { - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - } + return [ + svg.argClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + (svg.docks[1][1] * 2) / 3 + ]; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., if. A "child" flow is docked in an expandable clamp. The + // additional argument is a boolean. There is flow above and below. + this.flowClampBooleanArgBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 3; + this.args = 2; + this.dockTypes.push("out"); + this.dockTypes.push("booleanin"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.generator = this.flowClampBooleanArgBlockGenerator; + }; - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., ??? These are expandable. - this.threeArgBlock = function() { - this.expandable = true; - this.style = "twoarg"; - this.size = 3; - this.args = 3; - this.dockTypes.push("out"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("in"); - this.generator = this.threeArgBlockGenerator; - }; - - this.threeArgBlockGenerator = function(expandY) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setInnies([true, true, true]); - svg.setSlot(true); - - if (expandY) { - svg.setExpand( - 30 + this.extraWidth, - ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); - } else { - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - } + this.flowClampBooleanArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setBoolean(true); + svg.setSlot(true); + svg.setExpand(this.extraWidth, 0, 0, 0); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - this.fourArgBlock = function() { - this.expandable = true; - this.style = "twoarg"; - this.size = 4; - this.args = 4; - this.dockTypes.push("out"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("in"); - this.generator = this.fourArgBlockGenerator; - }; - - this.fourArgBlockGenerator = function(expandY) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setInnies([true, true, true, true]); - svg.setSlot(true); - - if (expandY) { - svg.setExpand( - 30 + this.extraWidth, - ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); - } else { - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[2][1] + ]; + }; - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., sqrt, box - this.oneArgMathBlock = function() { - this.style = "arg"; - this.size = 1; - this.args = 1; - this.parameter = true; - this.dockTypes.push("numberout"); - this.dockTypes.push("numberin"); - this.generator = this.oneArgMathBlockGenerator; - }; - - this.oneArgMathBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setSlot(false); - svg.setInnies([true]); - svg.setOutie(true); - svg.setTab(false); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., if then else. Two "child" flows are docked in expandable + // clamps. The additional argument is a boolean. There is flow + // above and below. + this.doubleFlowClampBooleanArgBlock = function () { + this.style = "doubleclamp"; + this.expandable = true; + this.size = 4; + this.args = 3; + this.dockTypes.push("out"); + this.dockTypes.push("booleanin"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.generator = this.doubleFlowClampBooleanArgBlockGenerator; + }; - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., plus, minus, multiply, divide, power,distance. These are also expandable. - this.twoArgMathBlock = function() { - this.expandable = true; - this.style = "arg"; - this.size = 2; - this.args = 2; - this.parameter = true; - this.dockTypes.push("numberout"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.generator = this.twoArgMathBlockGenerator; - }; - - this.twoArgMathBlockGenerator = function(expandY) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setSlot(false); - svg.setInnies([true, true]); - svg.setOutie(true); - svg.setTab(false); - - if (expandY) { - svg.setExpand( - 30 + this.extraWidth, - ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); - } else { - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - } + this.doubleFlowClampBooleanArgBlockGenerator = function ( + bottomSlots, + topSlots + ) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setBoolean(true); + svg.setClampCount(2); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (topSlots) { + svg.setClampSlots(0, topSlots); + } else { + svg.setClampSlots(0, 1); + } - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // - this.threeArgMathBlock = function() { - this.expandable = true; - this.style = "arg"; - this.size = 3; - this.args = 3; - this.parameter = true; - this.dockTypes.push("numberout"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.generator = this.threeArgMathBlockGenerator; - }; - - this.threeArgMathBlockGenerator = function(expandY) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setSlot(false); - svg.setInnies([true, true, true]); - svg.setOutie(true); - svg.setTab(false); - - if (expandY) { - svg.setExpand( - 30 + this.extraWidth, - ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); - } else { - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - } + if (bottomSlots) { + svg.setClampSlots(1, bottomSlots); + } else { + svg.setClampSlots(1, 1); + } - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + svg.setExpand(this.extraWidth, 0, 0, 0); - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - // E.g., distance . Distance block will calculate geometrical distance between two pointa - // by default (cursor x ,cursor y ) and x and y - this.fourArgMathBlock = function() { - this.expandable = true; - this.style = "arg"; - this.size = 4; - this.args = 4; - this.parameter = true; - this.dockTypes.push("numberout"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.generator = this.fourArgMathBlockGenerator; - }; - - this.fourArgMathBlockGenerator = function(expandY) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setSlot(false); - svg.setInnies([true, true, true, true]); - svg.setOutie(true); - svg.setTab(false); - - if (expandY) { - svg.setExpand( - 30 + this.extraWidth, - ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); - } else { - svg.setExpand(30 + this.extraWidth, 0, 0, 0); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[2][1] + ]; + }; - return [ - svg.basicBlock(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., number, string. Value blocks get DOM textareas associated - // with them so their values can be edited by the user. - this.valueBlock = function() { - this.style = "value"; - this.size = 1; - this.args = 0; - this.dockTypes.push("numberout"); - this.generator = this.valueBlockGenerator; - }; - - this.valueBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - // Extra room for parameter label - svg.setExpand(60 + this.extraWidth, 0, 0, 0); - svg.setOutie(true); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., forever. Unlike start, there is flow above and below. + this.flowClampZeroArgBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 2; + this.args = 1; + this.dockTypes.push("out"); + this.dockTypes.push("in"); + this.dockTypes.push("in"); + this.generator = this.flowClampZeroArgBlockGenerator; + }; - return [ - svg.basicBox(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., media. Media blocks invoke a chooser and a thumbnail - // image is overlayed to represent the data associated with the - // block. - this.mediaBlock = function() { - this.style = "value"; - this.size = 2; - this.args = 0; - this.dockTypes.push("mediaout"); - this.generator = this.mediaBlockGenerator; - }; - - this.mediaBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - // Extra room for graphics - svg.setExpand(60 + this.extraWidth, 23, 0, 0); - svg.setOutie(true); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + this.flowClampZeroArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setTab(true); + svg.setSlot(true); + svg.setExpand(10 + this.extraWidth, 0, 0, 0); - return [ - svg.basicBox(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., start. A "child" flow is docked in an expandable clamp. - // There are no additional arguments and no flow above or below. - this.stackClampZeroArgBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 3; - this.args = 1; - this.dockTypes.push("unavailable"); - this.dockTypes.push("in"); - this.dockTypes.push("unavailable"); - this.generator = this.stackClampZeroArgBlockGenerator; - }; - - this.stackClampZeroArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setCap(true); - svg.setTail(true); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - svg.setLabelOffset(this.labelOffset); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[1][1] - ]; - }; - - // E.g., emptyclamp. Unlike start, there is a flow above and below. - this.flowClampBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 2; - this.args = 1; - this.dockTypes.push("out"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.generator = this.flowClampBlockGenerator; - }; - - this.flowClampBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - - svg.setSlot(true); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[1][1] + ]; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., count clamp: math block with interior slots + this.argFlowClampBlock = function () { + this.style = "argflowclamp"; + this.expandable = true; + this.size = 3; + this.args = 1; + this.dockTypes.push("anyout"); + this.dockTypes.push("in"); + this.generator = this.argFlowClampGenerator; + }; - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[1][1] - ]; - }; - - // E.g., repeat. Unlike action, there is a flow above and below. - this.flowClampOneArgBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 2; - this.args = 2; - this.dockTypes.push("out"); - this.dockTypes.push("numberin"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.generator = this.flowClampOneArgBlockGenerator; - }; - - this.flowClampOneArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setInnies([true]); - svg.setLabelOffset(this.labelOffset); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + this.argFlowClampGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setSlot(false); + svg.setOutie(true); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, [1]); + } - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[2][1] - ]; - }; - - // E.g., tuplet, which takes two args plus an interior flow. - // There is a flow above and below. - this.flowClampTwoArgBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 3; - this.args = 3; - this.dockTypes.push("out"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.generator = this.flowClampTwoArgBlockGenerator; - }; - - this.flowClampTwoArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setInnies([true, true]); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[1][1] + ]; + }; - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[3][1] - ]; - }; - - this.flowClampThreeArgBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 4; - this.args = 4; - this.dockTypes.push("out"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.dockTypes.push("textin"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.generator = this.flowClampThreeArgBlockGenerator; - }; - - this.flowClampThreeArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setInnies([true, true, true]); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + // E.g., action. A "child" flow is docked in an expandable clamp. + // The additional argument is a name. Again, no flow above or below. + this.stackClampOneArgBlock = function () { + this.style = "clamp"; + this.expandable = true; + this.size = 3; + this.args = 2; + this.dockTypes.push("unavailable"); + this.dockTypes.push("anyin"); + this.dockTypes.push("in"); + this.dockTypes.push("unavailable"); + this.generator = this.stackClampOneArgBlockGenerator; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + this.stackClampOneArgBlockGenerator = function (slots) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setCap(true); + svg.setTail(true); + svg.setInnies([true]); + svg.setExpand(10 + this.extraWidth, 0, 0, 0); + svg.setLabelOffset(this.labelOffset); - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[4][1] - ]; - }; - - // E.g., do with args: innies instead of interior slots. - this.argClampOneArgBlock = function() { - this.style = "argclamp"; - this.expandable = true; - this.size = 3; - this.args = 2; - this.dockTypes.push("out"); - this.dockTypes.push("textin"); - this.dockTypes.push("anyin"); - this.dockTypes.push("in"); - this.generator = this.argClampOneArgBlockGenerator; - }; - - this.argClampOneArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setInnies([true]); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, [1]); - } + if (slots) { + svg.setClampSlots(0, slots); + } else { + svg.setClampSlots(0, 1); + } - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - // The hit area extends halfway between the label dock and the - // first innie arg dock. - return [ - svg.argClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - (svg.docks[1][1] + svg.docks[2][1]) / 2 - ]; - }; - - // E.g., calculate with args: innies instead of interior slots. - this.argClampOneArgMathBlock = function() { - this.style = "argclamparg"; - this.expandable = true; - this.size = 3; - this.args = 2; - this.dockTypes.push("anyout"); - this.dockTypes.push("textin"); - this.dockTypes.push("anyin"); - this.generator = this.argClampOneArgMathBlockGenerator; - }; - - this.argClampOneArgMathBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setInnies([true]); - svg.setOutie(true); - svg.setTab(false); - svg.setSlot(false); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, [1]); - } + return [ + svg.basicClamp(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.docks[2][1] + ]; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., mouse button. + this.booleanZeroArgBlock = function () { + this.style = "arg"; + this.size = 1; + this.args = 0; + this.dockTypes.push("booleanout"); + this.generator = this.booleanZeroArgBlockGenerator; + }; - // The hit area extends halfway between the label dock and the - // first innie arg dock. - return [ - svg.argClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - (svg.docks[1][1] + svg.docks[2][1]) / 2 - ]; - }; - - // E.g., named do with args: innies instead of interior slots. - this.argClampBlock = function() { - this.style = "argclamp"; - this.expandable = true; - this.size = 3; - this.args = 1; - this.dockTypes.push("out"); - this.dockTypes.push("anyin"); - this.dockTypes.push("in"); - this.generator = this.argClampBlockGenerator; - }; - - this.argClampBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, [1]); - } + this.booleanZeroArgBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setExpand(60 + this.extraWidth, 0, 0, 4); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - return [ - svg.argClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - (svg.docks[1][1] * 2) / 3 - ]; - }; - - // E.g., named calculate with args: innies instead of interior slots. - this.argClampMathBlock = function() { - this.style = "argclamparg"; - this.expandable = true; - this.size = 3; - this.args = 1; - this.dockTypes.push("anyout"); - this.dockTypes.push("anyin"); - this.generator = this.argClampMathBlockGenerator; - }; - - this.argClampMathBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setOutie(true); - svg.setTab(false); - svg.setSlot(false); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, [1]); - } + return [ + svg.booleanNot(true), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., named sensor blocks + this.booleanOneArgBlock = function () { + this.style = "arg"; + this.size = 2; + this.args = 1; + this.parameter = true; + this.dockTypes.push("booleanout"); + this.dockTypes.push("textin"); + this.generator = this.booleanOneArgBlockGenerator; + }; - return [ - svg.argClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - (svg.docks[1][1] * 2) / 3 - ]; - }; - - // E.g., if. A "child" flow is docked in an expandable clamp. The - // additional argument is a boolean. There is flow above and below. - this.flowClampBooleanArgBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 3; - this.args = 2; - this.dockTypes.push("out"); - this.dockTypes.push("booleanin"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.generator = this.flowClampBooleanArgBlockGenerator; - }; - - this.flowClampBooleanArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setBoolean(true); - svg.setSlot(true); - svg.setExpand(this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + this.booleanOneArgBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[2][1] - ]; - }; - - // E.g., if then else. Two "child" flows are docked in expandable - // clamps. The additional argument is a boolean. There is flow - // above and below. - this.doubleFlowClampBooleanArgBlock = function() { - this.style = "doubleclamp"; - this.expandable = true; - this.size = 4; - this.args = 3; - this.dockTypes.push("out"); - this.dockTypes.push("booleanin"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.generator = this.doubleFlowClampBooleanArgBlockGenerator; - }; - - this.doubleFlowClampBooleanArgBlockGenerator = function( - bottomSlots, - topSlots - ) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setBoolean(true); - svg.setClampCount(2); - - if (topSlots) { - svg.setClampSlots(0, topSlots); - } else { - svg.setClampSlots(0, 1); - } + svg.setInnies([true]); + return [ + svg.booleanNot(true), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; - if (bottomSlots) { - svg.setClampSlots(1, bottomSlots); - } else { - svg.setClampSlots(1, 1); - } + // E.g., not + this.booleanOneBooleanArgBlock = function () { + this.style = "arg"; + this.size = 2; + this.args = 1; + this.parameter = true; + this.dockTypes.push("booleanout"); + this.dockTypes.push("booleanin"); + this.generator = this.booleanOneBooleanArgBlockGenerator; + }; - svg.setExpand(this.extraWidth, 0, 0, 0); + this.booleanOneBooleanArgBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[2][1] - ]; - }; - - // E.g., forever. Unlike start, there is flow above and below. - this.flowClampZeroArgBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 2; - this.args = 1; - this.dockTypes.push("out"); - this.dockTypes.push("in"); - this.dockTypes.push("in"); - this.generator = this.flowClampZeroArgBlockGenerator; - }; - - this.flowClampZeroArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setTab(true); - svg.setSlot(true); - svg.setExpand(10 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + return [ + svg.booleanNot(false), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., and, or + this.booleanTwoBooleanArgBlock = function () { + this.style = "arg"; + this.size = 3; + this.args = 2; + this.parameter = true; + this.dockTypes.push("booleanout"); + this.dockTypes.push("booleanin"); + this.dockTypes.push("booleanin"); + this.generator = this.booleanTwoBooleanArgBlockGenerator; + }; - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[1][1] - ]; - }; - - // E.g., count clamp: math block with interior slots - this.argFlowClampBlock = function() { - this.style = "argflowclamp"; - this.expandable = true; - this.size = 3; - this.args = 1; - this.dockTypes.push("anyout"); - this.dockTypes.push("in"); - this.generator = this.argFlowClampGenerator; - }; - - this.argFlowClampGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setSlot(false); - svg.setOutie(true); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, [1]); - } + this.booleanTwoBooleanArgBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + svg.setExpand(20 + this.extraWidth, 0, 0, 0); - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[1][1] - ]; - }; - - // E.g., action. A "child" flow is docked in an expandable clamp. - // The additional argument is a name. Again, no flow above or below. - this.stackClampOneArgBlock = function() { - this.style = "clamp"; - this.expandable = true; - this.size = 3; - this.args = 2; - this.dockTypes.push("unavailable"); - this.dockTypes.push("anyin"); - this.dockTypes.push("in"); - this.dockTypes.push("unavailable"); - this.generator = this.stackClampOneArgBlockGenerator; - }; - - this.stackClampOneArgBlockGenerator = function(slots) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setCap(true); - svg.setTail(true); - svg.setInnies([true]); - svg.setExpand(10 + this.extraWidth, 0, 0, 0); - svg.setLabelOffset(this.labelOffset); - - if (slots) { - svg.setClampSlots(0, slots); - } else { - svg.setClampSlots(0, 1); - } + return [ + svg.booleanAndOr(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + // E.g., greater, less, equal + this.booleanTwoArgBlock = function () { + this.style = "arg"; + this.size = 2; + this.args = 2; + this.parameter = true; + this.expandable = true; + this.dockTypes.push("booleanout"); + this.dockTypes.push("numberin"); + this.dockTypes.push("numberin"); + this.generator = this.booleanTwoArgBlockGenerator; + }; - return [ - svg.basicClamp(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.docks[2][1] - ]; - }; - - // E.g., mouse button. - this.booleanZeroArgBlock = function() { - this.style = "arg"; - this.size = 1; - this.args = 0; - this.dockTypes.push("booleanout"); - this.generator = this.booleanZeroArgBlockGenerator; - }; - - this.booleanZeroArgBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setExpand(60 + this.extraWidth, 0, 0, 4); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + this.booleanTwoArgBlockGenerator = function (expandY) { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); - return [ - svg.booleanNot(true), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., named sensor blocks - this.booleanOneArgBlock = function() { - this.style = "arg"; - this.size = 2; - this.args = 1; - this.parameter = true; - this.dockTypes.push("booleanout"); - this.dockTypes.push("textin"); - this.generator = this.booleanOneArgBlockGenerator; - }; - - this.booleanOneArgBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (expandY) { + svg.setExpand( + 10 + this.extraWidth, + ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); + } else { + svg.setExpand(10 + this.extraWidth, 0, 0, 0); + } - svg.setInnies([true]); - return [ - svg.booleanNot(true), // OneArg - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., not - this.booleanOneBooleanArgBlock = function() { - this.style = "arg"; - this.size = 2; - this.args = 1; - this.parameter = true; - this.dockTypes.push("booleanout"); - this.dockTypes.push("booleanin"); - this.generator = this.booleanOneBooleanArgBlockGenerator; - }; - - this.booleanOneBooleanArgBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - return [ - svg.booleanNot(false), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., and, or - this.booleanTwoBooleanArgBlock = function() { - this.style = "arg"; - this.size = 3; - this.args = 2; - this.parameter = true; - this.dockTypes.push("booleanout"); - this.dockTypes.push("booleanin"); - this.dockTypes.push("booleanin"); - this.generator = this.booleanTwoBooleanArgBlockGenerator; - }; - - this.booleanTwoBooleanArgBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - svg.setExpand(20 + this.extraWidth, 0, 0, 0); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + return [ + svg.booleanCompare(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; - return [ - svg.booleanAndOr(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., greater, less, equal - this.booleanTwoArgBlock = function() { - this.style = "arg"; - this.size = 2; - this.args = 2; - this.parameter = true; - this.expandable = true; - this.dockTypes.push("booleanout"); - this.dockTypes.push("numberin"); - this.dockTypes.push("numberin"); - this.generator = this.booleanTwoArgBlockGenerator; - }; - - this.booleanTwoArgBlockGenerator = function(expandY) { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - - if (expandY) { - svg.setExpand( - 10 + this.extraWidth, - ((expandY - 1) * STANDARDBLOCKHEIGHT) / 2, 0, 0); - } else { - svg.setExpand(10 + this.extraWidth, 0, 0, 0); - } + // E.g., color, shade, pensize, ... + this.parameterBlock = function () { + this.style = "arg"; + this.parameter = true; + this.size = 1; + this.args = 0; + this.dockTypes.push("numberout"); + this.generator = this.parameterBlockGenerator; + }; - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + this.parameterBlockGenerator = function () { + let svg = new SVG(); + svg.init(); + svg.setScale(this.scale); + // Extra room for parameter label + svg.setExpand(70 + this.extraWidth, 0, 0, 0); + svg.setOutie(true); - return [ - svg.booleanCompare(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; - - // E.g., color, shade, pensize, ... - this.parameterBlock = function() { - this.style = "arg"; - this.parameter = true; - this.size = 1; - this.args = 0; - this.dockTypes.push("numberout"); - this.generator = this.parameterBlockGenerator; - }; - - this.parameterBlockGenerator = function() { - let svg = new SVG(); - svg.init(); - svg.setScale(this.scale); - // Extra room for parameter label - svg.setExpand(70 + this.extraWidth, 0, 0, 0); - svg.setOutie(true); - - if (this.fontsize) { - svg.setFontSize(this.fontsize); - } + if (this.fontsize) { + svg.setFontSize(this.fontsize); + } - return [ - svg.basicBox(), - svg.docks, - svg.getWidth(), - svg.getHeight(), - svg.getHeight() - ]; - }; + return [ + svg.basicBox(), + svg.docks, + svg.getWidth(), + svg.getHeight(), + svg.getHeight() + ]; + }; + } } function isObject(item) { From d0f56ab4ef7ee3990c595196131fa5d83062dea5 Mon Sep 17 00:00:00 2001 From: kushal khare Date: Sat, 28 Nov 2020 20:17:00 +0530 Subject: [PATCH 03/26] adding classes to saveinterface.js --- js/SaveInterface.js | 835 ++++++++++++++++++++++---------------------- 1 file changed, 418 insertions(+), 417 deletions(-) diff --git a/js/SaveInterface.js b/js/SaveInterface.js index 3fbdfd8631..b93273b678 100644 --- a/js/SaveInterface.js +++ b/js/SaveInterface.js @@ -9,451 +9,452 @@ // License along with this library; if not, write to the Free Software // Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA -function SaveInterface(PlanetInterface) { - this.PlanetInterface = PlanetInterface; - this.logo = null; - this.turtles = null; - this.storage = null; - this.planet = null; - this.printBlockSVG = null; - - this.filename = null; - this.notationConvert = ""; - this.timeLastSaved = -100; - - this.htmlSaveTemplate = - ' {{ project_name }}

' + - _("Music Blocks Project") + - ' - {{ project_name }}

{{ project_description }}


' + - _("This project was created in Music Blocks") + - ' (https://musicblocks.sugarlabs.org). ' + - TITLESTRING + - " " + - _("Music Blocks is a Free/Libre Software application.") + - " " + - _("The source code can be accessed at") + - ' https://github.com/sugarlabs/musicblocks.' + - " " + - _("For more information, please consult the") + - ' ' + - _("Music Blocks Guide") + - "." + - "

" + - _("To run this project, open Music Blocks in a web browser and drag and drop this file into the browser window.") + - " " + - _("Alternatively, open the file in Music Blocks using the Load project button.") + - '

' + - _("Project Code") + - "

" + - _("This code stores data about the blocks in a project.") + - ' ' + - _("Show") + - '
{{ data }}
'; - - this.download = function(extension, dataurl, defaultfilename) { - let filename = null; - if (defaultfilename === undefined || defaultfilename === null) { - if (this.PlanetInterface === undefined) { - defaultfilename = _("My Project"); +class SaveInterface { + constructor(PlanetInterface) { + this.PlanetInterface = PlanetInterface; + this.logo = null; + this.turtles = null; + this.storage = null; + this.planet = null; + this.printBlockSVG = null; + + this.filename = null; + this.notationConvert = ""; + this.timeLastSaved = -100; + + this.htmlSaveTemplate = + ' {{ project_name }}

' + + _("Music Blocks Project") + + ' - {{ project_name }}

{{ project_description }}


' + + _("This project was created in Music Blocks") + + ' (https://musicblocks.sugarlabs.org). ' + + TITLESTRING + + " " + + _("Music Blocks is a Free/Libre Software application.") + + " " + + _("The source code can be accessed at") + + ' https://github.com/sugarlabs/musicblocks.' + + " " + + _("For more information, please consult the") + + ' ' + + _("Music Blocks Guide") + + "." + + "

" + + _("To run this project, open Music Blocks in a web browser and drag and drop this file into the browser window.") + + " " + + _("Alternatively, open the file in Music Blocks using the Load project button.") + + '

' + + _("Project Code") + + "

" + + _("This code stores data about the blocks in a project.") + + ' ' + + _("Show") + + '
{{ data }}
'; + + this.download = function (extension, dataurl, defaultfilename) { + let filename = null; + if (defaultfilename === undefined || defaultfilename === null) { + if (this.PlanetInterface === undefined) { + defaultfilename = _("My Project"); + } else { + defaultfilename = this.PlanetInterface.getCurrentProjectName(); + } + + console.debug(defaultfilename); + + if (fileExt(defaultfilename) != extension) { + defaultfilename += "." + extension; + } + + if (window.isElectron == true) { + filename = defaultfilename; + } else { + filename = prompt("Filename:", defaultfilename); + } } else { - defaultfilename = this.PlanetInterface.getCurrentProjectName(); + if (fileExt(defaultfilename) != extension) { + defaultfilename += "." + extension; + } + filename = defaultfilename; } - console.debug(defaultfilename); + console.debug(filename); + if (filename === null) { + console.debug("save cancelled"); + return; + } - if (fileExt(defaultfilename) != extension) { - defaultfilename += "." + extension; + if (fileExt(filename) != extension) { + filename += "." + extension; } - if (window.isElectron == true) { - filename = defaultfilename; - } else { - filename = prompt("Filename:", defaultfilename); + this.downloadURL(filename, dataurl); + }; + + this.downloadURL = function (filename, dataurl) { + let a = document.createElement("a"); + a.setAttribute("href", dataurl); + a.setAttribute("download", filename); + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + }; + + this.setVariables = function (vars) { + for (let i = 0; i < vars.length; i++) { + this[vars[i][0]] = vars[i][1]; + } + }; + + //Save Functions - n.b. include filename parameter - can be left blank / undefined + this.prepareHTML = function () { + let file = this.htmlSaveTemplate; + let description = _("No description provided"); + if (this.PlanetInterface !== undefined) { + description = this.PlanetInterface.getCurrentProjectDescription(); + } + + //let author = ''; //currently we're using anonymous for authors - not storing names + let name = _("My Project"); + if (this.PlanetInterface !== undefined) { + name = this.PlanetInterface.getCurrentProjectName(); } - } else { - if (fileExt(defaultfilename) != extension) { - defaultfilename += "." + extension; + + let data = prepareExport(); + let image = ""; + if (this.PlanetInterface !== undefined) { + image = this.PlanetInterface.getCurrentProjectImage(); } - filename = defaultfilename; - } - - console.debug(filename); - if (filename === null) { - console.debug("save cancelled"); - return; - } - - if (fileExt(filename) != extension) { - filename += "." + extension; - } - - this.downloadURL(filename, dataurl); - }; - - this.downloadURL = function(filename, dataurl) { - let a = document.createElement("a"); - a.setAttribute("href", dataurl); - a.setAttribute("download", filename); - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - }; - - this.setVariables = function(vars) { - for (let i = 0; i < vars.length; i++) { - this[vars[i][0]] = vars[i][1]; - } - }; - - //Save Functions - n.b. include filename parameter - can be left blank / undefined - this.prepareHTML = function() { - let file = this.htmlSaveTemplate; - let description = _("No description provided"); - if (this.PlanetInterface !== undefined) { - description = this.PlanetInterface.getCurrentProjectDescription(); - } - - //let author = ''; //currently we're using anonymous for authors - not storing names - let name = _("My Project"); - if (this.PlanetInterface !== undefined) { - name = this.PlanetInterface.getCurrentProjectName(); - } - - let data = prepareExport(); - let image = ""; - if (this.PlanetInterface !== undefined) { - image = this.PlanetInterface.getCurrentProjectImage(); - } - - file = file - .replace(new RegExp("{{ project_description }}", "g"), description) - .replace(new RegExp("{{ project_name }}", "g"), name) - .replace(new RegExp("{{ data }}", "g"), data) - .replace(new RegExp("{{ project_image }}", "g"), image); - return file; - }; - - this.saveHTML = function(filename) { - let html = "data:text/plain;charset=utf-8," + - encodeURIComponent(this.prepareHTML()); - console.debug(filename); - this.download("html", html, filename); - }; - - this.saveHTMLNoPrompt = function() { - setTimeout( - function() { - let html = "data:text/plain;charset=utf-8," + - encodeURIComponent(this.prepareHTML()); + + file = file + .replace(new RegExp("{{ project_description }}", "g"), description) + .replace(new RegExp("{{ project_name }}", "g"), name) + .replace(new RegExp("{{ data }}", "g"), data) + .replace(new RegExp("{{ project_image }}", "g"), image); + return file; + }; + + this.saveHTML = function (filename) { + let html = "data:text/plain;charset=utf-8," + + encodeURIComponent(this.prepareHTML()); + console.debug(filename); + this.download("html", html, filename); + }; + + this.saveHTMLNoPrompt = function () { + setTimeout( + function () { + let html = "data:text/plain;charset=utf-8," + + encodeURIComponent(this.prepareHTML()); + if (this.PlanetInterface !== undefined) { + this.downloadURL( + this.PlanetInterface.getCurrentProjectName() + ".html", + html); + } else { + this.downloadURL( + _("My Project").replace(" ", "_") + ".html", + html); + } + }.bind(this), + 500 + ); + }; + + this.saveSVG = function (filename) { + let svg = "data:image/svg+xml;utf8," + + doSVG( + this.logo.canvas, + this.logo, + this.logo.turtles, + this.logo.canvas.width, + this.logo.canvas.height, + 1.0 + ); + this.download("svg", svg, filename); + }; + + this.savePNG = function (filename) { + let png = docById("overlayCanvas").toDataURL("image/png"); + this.download("png", png, filename); + }; + + this.saveBlockArtwork = function (filename) { + let svg = "data:image/svg+xml;utf8," + this.printBlockSVG(); + this.download("svg", svg, filename); + }; + + this.saveWAV = function (filename) { + document.body.style.cursor = "wait"; + this.filename = filename; + this.logo.recording = true; + console.debug("DURING SAVE WAV"); + this.logo.synth.setupRecorder(); + this.logo.synth.recorder.start(); + this.logo.runLogoCommands(); + this.logo.textMsg(_("Your recording is in progress.")); + }; + + this.saveAbc = function (filename) { + document.body.style.cursor = "wait"; + this.filename = filename; + console.debug("Saving .abc file"); + //Suppress music and turtle output when generating + // Abc output. + this.logo.runningAbc = true; + this.logo.notationOutput = ABCHEADER; + this.logo.notationNotes = {}; + for (let t = 0; t < this.turtles.turtleList.length; t++) { + this.logo.notation.notationStaging[t] = []; + this.logo.notation.notationDrumStaging[t] = []; + this.turtles.turtleList[t].painter.doClear(true, true, true); + } + this.logo.runLogoCommands(); + }; + + this.afterSaveAbc = function (filename) { + let abc = encodeURIComponent(saveAbcOutput(this.logo)); + this.download("abc", "data:text;utf8," + abc, filename); + }; + + this.saveLilypond = function (filename) { + let lyext = "ly"; + if (filename === undefined) { if (this.PlanetInterface !== undefined) { - this.downloadURL( - this.PlanetInterface.getCurrentProjectName() + ".html", - html); + filename = this.PlanetInterface.getCurrentProjectName(); } else { - this.downloadURL( - _("My Project").replace(" ", "_") + ".html", - html); + filename = _("My Project"); } - }.bind(this), - 500 - ); - }; - - this.saveSVG = function(filename) { - let svg = - "data:image/svg+xml;utf8," + - doSVG( - this.logo.canvas, - this.logo, - this.logo.turtles, - this.logo.canvas.width, - this.logo.canvas.height, - 1.0 + } + + if (fileExt(filename) != lyext) { + filename += "." + lyext; + } + + console.debug("Saving .ly file"); + docById("lilypondModal").style.display = "block"; + let projectTitle, projectAuthor, MIDICheck, guitarCheck; + + //.TRANS: File name prompt for save as Lilypond + docById("fileNameText").textContent = _("File name"); + //.TRANS: Project title prompt for save as Lilypond + docById("titleText").textContent = _("Project title"); + //.TRANS: Project title prompt for save as Lilypond + docById("authorText").textContent = _("Project author"); + //.TRANS: MIDI prompt for save as Lilypond + docById("MIDIText").textContent = _("Include MIDI output?"); + //.TRANS: Guitar prompt for save as Lilypond + docById("guitarText").textContent = _( + "Include guitar tablature output?" ); - this.download("svg", svg, filename); - }; - - this.savePNG = function(filename) { - let png = docById("overlayCanvas").toDataURL("image/png"); - this.download("png", png, filename); - }; - - this.saveBlockArtwork = function(filename) { - let svg = "data:image/svg+xml;utf8," + this.printBlockSVG(); - this.download("svg", svg, filename); - }; - - this.saveWAV = function(filename) { - document.body.style.cursor = "wait"; - this.filename = filename; - this.logo.recording = true; - console.debug("DURING SAVE WAV"); - this.logo.synth.setupRecorder(); - this.logo.synth.recorder.start(); - this.logo.runLogoCommands(); - this.logo.textMsg(_("Your recording is in progress.")); - }; - - this.saveAbc = function(filename) { - document.body.style.cursor = "wait"; - this.filename = filename; - console.debug("Saving .abc file"); - //Suppress music and turtle output when generating - // Abc output. - this.logo.runningAbc = true; - this.logo.notationOutput = ABCHEADER; - this.logo.notationNotes = {}; - for (let t = 0; t < this.turtles.turtleList.length; t++) { - this.logo.notation.notationStaging[t] = []; - this.logo.notation.notationDrumStaging[t] = []; - this.turtles.turtleList[t].painter.doClear(true, true, true); - } - this.logo.runLogoCommands(); - }; - - this.afterSaveAbc = function(filename) { - let abc = encodeURIComponent(saveAbcOutput(this.logo)); - this.download("abc", "data:text;utf8," + abc, filename); - }; - - this.saveLilypond = function(filename) { - let lyext = "ly"; - if (filename === undefined) { + //.TRANS: Lilypond is a scripting language for generating sheet music + docById("submitLilypond").textContent = _("Save as Lilypond"); + docById("fileName").value = filename; if (this.PlanetInterface !== undefined) { - filename = this.PlanetInterface.getCurrentProjectName(); + docById("title").value = + this.PlanetInterface.getCurrentProjectName(); } else { - filename = _("My Project"); + //.TRANS: default project title when saving as Lilypond + docById("title").value = _("My Project"); } - } - - if (fileExt(filename) != lyext) { - filename += "." + lyext; - } - - console.debug("Saving .ly file"); - docById("lilypondModal").style.display = "block"; - let projectTitle, projectAuthor, MIDICheck, guitarCheck; - - //.TRANS: File name prompt for save as Lilypond - docById("fileNameText").textContent = _("File name"); - //.TRANS: Project title prompt for save as Lilypond - docById("titleText").textContent = _("Project title"); - //.TRANS: Project title prompt for save as Lilypond - docById("authorText").textContent = _("Project author"); - //.TRANS: MIDI prompt for save as Lilypond - docById("MIDIText").textContent = _("Include MIDI output?"); - //.TRANS: Guitar prompt for save as Lilypond - docById("guitarText").textContent = _( - "Include guitar tablature output?" - ); - //.TRANS: Lilypond is a scripting language for generating sheet music - docById("submitLilypond").textContent = _("Save as Lilypond"); - docById("fileName").value = filename; - if (this.PlanetInterface !== undefined) { - docById("title").value = - this.PlanetInterface.getCurrentProjectName(); - } else { - //.TRANS: default project title when saving as Lilypond - docById("title").value = _("My Project"); - } - - // Load custom author saved in local storage. - let customAuthorData = this.storage.getItem("customAuthor"); - if (customAuthorData != undefined) { - docById("author").value = JSON.parse(customAuthorData); - } else { - //.TRANS: default project author when saving as Lilypond - docById("author").value = _("Mr. Mouse"); - } - - docById("submitLilypond").onclick = function() { - this.saveLYFile(false); - }.bind(this); - // if (this.planet){ - // docById('submitPDF').onclick = function(){this.saveLYFile(true);}.bind(this); - // docById('submitPDF').disabled = false; - // } else { - // docById('submitPDF').disabled = true; - // } - let that = this; - docByClass("close")[0].onclick = function() { - that.logo.runningLilypond = false; - docById("lilypondModal").style.display = "none"; + + // Load custom author saved in local storage. + let customAuthorData = this.storage.getItem("customAuthor"); + if (customAuthorData != undefined) { + docById("author").value = JSON.parse(customAuthorData); + } else { + //.TRANS: default project author when saving as Lilypond + docById("author").value = _("Mr. Mouse"); + } + + docById("submitLilypond").onclick = function () { + this.saveLYFile(false); + }.bind(this); + // if (this.planet){ + // docById('submitPDF').onclick = function(){this.saveLYFile(true);}.bind(this); + // docById('submitPDF').disabled = false; + // } else { + // docById('submitPDF').disabled = true; + // } + let that = this; + docByClass("close")[0].onclick = function () { + that.logo.runningLilypond = false; + docById("lilypondModal").style.display = "none"; + }; }; - }; - this.saveLYFile = function(isPDF) { - if (isPDF === undefined) { - isPDF = false; - } - let filename = docById("fileName").value; - let projectTitle = docById("title").value; - let projectAuthor = docById("author").value; + this.saveLYFile = function (isPDF) { + if (isPDF === undefined) { + isPDF = false; + } + let filename = docById("fileName").value; + let projectTitle = docById("title").value; + let projectAuthor = docById("author").value; + + // Save the author in local storage. + this.storage.setItem("customAuthor", JSON.stringify(projectAuthor)); - // Save the author in local storage. - this.storage.setItem("customAuthor", JSON.stringify(projectAuthor)); + let MIDICheck = docById("MIDICheck").checked; + let guitarCheck = docById("guitarCheck").checked; - let MIDICheck = docById("MIDICheck").checked; - let guitarCheck = docById("guitarCheck").checked; + if (filename != null) { + if (fileExt(filename) !== "ly") { + filename += ".ly"; + } + } - if (filename != null) { - if (fileExt(filename) !== "ly") { - filename += ".ly"; + let mapLilypondObj = { + "My Music Blocks Creation": projectTitle, + "Mr. Mouse": projectAuthor + }; + + let lyheader = LILYPONDHEADER.replace( + /My Music Blocks Creation|Mr. Mouse/gi, + function (matched) { + return mapLilypondObj[matched]; + } + ); + + if (MIDICheck) { + MIDIOutput = + "% MIDI SECTION\n% MIDI Output included! \n\n\\midi {\n \\tempo 4=90\n}\n\n\n}\n\n"; + } else { + MIDIOutput = + "% MIDI SECTION\n% Delete the %{ and %} below to include MIDI output.\n%{\n\\midi {\n \\tempo 4=90\n}\n%}\n\n}\n\n"; + } + + if (guitarCheck) { + guitarOutputHead = + '\n\n% GUITAR TAB SECTION\n% Guitar tablature output included!\n\n \\new TabStaff = "guitar tab" \n <<\n \\clef moderntab\n'; + guitarOutputEnd = " >>\n\n"; + } else { + guitarOutputHead = + '\n\n% GUITAR TAB SECTION\n% Delete the %{ and %} below to include guitar tablature output.\n%{\n \\new TabStaff = "guitar tab" \n <<\n \\clef moderntab\n'; + guitarOutputEnd = " >>\n%}\n"; + } + + // Suppress music and turtle output when generating + // Lilypond output. + this.logo.runningLilypond = true; + if (isPDF) { + this.notationConvert = "pdf"; + } else { + this.notationConvert = ""; + } + this.logo.notationOutput = lyheader; + this.logo.notationNotes = {}; + for (let t = 0; t < this.turtles.turtleList.length; t++) { + this.logo.notation.notationStaging[t] = []; + this.logo.notation.notationDrumStaging[t] = []; + this.turtles.turtleList[t].painter.doClear(true, true, true); } - } + document.body.style.cursor = "wait"; + this.logo.runLogoCommands(); - let mapLilypondObj = { - "My Music Blocks Creation": projectTitle, - "Mr. Mouse": projectAuthor + // Close the dialog box after hitting button. + docById("lilypondModal").style.display = "none"; }; - let lyheader = LILYPONDHEADER.replace( - /My Music Blocks Creation|Mr. Mouse/gi, - function(matched) { - return mapLilypondObj[matched]; + this.afterSaveLilypond = function (filename) { + let ly = saveLilypondOutput(this.logo); + switch (this.notationConvert) { + case "pdf": + this.afterSaveLilypondPDF(ly, filename); + break; + default: + this.afterSaveLilypondLY(ly, filename); + break; } - ); - - if (MIDICheck) { - MIDIOutput = - "% MIDI SECTION\n% MIDI Output included! \n\n\\midi {\n \\tempo 4=90\n}\n\n\n}\n\n"; - } else { - MIDIOutput = - "% MIDI SECTION\n% Delete the %{ and %} below to include MIDI output.\n%{\n\\midi {\n \\tempo 4=90\n}\n%}\n\n}\n\n"; - } - - if (guitarCheck) { - guitarOutputHead = - '\n\n% GUITAR TAB SECTION\n% Guitar tablature output included!\n\n \\new TabStaff = "guitar tab" \n <<\n \\clef moderntab\n'; - guitarOutputEnd = " >>\n\n"; - } else { - guitarOutputHead = - '\n\n% GUITAR TAB SECTION\n% Delete the %{ and %} below to include guitar tablature output.\n%{\n \\new TabStaff = "guitar tab" \n <<\n \\clef moderntab\n'; - guitarOutputEnd = " >>\n%}\n"; - } - - // Suppress music and turtle output when generating - // Lilypond output. - this.logo.runningLilypond = true; - if (isPDF) { - this.notationConvert = "pdf"; - } else { this.notationConvert = ""; - } - this.logo.notationOutput = lyheader; - this.logo.notationNotes = {}; - for (let t = 0; t < this.turtles.turtleList.length; t++) { - this.logo.notation.notationStaging[t] = []; - this.logo.notation.notationDrumStaging[t] = []; - this.turtles.turtleList[t].painter.doClear(true, true, true); - } - document.body.style.cursor = "wait"; - this.logo.runLogoCommands(); - - // Close the dialog box after hitting button. - docById("lilypondModal").style.display = "none"; - }; - - this.afterSaveLilypond = function(filename) { - let ly = saveLilypondOutput(this.logo); - switch (this.notationConvert) { - case "pdf": - this.afterSaveLilypondPDF(ly, filename); - break; - default: - this.afterSaveLilypondLY(ly, filename); - break; - } - this.notationConvert = ""; - }; - - this.afterSaveLilypondLY = function(lydata, filename) { - if (platform.FF) { - console.debug('execCommand("copy") does not work on FireFox'); - } else { - let tmp = jQuery("