diff --git a/HISTORY.md b/HISTORY.md index 0c9b3367..dc42b30f 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,7 @@ ### 2019-01-14 * Symbols: added 'loop' arrow symbol +* Blocks, Objects, Store: added 'loop' symbol to primitive loop blocks ### 2019-01-12 * Threads: try to identify Brian's problem with parsing a CSV diff --git a/snap.html b/snap.html index a2885653..ef33897b 100755 --- a/snap.html +++ b/snap.html @@ -6,9 +6,9 @@ - + - + @@ -17,7 +17,7 @@ - + diff --git a/src/blocks.js b/src/blocks.js index b5d9bf0a..b5e9c3bd 100644 --- a/src/blocks.js +++ b/src/blocks.js @@ -148,7 +148,7 @@ CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2019-January-09'; +modules.blocks = '2019-January-14'; var SyntaxElementMorph; var BlockMorph; @@ -778,6 +778,8 @@ SyntaxElementMorph.prototype.setLabelColor = function ( || (morph instanceof InputSlotMorph && morph.isReadOnly)) { morph.setLabelColor(textColor, shadowColor, shadowOffset); + } else if (morph.isLoop) { // C-shaped slot with loop arrow symbol + morph.loop().setLabelColor(textColor, shadowColor, shadowOffset); } }); }; @@ -1467,6 +1469,21 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { part.isStatic = true; // rejects reporter drops part.isLambda = true; // auto-reifies nested script break; + case '%loop': + part = new CSlotMorph(); + part.isStatic = true; + part.isLoop = true; // has a loop symbol + part.add(this.labelPart('%loopArrow')); + break; + case '%loopArrow': + part = new SymbolMorph('loop'); + part.size = this.fontSize * 0.7; + part.color = new Color(255, 255, 255); + part.shadowColor = this.color.darker(this.labelContrast); + part.shadowOffset = MorphicPreferences.isFlat ? + new Point() : this.embossing; + part.drawNew(); + break; case '%clr': part = new ColorSlotMorph(); part.isStatic = true; @@ -1781,7 +1798,7 @@ SyntaxElementMorph.prototype.fixLayout = function (silently) { } else { part.setPosition(new Point(x, y)); if (!part.isBlockLabelBreak) { - if (part.slotSpec === '%c') { + if (part.slotSpec === '%c' || part.slotSpec === '%loop') { x += part.width(); } else if (part.isVisible) { x += part.fullBounds().width() + space; @@ -7821,6 +7838,7 @@ CSlotMorph.prototype.init = function (silently) { CommandSlotMorph.uber.init.call(this, null, true); // silently this.isHole = true; this.isLambda = false; // see Process.prototype.evaluateInput + this.isLoop = false; // has a loop arrow symbol this.color = new Color(0, 17, 173); this.setExtent( new Point(230, this.corner * 4 + this.cSlotPadding), @@ -7829,7 +7847,7 @@ CSlotMorph.prototype.init = function (silently) { }; CSlotMorph.prototype.getSpec = function () { - return '%c'; + return this.isLoop? '%loop' : '%c'; }; CSlotMorph.prototype.mappedCode = function (definitions) { @@ -7857,7 +7875,6 @@ CSlotMorph.prototype.mappedCode = function (definitions) { return codeLines.join('\n'); }; - // CSlotMorph layout: CSlotMorph.prototype.fixLayout = function () { @@ -7885,10 +7902,38 @@ CSlotMorph.prototype.fixLayout = function () { } }; +CSlotMorph.prototype.fixLoopLayout = function () { + var loop; + if (this.isLoop) { + loop = this.loop(); + if (loop) { + loop.setRight(this.right() - this.corner); + loop.setBottom(this.bottom() + this.cSlotPadding + this.edge); + } + } +}; + +CSlotMorph.prototype.loop = function () { + if (this.isLoop) { + return detect( + this.children, + function (child) { + return child instanceof SymbolMorph; + } + ); + } + return null; +}; + // CSlotMorph drawing: CSlotMorph.prototype.drawNew = function () { var context; + + // position loop symbol, if any + this.fixLoopLayout(); + + // init this.cachedClr = this.color.toString(); this.cachedClrBright = this.bright(); this.cachedClrDark = this.dark(); diff --git a/src/objects.js b/src/objects.js index b238d74c..b6713599 100644 --- a/src/objects.js +++ b/src/objects.js @@ -83,7 +83,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize, TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph, AlignmentMorph, Process, XML_Element, VectorPaintEditorMorph*/ -modules.objects = '2019-January-11'; +modules.objects = '2019-January-14'; var SpriteMorph; var StageMorph; @@ -605,18 +605,18 @@ SpriteMorph.prototype.initBlocks = function () { doForever: { type: 'command', category: 'control', - spec: 'forever %c' + spec: 'forever %loop' }, doRepeat: { type: 'command', category: 'control', - spec: 'repeat %n %c', + spec: 'repeat %n %loop', defaults: [10] }, doUntil: { type: 'command', category: 'control', - spec: 'repeat until %b %c' + spec: 'repeat until %b %loop' }, doIf: { type: 'command', diff --git a/src/store.js b/src/store.js index 83bc3623..0c7daf6b 100644 --- a/src/store.js +++ b/src/store.js @@ -61,7 +61,7 @@ normalizeCanvas, contains*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2019-January-11'; +modules.store = '2019-January-14'; // XML_Serializer /////////////////////////////////////////////////////// @@ -2104,7 +2104,7 @@ TemplateSlotMorph.prototype.toXML = function (serializer) { }; CommandSlotMorph.prototype.toXML = function (serializer) { - var block = this.children[0]; + var block = this.nestedBlock(); if (block instanceof BlockMorph) { if (block instanceof ReporterBlockMorph) { return serializer.format( diff --git a/src/symbols.js b/src/symbols.js index 535d06cb..afdac60e 100644 --- a/src/symbols.js +++ b/src/symbols.js @@ -1269,7 +1269,7 @@ SymbolMorph.prototype.drawSymbolLoop = function (canvas, aColor) { w2 = canvas.width / 2, w4 = w2 / 2, h2 = canvas.height / 2, - l = Math.max(h / 20, 0.5); + l = Math.max(h / 10, 0.5); ctx.lineWidth = l * 2; ctx.strokeStyle = aColor.toString();