diff options
Diffstat (limited to 'blocks.js')
| -rw-r--r-- | blocks.js | 191 |
1 files changed, 133 insertions, 58 deletions
@@ -9,7 +9,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2014 by Jens Mönig + Copyright (C) 2015 by Jens Mönig This file is part of Snap!. @@ -155,8 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2014-November-21'; - +modules.blocks = '2015-June-25'; var SyntaxElementMorph; var BlockMorph; @@ -340,6 +339,7 @@ SyntaxElementMorph.prototype.setScale = function (num) { }; SyntaxElementMorph.prototype.setScale(1); +SyntaxElementMorph.prototype.isCachingInputs = false; // SyntaxElementMorph instance creation: @@ -356,8 +356,13 @@ SyntaxElementMorph.prototype.init = function () { SyntaxElementMorph.uber.init.call(this); this.defaults = []; + this.cachedInputs = null; }; +// SyntaxElementMorph stepping: + +SyntaxElementMorph.prototype.step = null; + // SyntaxElementMorph accessing: SyntaxElementMorph.prototype.parts = function () { @@ -375,10 +380,39 @@ SyntaxElementMorph.prototype.parts = function () { SyntaxElementMorph.prototype.inputs = function () { // answer my arguments and nested reporters - return this.parts().filter(function (part) { - return part instanceof SyntaxElementMorph; - }); + if (isNil(this.cachedInputs) || !this.isCachingInputs) { + this.cachedInputs = this.parts().filter(function (part) { + return part instanceof SyntaxElementMorph; + }); + } + // this.debugCachedInputs(); + return this.cachedInputs; +}; +SyntaxElementMorph.prototype.debugCachedInputs = function () { + // private - only used for manually debugging inputs caching + var realInputs, i; + if (!isNil(this.cachedInputs)) { + realInputs = this.parts().filter(function (part) { + return part instanceof SyntaxElementMorph; + }); + } + if (this.cachedInputs.length !== realInputs.length) { + throw new Error('cached inputs size do not match: ' + + this.constructor.name); + } + for (i = 0; i < realInputs.length; i += 1) { + if (this.cachedInputs[i] !== realInputs[i]) { + throw new Error('cached input does not match: ' + + this.constructor.name + + ' #' + + i + + ' ' + + this.cachedInputs[i].constructor.name + + ' != ' + + realInputs[i].constructor.name); + } + } }; SyntaxElementMorph.prototype.allInputs = function () { @@ -494,6 +528,7 @@ SyntaxElementMorph.prototype.replaceInput = function (oldArg, newArg) { replacement.drawNew(); this.fixLayout(); } + this.cachedInputs = null; this.endLayout(); }; @@ -529,6 +564,7 @@ SyntaxElementMorph.prototype.silentReplaceInput = function (oldArg, newArg) { replacement.drawNew(); this.fixLayout(); } + this.cachedInputs = null; }; SyntaxElementMorph.prototype.revertToDefaultInput = function (arg, noValues) { @@ -571,6 +607,7 @@ SyntaxElementMorph.prototype.revertToDefaultInput = function (arg, noValues) { } else if (deflt instanceof RingMorph) { deflt.fixBlockColor(); } + this.cachedInputs = null; }; SyntaxElementMorph.prototype.isLocked = function () { @@ -848,6 +885,20 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { true // read-only ); break; + case '%interaction': + part = new InputSlotMorph( + null, // text + false, // numeric? + { + 'clicked' : ['clicked'], + 'pressed' : ['pressed'], + 'dropped' : ['dropped'], + 'mouse-entered' : ['mouse-entered'], + 'mouse-departed' : ['mouse-departed'] + }, + true // read-only + ); + break; case '%dates': part = new InputSlotMorph( null, // text @@ -1063,9 +1114,9 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { acos : ['acos'], atan : ['atan'], ln : ['ln'], - // log : 'log', - 'e^' : ['e^'] - // '10^' : '10^' + log : ['log'], + 'e^' : ['e^'], + '10^' : ['10^'] }, true ); @@ -1369,16 +1420,19 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { new Point() : this.embossing; part.drawNew(); } else { - part = new StringMorph(spec); - part.fontName = this.labelFontName; - part.fontStyle = this.labelFontStyle; - part.fontSize = this.fontSize; - part.color = new Color(255, 255, 255); - part.isBold = true; - part.shadowColor = this.color.darker(this.labelContrast); - part.shadowOffset = MorphicPreferences.isFlat ? - new Point() : this.embossing; - part.drawNew(); + part = new StringMorph( + spec, // text + this.fontSize, // fontSize + this.labelFontStyle, // fontStyle + true, // bold + false, // italic + false, // isNumeric + MorphicPreferences.isFlat ? + new Point() : this.embossing, // shadowOffset + this.color.darker(this.labelContrast), // shadowColor + new Color(255, 255, 255), // color + this.labelFontName // fontName + ); } return part; }; @@ -1895,6 +1949,7 @@ BlockMorph.uber = SyntaxElementMorph.prototype; // BlockMorph preferences settings: +BlockMorph.prototype.isCachingInputs = true; BlockMorph.prototype.zebraContrast = 40; // alternating color brightness // BlockMorph sound feedback: @@ -1928,6 +1983,7 @@ BlockMorph.prototype.init = function () { BlockMorph.uber.init.call(this); this.color = new Color(0, 17, 173); + this.cashedInputs = null; }; BlockMorph.prototype.receiver = function () { @@ -2008,7 +2064,8 @@ BlockMorph.prototype.setSpec = function (spec) { } part = myself.labelPart(word); myself.add(part); - if (!(part instanceof CommandSlotMorph)) { + if (!(part instanceof CommandSlotMorph || + part instanceof StringMorph)) { part.drawNew(); } if (part instanceof RingMorph) { @@ -2033,6 +2090,7 @@ BlockMorph.prototype.setSpec = function (spec) { }); this.blockSpec = spec; this.fixLayout(); + this.cachedInputs = null; }; BlockMorph.prototype.buildSpec = function () { @@ -2174,7 +2232,7 @@ BlockMorph.prototype.userMenu = function () { ); if (this instanceof CommandBlockMorph && this.nextBlock()) { menu.addItem( - this.thumbnail(0.5, 60, false), + this.thumbnail(0.5, 60), function () { var cpy = this.fullCopy(), nb = cpy.nextBlock(), @@ -2425,6 +2483,7 @@ BlockMorph.prototype.restoreInputs = function (oldInputs) { } i += 1; }); + this.cachedInputs = null; }; BlockMorph.prototype.showHelp = function () { @@ -3012,6 +3071,14 @@ BlockMorph.prototype.fullCopy = function () { ans.setSpec(this.instantiationSpec); } ans.allChildren().filter(function (block) { + if (block instanceof SyntaxElementMorph) { + block.cachedInputs = null; + if (block instanceof InputSlotMorph) { + block.contents().clearSelection(); + } + } else if (block instanceof CursorMorph) { + block.destroy(); + } return !isNil(block.comment); }).forEach(function (block) { var cmnt = block.comment.fullCopy(); @@ -3020,6 +3087,7 @@ BlockMorph.prototype.fullCopy = function () { //block.comment = null; }); + ans.cachedInputs = null; return ans; }; @@ -3042,38 +3110,34 @@ BlockMorph.prototype.mouseClickLeft = function () { // BlockMorph thumbnail -BlockMorph.prototype.thumbnail = function (scale, clipWidth, noShadow) { - var block = this.fullCopy(), - nb = block.nextBlock(), +BlockMorph.prototype.thumbnail = function (scale, clipWidth) { + var nb = this.nextBlock(), fadeout = 12, ext, trgt, ctx, gradient; - if (nb) {nb.destroy(); } - if (!noShadow) {block.addShadow(); } - ext = block.fullBounds().extent(); - if (!noShadow) { - ext = ext.subtract(this.shadowBlur * - (useBlurredShadows && !MorphicPreferences.isFlat ? 1 : 2)); - } + + if (nb) {nb.isVisible = false; } + ext = this.fullBounds().extent(); trgt = newCanvas(new Point( - Math.min(ext.x * scale, clipWidth || ext.x), + clipWidth ? Math.min(ext.x * scale, clipWidth) : ext.x * scale, ext.y * scale )); ctx = trgt.getContext('2d'); ctx.scale(scale, scale); - ctx.drawImage(block.fullImage(), 0, 0); + ctx.drawImage(this.fullImage(), 0, 0); // draw fade-out - if (trgt.width === clipWidth) { + if (clipWidth && ext.x * scale > clipWidth) { gradient = ctx.createLinearGradient( trgt.width / scale - fadeout, 0, trgt.width / scale, 0 ); - gradient.addColorStop(0, new Color(255, 255, 255, 0).toString()); - gradient.addColorStop(1, 'white'); + gradient.addColorStop(0, 'transparent'); + gradient.addColorStop(1, 'black'); + ctx.globalCompositeOperation = 'destination-out'; ctx.fillStyle = gradient; ctx.fillRect( trgt.width / scale - fadeout, @@ -3082,6 +3146,7 @@ BlockMorph.prototype.thumbnail = function (scale, clipWidth, noShadow) { trgt.height / scale ); } + if (nb) {nb.isVisible = true; } return trgt; }; @@ -4589,6 +4654,7 @@ RingMorph.uber = ReporterBlockMorph.prototype; // RingMorph preferences settings: +RingMorph.prototype.isCachingInputs = false; // RingMorph.prototype.edge = 2; // RingMorph.prototype.rounding = 9; // RingMorph.prototype.alpha = 0.8; @@ -6855,7 +6921,8 @@ InputSlotMorph.prototype.setChoices = function (dict, readonly) { // InputSlotMorph layout: InputSlotMorph.prototype.fixLayout = function () { - var contents = this.contents(), + var width, height, arrowWidth, + contents = this.contents(), arrow = this.arrow(); contents.isNumeric = this.isNumeric; @@ -6872,35 +6939,32 @@ InputSlotMorph.prototype.fixLayout = function () { arrow.setSize(this.fontSize); arrow.show(); } else { - arrow.setSize(0); arrow.hide(); } - this.setHeight( - contents.height() - + this.edge * 2 - // + this.typeInPadding * 2 - ); + arrowWidth = arrow.isVisible ? arrow.width() : 0; + + height = contents.height() + this.edge * 2; // + this.typeInPadding * 2 if (this.isNumeric) { - this.setWidth(contents.width() - + Math.floor(arrow.width() * 0.5) - + this.height() - + this.typeInPadding * 2 - ); + width = contents.width() + + Math.floor(arrowWidth * 0.5) + + height + + this.typeInPadding * 2; } else { - this.setWidth(Math.max( + width = Math.max( contents.width() - + arrow.width() + + arrowWidth + this.edge * 2 + this.typeInPadding * 2, contents.rawHeight ? // single vs. multi-line contents - contents.rawHeight() + arrow.width() - : contents.height() / 1.2 + arrow.width(), + contents.rawHeight() + arrowWidth + : contents.height() / 1.2 + arrowWidth, this.minWidth // for text-type slots - )); + ); } + this.setExtent(new Point(width, height)); if (this.isNumeric) { contents.setPosition(new Point( - Math.floor(this.height() / 2), + Math.floor(height / 2), this.edge ).add(new Point(this.typeInPadding, 0)).add(this.position())); } else { @@ -6910,10 +6974,12 @@ InputSlotMorph.prototype.fixLayout = function () { ).add(new Point(this.typeInPadding, 0)).add(this.position())); } - arrow.setPosition(new Point( - this.right() - arrow.width() - this.edge, - contents.top() - )); + if (arrow.isVisible) { + arrow.setPosition(new Point( + this.right() - arrowWidth - this.edge, + contents.top() + )); + } if (this.parent) { if (this.parent.fixLayout) { @@ -6930,6 +6996,15 @@ InputSlotMorph.prototype.fixLayout = function () { // InputSlotMorph events: +InputSlotMorph.prototype.mouseDownLeft = function (pos) { + if (this.isReadOnly || this.arrow().bounds.containsPoint(pos)) { + this.escalateEvent('mouseDownLeft', pos); + } else { + this.contents().edit(); + this.contents().selectAll(); + } +}; + InputSlotMorph.prototype.mouseClickLeft = function (pos) { if (this.arrow().bounds.containsPoint(pos)) { this.dropDownMenu(); |
