summaryrefslogtreecommitdiff
path: root/blocks.js
diff options
context:
space:
mode:
Diffstat (limited to 'blocks.js')
-rw-r--r--blocks.js191
1 files changed, 133 insertions, 58 deletions
diff --git a/blocks.js b/blocks.js
index e56d0ed..0a4c5ed 100644
--- a/blocks.js
+++ b/blocks.js
@@ -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();