kopia lustrzana https://github.com/backface/turtlestitch
Prepare for v4.0.3
* fixed occasional horizontal rendering artifacts in block “holes” (C-shaped slots and Ring holes) * improved user editing of input slots and fixed cursor behavior (note: the text cursor inside input slots also blinks again, as it should have) * always export comments attached to prototype hat blocks in the block editor along with script pic * when first opening a block editor on a custom block definition make it big enough to show everything (as much as fits on the screen) * remember block editor position and dimensions for each edited custom block definition when acknowledging (pressing OK or APPLY) for the session * speed up stacking of commands and loading of projects by suppressing redundant block redraws * introducing a “grab threshold” preference to suppress accidental grabbing through micro-movements of the hand. This addresses the “cannot-click-on-drop-downs-in-Chrome-under-Windows” set of bug reports, and also the issues that arise out of accidentally dragging off a copy of a parameter blob when trying to just click on it to rename it * new hidden (shift-click) option to adjust the grab threshold in the settings menu for the current session * expand list watchers inside result bubbles and speech/thought balloons to show everything (as much of the list’s first level as fist into either the scripting area for result bubbles or the stage for speech balloons - note resizing the stage affects the size of the list watchers inside speech balloons, i.e. making the stage bigger increases the number of visible elements even while the balloon is showing) * fixed a bug that make an occasional gray rectangle appear at the mouse pointer * added a way to invoke blocks synchronously in JavaScript - under construction (possibly to be used for generic “When” hat blocks and user-customizable drop-downs) * added methods to cache morphs’ fullImage and fullBounds while dragging * Reporters (also nested reporters) and sprite icons (in the corral) are now semi-transparent when being dragged, so you can see possible drop target halos /through/ them * in “prefer empty slot drops” mode (default) it is now much harder to drop reporters onto non-static C-slots inside custom blocks (e.g. in FOR loops) and onto variadic input arrowheads (to replace the whole input with an input list) * ScriptsMorphs are now noticing transparent clicks (addresses #997) * %interaction slots are now static, fixed #982 (it is no longer possible to drop reporters into the input slot of a “When I am…” hat block (never was intended that it should be possible) * fixed ctrl-f for the block editor in all situations (thanks, Brian, for the bug report)dev
rodzic
72bf4cfb8c
commit
6061403a89
183
blocks.js
183
blocks.js
|
|
@ -156,7 +156,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.blocks = '2015-October-02';
|
modules.blocks = '2015-November-16';
|
||||||
|
|
||||||
var SyntaxElementMorph;
|
var SyntaxElementMorph;
|
||||||
var BlockMorph;
|
var BlockMorph;
|
||||||
|
|
@ -349,22 +349,18 @@ function SyntaxElementMorph() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxElementMorph.prototype.init = function () {
|
SyntaxElementMorph.prototype.init = function (silently) {
|
||||||
this.cachedClr = null;
|
this.cachedClr = null;
|
||||||
this.cachedClrBright = null;
|
this.cachedClrBright = null;
|
||||||
this.cachedClrDark = null;
|
this.cachedClrDark = null;
|
||||||
this.isStatic = false; // if true, I cannot be exchanged
|
this.isStatic = false; // if true, I cannot be exchanged
|
||||||
|
|
||||||
SyntaxElementMorph.uber.init.call(this);
|
SyntaxElementMorph.uber.init.call(this, silently);
|
||||||
|
|
||||||
this.defaults = [];
|
this.defaults = [];
|
||||||
this.cachedInputs = null;
|
this.cachedInputs = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// SyntaxElementMorph stepping:
|
|
||||||
|
|
||||||
SyntaxElementMorph.prototype.step = null;
|
|
||||||
|
|
||||||
// SyntaxElementMorph accessing:
|
// SyntaxElementMorph accessing:
|
||||||
|
|
||||||
SyntaxElementMorph.prototype.parts = function () {
|
SyntaxElementMorph.prototype.parts = function () {
|
||||||
|
|
@ -472,8 +468,7 @@ SyntaxElementMorph.prototype.replaceInput = function (oldArg, newArg) {
|
||||||
var scripts = this.parentThatIsA(ScriptsMorph),
|
var scripts = this.parentThatIsA(ScriptsMorph),
|
||||||
replacement = newArg,
|
replacement = newArg,
|
||||||
idx = this.children.indexOf(oldArg),
|
idx = this.children.indexOf(oldArg),
|
||||||
i = 0,
|
i = 0;
|
||||||
nb;
|
|
||||||
|
|
||||||
// try to find the ArgLabel embedding the newArg,
|
// try to find the ArgLabel embedding the newArg,
|
||||||
// used for the undrop() feature
|
// used for the undrop() feature
|
||||||
|
|
@ -511,13 +506,6 @@ SyntaxElementMorph.prototype.replaceInput = function (oldArg, newArg) {
|
||||||
oldArg.moveBy(replacement.extent());
|
oldArg.moveBy(replacement.extent());
|
||||||
oldArg.fixBlockColor();
|
oldArg.fixBlockColor();
|
||||||
}
|
}
|
||||||
} else if (oldArg instanceof CommandSlotMorph) {
|
|
||||||
nb = oldArg.nestedBlock();
|
|
||||||
if (nb) {
|
|
||||||
scripts.add(nb);
|
|
||||||
nb.moveBy(replacement.extent());
|
|
||||||
nb.fixBlockColor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (replacement instanceof MultiArgMorph
|
if (replacement instanceof MultiArgMorph
|
||||||
|| replacement instanceof ArgLabelMorph
|
|| replacement instanceof ArgLabelMorph
|
||||||
|
|
@ -703,10 +691,11 @@ SyntaxElementMorph.prototype.dark = function () {
|
||||||
|
|
||||||
// SyntaxElementMorph color changing:
|
// SyntaxElementMorph color changing:
|
||||||
|
|
||||||
SyntaxElementMorph.prototype.setColor = function (aColor) {
|
SyntaxElementMorph.prototype.setColor = function (aColor, silently) {
|
||||||
if (aColor) {
|
if (aColor) {
|
||||||
if (!this.color.eq(aColor)) {
|
if (!this.color.eq(aColor)) {
|
||||||
this.color = aColor;
|
this.color = aColor;
|
||||||
|
if (silently) {return; }
|
||||||
this.drawNew();
|
this.drawNew();
|
||||||
this.children.forEach(function (child) {
|
this.children.forEach(function (child) {
|
||||||
child.drawNew();
|
child.drawNew();
|
||||||
|
|
@ -942,6 +931,7 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
|
||||||
},
|
},
|
||||||
true // read-only
|
true // read-only
|
||||||
);
|
);
|
||||||
|
part.isStatic = true;
|
||||||
break;
|
break;
|
||||||
case '%dates':
|
case '%dates':
|
||||||
part = new InputSlotMorph(
|
part = new InputSlotMorph(
|
||||||
|
|
@ -1302,6 +1292,11 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
|
||||||
case '%cs':
|
case '%cs':
|
||||||
part = new CSlotMorph(); // non-static
|
part = new CSlotMorph(); // non-static
|
||||||
break;
|
break;
|
||||||
|
case '%cl':
|
||||||
|
part = new CSlotMorph();
|
||||||
|
part.isStatic = true; // rejects reporter drops
|
||||||
|
part.isLambda = true; // auto-reifies nested script
|
||||||
|
break;
|
||||||
case '%clr':
|
case '%clr':
|
||||||
part = new ColorSlotMorph();
|
part = new ColorSlotMorph();
|
||||||
part.isStatic = true;
|
part.isStatic = true;
|
||||||
|
|
@ -1501,7 +1496,7 @@ SyntaxElementMorph.prototype.isObjInputFragment = function () {
|
||||||
|
|
||||||
// SyntaxElementMorph layout:
|
// SyntaxElementMorph layout:
|
||||||
|
|
||||||
SyntaxElementMorph.prototype.fixLayout = function () {
|
SyntaxElementMorph.prototype.fixLayout = function (silently) {
|
||||||
var nb,
|
var nb,
|
||||||
parts = this.parts(),
|
parts = this.parts(),
|
||||||
myself = this,
|
myself = this,
|
||||||
|
|
@ -1682,8 +1677,8 @@ SyntaxElementMorph.prototype.fixLayout = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set my extent:
|
// set my extent (silently, because we'll redraw later anyway):
|
||||||
this.setExtent(new Point(blockWidth, blockHeight));
|
this.silentSetExtent(new Point(blockWidth, blockHeight));
|
||||||
|
|
||||||
// adjust CSlots
|
// adjust CSlots
|
||||||
parts.forEach(function (part) {
|
parts.forEach(function (part) {
|
||||||
|
|
@ -1697,7 +1692,7 @@ SyntaxElementMorph.prototype.fixLayout = function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
// redraw in order to erase CSlot backgrounds
|
// redraw in order to erase CSlot backgrounds
|
||||||
this.drawNew();
|
if (!silently) {this.drawNew(); }
|
||||||
|
|
||||||
// position next block:
|
// position next block:
|
||||||
if (nb) {
|
if (nb) {
|
||||||
|
|
@ -1777,6 +1772,7 @@ SyntaxElementMorph.prototype.showBubble = function (value, exportPic) {
|
||||||
morphToShow.update(true);
|
morphToShow.update(true);
|
||||||
morphToShow.step = value.update;
|
morphToShow.step = value.update;
|
||||||
morphToShow.isDraggable = false;
|
morphToShow.isDraggable = false;
|
||||||
|
morphToShow.expand(this.parentThatIsA(ScrollFrameMorph).extent());
|
||||||
isClickable = true;
|
isClickable = true;
|
||||||
} else if (value instanceof Morph) {
|
} else if (value instanceof Morph) {
|
||||||
img = value.fullImage();
|
img = value.fullImage();
|
||||||
|
|
@ -1954,7 +1950,9 @@ SyntaxElementMorph.prototype.endLayout = function () {
|
||||||
%lst - chameleon colored rectangular drop-down for list names
|
%lst - chameleon colored rectangular drop-down for list names
|
||||||
%b - chameleon colored hexagonal slot (for predicates)
|
%b - chameleon colored hexagonal slot (for predicates)
|
||||||
%l - list icon
|
%l - list icon
|
||||||
%c - C-shaped command slot
|
%c - C-shaped command slot, special form for primitives
|
||||||
|
%cs - C-shaped, auto-reifying, accepts reporter drops
|
||||||
|
%cl - C-shaped, auto-reifying, rejects reporters
|
||||||
%clr - interactive color slot
|
%clr - interactive color slot
|
||||||
%t - inline variable reporter template
|
%t - inline variable reporter template
|
||||||
%anyUE - white rectangular type-in slot, unevaluated if replaced
|
%anyUE - white rectangular type-in slot, unevaluated if replaced
|
||||||
|
|
@ -2027,7 +2025,7 @@ function BlockMorph() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockMorph.prototype.init = function () {
|
BlockMorph.prototype.init = function (silently) {
|
||||||
this.selector = null; // name of method to be triggered
|
this.selector = null; // name of method to be triggered
|
||||||
this.blockSpec = ''; // formal description of label and arguments
|
this.blockSpec = ''; // formal description of label and arguments
|
||||||
this.comment = null; // optional "sticky" comment morph
|
this.comment = null; // optional "sticky" comment morph
|
||||||
|
|
@ -2036,7 +2034,7 @@ BlockMorph.prototype.init = function () {
|
||||||
this.instantiationSpec = null; // spec to set upon fullCopy() of template
|
this.instantiationSpec = null; // spec to set upon fullCopy() of template
|
||||||
this.category = null; // for zebra coloring (non persistent)
|
this.category = null; // for zebra coloring (non persistent)
|
||||||
|
|
||||||
BlockMorph.uber.init.call(this);
|
BlockMorph.uber.init.call(this, silently);
|
||||||
this.color = new Color(0, 17, 173);
|
this.color = new Color(0, 17, 173);
|
||||||
this.cashedInputs = null;
|
this.cashedInputs = null;
|
||||||
};
|
};
|
||||||
|
|
@ -2101,7 +2099,7 @@ BlockMorph.prototype.parseSpec = function (spec) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockMorph.prototype.setSpec = function (spec) {
|
BlockMorph.prototype.setSpec = function (spec, silently) {
|
||||||
var myself = this,
|
var myself = this,
|
||||||
part,
|
part,
|
||||||
inputIdx = -1;
|
inputIdx = -1;
|
||||||
|
|
@ -2144,10 +2142,17 @@ BlockMorph.prototype.setSpec = function (spec) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.blockSpec = spec;
|
this.blockSpec = spec;
|
||||||
this.fixLayout();
|
this.fixLayout(silently);
|
||||||
this.cachedInputs = null;
|
this.cachedInputs = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BlockMorph.prototype.userSetSpec = function (spec) {
|
||||||
|
var tb = this.topBlock();
|
||||||
|
tb.fullChanged();
|
||||||
|
this.setSpec(spec);
|
||||||
|
tb.fullChanged();
|
||||||
|
};
|
||||||
|
|
||||||
BlockMorph.prototype.buildSpec = function () {
|
BlockMorph.prototype.buildSpec = function () {
|
||||||
// create my blockSpec from my parts - for demo purposes only
|
// create my blockSpec from my parts - for demo purposes only
|
||||||
var myself = this;
|
var myself = this;
|
||||||
|
|
@ -2448,6 +2453,7 @@ BlockMorph.prototype.ringify = function () {
|
||||||
center = top.fullBounds().center();
|
center = top.fullBounds().center();
|
||||||
|
|
||||||
if (this.parent === null) {return null; }
|
if (this.parent === null) {return null; }
|
||||||
|
top.fullChanged();
|
||||||
if (this.parent instanceof SyntaxElementMorph) {
|
if (this.parent instanceof SyntaxElementMorph) {
|
||||||
if (this instanceof ReporterBlockMorph) {
|
if (this instanceof ReporterBlockMorph) {
|
||||||
this.parent.silentReplaceInput(this, ring);
|
this.parent.silentReplaceInput(this, ring);
|
||||||
|
|
@ -2463,11 +2469,14 @@ BlockMorph.prototype.ringify = function () {
|
||||||
ring.setCenter(center);
|
ring.setCenter(center);
|
||||||
}
|
}
|
||||||
this.fixBlockColor(null, true);
|
this.fixBlockColor(null, true);
|
||||||
|
top.fullChanged();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockMorph.prototype.unringify = function () {
|
BlockMorph.prototype.unringify = function () {
|
||||||
// remove a Ring around me, if any
|
// remove a Ring around me, if any
|
||||||
var ring = this.parentThatIsA(RingMorph),
|
var ring = this.parentThatIsA(RingMorph),
|
||||||
|
top = this.topBlock(),
|
||||||
scripts = this.parentThatIsA(ScriptsMorph),
|
scripts = this.parentThatIsA(ScriptsMorph),
|
||||||
block,
|
block,
|
||||||
center;
|
center;
|
||||||
|
|
@ -2476,6 +2485,7 @@ BlockMorph.prototype.unringify = function () {
|
||||||
block = ring.contents();
|
block = ring.contents();
|
||||||
center = ring.center();
|
center = ring.center();
|
||||||
|
|
||||||
|
top.fullChanged();
|
||||||
if (ring.parent instanceof SyntaxElementMorph) {
|
if (ring.parent instanceof SyntaxElementMorph) {
|
||||||
if (block instanceof ReporterBlockMorph) {
|
if (block instanceof ReporterBlockMorph) {
|
||||||
ring.parent.silentReplaceInput(ring, block);
|
ring.parent.silentReplaceInput(ring, block);
|
||||||
|
|
@ -2491,6 +2501,7 @@ BlockMorph.prototype.unringify = function () {
|
||||||
ring.destroy();
|
ring.destroy();
|
||||||
}
|
}
|
||||||
this.fixBlockColor(null, true);
|
this.fixBlockColor(null, true);
|
||||||
|
top.fullChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockMorph.prototype.relabel = function (alternativeSelectors) {
|
BlockMorph.prototype.relabel = function (alternativeSelectors) {
|
||||||
|
|
@ -2887,12 +2898,13 @@ BlockMorph.prototype.eraseHoles = function (context) {
|
||||||
var w = hole.width(),
|
var w = hole.width(),
|
||||||
h = Math.floor(hole.height()) - 2; // Opera needs this
|
h = Math.floor(hole.height()) - 2; // Opera needs this
|
||||||
context.clearRect(
|
context.clearRect(
|
||||||
Math.floor(hole.bounds.origin.x - myself.bounds.origin.x) + 1,
|
hole.bounds.origin.x - myself.bounds.origin.x + 1,
|
||||||
Math.floor(hole.bounds.origin.y - myself.bounds.origin.y) + 1,
|
hole.bounds.origin.y - myself.bounds.origin.y + 1,
|
||||||
isReporter ? w - 1 : w + 1,
|
isReporter ? w - 2 : w + 1,
|
||||||
h
|
h
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// BlockMorph highlighting
|
// BlockMorph highlighting
|
||||||
|
|
@ -3081,7 +3093,7 @@ BlockMorph.prototype.fixBlockColor = function (nearestBlock, isForced) {
|
||||||
|
|
||||||
BlockMorph.prototype.forceNormalColoring = function () {
|
BlockMorph.prototype.forceNormalColoring = function () {
|
||||||
var clr = SpriteMorph.prototype.blockColor[this.category];
|
var clr = SpriteMorph.prototype.blockColor[this.category];
|
||||||
this.setColor(clr);
|
this.setColor(clr, true); // silently
|
||||||
this.setLabelColor(
|
this.setLabelColor(
|
||||||
new Color(255, 255, 255),
|
new Color(255, 255, 255),
|
||||||
clr.darker(this.labelContrast),
|
clr.darker(this.labelContrast),
|
||||||
|
|
@ -3096,10 +3108,11 @@ BlockMorph.prototype.alternateBlockColor = function () {
|
||||||
if (this.color.eq(clr)) {
|
if (this.color.eq(clr)) {
|
||||||
this.setColor(
|
this.setColor(
|
||||||
this.zebraContrast < 0 ? clr.darker(Math.abs(this.zebraContrast))
|
this.zebraContrast < 0 ? clr.darker(Math.abs(this.zebraContrast))
|
||||||
: clr.lighter(this.zebraContrast)
|
: clr.lighter(this.zebraContrast),
|
||||||
|
true // silently
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.setColor(clr);
|
this.setColor(clr, true); // silently
|
||||||
}
|
}
|
||||||
this.fixLabelColor();
|
this.fixLabelColor();
|
||||||
this.fixChildrensBlockColor(true); // has issues if not forced
|
this.fixChildrensBlockColor(true); // has issues if not forced
|
||||||
|
|
@ -3356,6 +3369,7 @@ BlockMorph.prototype.prepareToBeGrabbed = function (hand) {
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockMorph.prototype.justDropped = function () {
|
BlockMorph.prototype.justDropped = function () {
|
||||||
|
this.alpha = 1;
|
||||||
this.allComments().forEach(function (comment) {
|
this.allComments().forEach(function (comment) {
|
||||||
comment.stopFollowing();
|
comment.stopFollowing();
|
||||||
});
|
});
|
||||||
|
|
@ -3444,9 +3458,9 @@ function CommandBlockMorph() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBlockMorph.prototype.init = function () {
|
CommandBlockMorph.prototype.init = function (silently) {
|
||||||
CommandBlockMorph.uber.init.call(this);
|
CommandBlockMorph.uber.init.call(this, silently);
|
||||||
this.setExtent(new Point(200, 100));
|
this.setExtent(new Point(200, 100), silently);
|
||||||
this.partOfCustomCommand = false;
|
this.partOfCustomCommand = false;
|
||||||
this.exitTag = null;
|
this.exitTag = null;
|
||||||
};
|
};
|
||||||
|
|
@ -3479,7 +3493,12 @@ CommandBlockMorph.prototype.nextBlock = function (block) {
|
||||||
if (nb) {
|
if (nb) {
|
||||||
block.bottomBlock().nextBlock(nb);
|
block.bottomBlock().nextBlock(nb);
|
||||||
}
|
}
|
||||||
this.fixLayout();
|
block.setPosition(
|
||||||
|
new Point(
|
||||||
|
this.left(),
|
||||||
|
this.bottom() - (this.corner)
|
||||||
|
)
|
||||||
|
);
|
||||||
if (affected) {
|
if (affected) {
|
||||||
affected.fixLayout();
|
affected.fixLayout();
|
||||||
}
|
}
|
||||||
|
|
@ -4125,7 +4144,7 @@ function HatBlockMorph() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HatBlockMorph.prototype.init = function () {
|
HatBlockMorph.prototype.init = function () {
|
||||||
HatBlockMorph.uber.init.call(this);
|
HatBlockMorph.uber.init.call(this, true); // silently
|
||||||
this.setExtent(new Point(300, 150));
|
this.setExtent(new Point(300, 150));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -4302,10 +4321,10 @@ function ReporterBlockMorph(isPredicate) {
|
||||||
this.init(isPredicate);
|
this.init(isPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReporterBlockMorph.prototype.init = function (isPredicate) {
|
ReporterBlockMorph.prototype.init = function (isPredicate, silently) {
|
||||||
ReporterBlockMorph.uber.init.call(this);
|
ReporterBlockMorph.uber.init.call(this, silently);
|
||||||
this.isPredicate = isPredicate || false;
|
this.isPredicate = isPredicate || false;
|
||||||
this.setExtent(new Point(200, 80));
|
this.setExtent(new Point(200, 80), silently);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ReporterBlockMorph drag & drop:
|
// ReporterBlockMorph drag & drop:
|
||||||
|
|
@ -4313,6 +4332,7 @@ ReporterBlockMorph.prototype.init = function (isPredicate) {
|
||||||
ReporterBlockMorph.prototype.snap = function (hand) {
|
ReporterBlockMorph.prototype.snap = function (hand) {
|
||||||
// passing the hand is optional (for when blocks are dragged & dropped)
|
// passing the hand is optional (for when blocks are dragged & dropped)
|
||||||
var scripts = this.parent,
|
var scripts = this.parent,
|
||||||
|
nb,
|
||||||
target;
|
target;
|
||||||
|
|
||||||
if (!scripts instanceof ScriptsMorph) {
|
if (!scripts instanceof ScriptsMorph) {
|
||||||
|
|
@ -4329,6 +4349,16 @@ ReporterBlockMorph.prototype.snap = function (hand) {
|
||||||
if (target instanceof MultiArgMorph) {
|
if (target instanceof MultiArgMorph) {
|
||||||
scripts.lastPreservedBlocks = target.inputs();
|
scripts.lastPreservedBlocks = target.inputs();
|
||||||
scripts.lastReplacedInput = target.fullCopy();
|
scripts.lastReplacedInput = target.fullCopy();
|
||||||
|
} else if (target instanceof CommandSlotMorph) {
|
||||||
|
scripts.lastReplacedInput = target;
|
||||||
|
nb = target.nestedBlock();
|
||||||
|
if (nb) {
|
||||||
|
nb = nb.fullCopy();
|
||||||
|
scripts.add(nb);
|
||||||
|
nb.moveBy(nb.extent());
|
||||||
|
nb.fixBlockColor();
|
||||||
|
scripts.lastPreservedBlocks = [nb];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
target.parent.replaceInput(target, this);
|
target.parent.replaceInput(target, this);
|
||||||
if (this.snapSound) {
|
if (this.snapSound) {
|
||||||
|
|
@ -4352,6 +4382,7 @@ ReporterBlockMorph.prototype.prepareToBeGrabbed = function (handMorph) {
|
||||||
this.setPosition(oldPos);
|
this.setPosition(oldPos);
|
||||||
}
|
}
|
||||||
ReporterBlockMorph.uber.prepareToBeGrabbed.call(this, handMorph);
|
ReporterBlockMorph.uber.prepareToBeGrabbed.call(this, handMorph);
|
||||||
|
this.alpha = 0.85;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ReporterBlockMorph enumerating
|
// ReporterBlockMorph enumerating
|
||||||
|
|
@ -4413,7 +4444,7 @@ ReporterBlockMorph.prototype.mouseClickLeft = function (pos) {
|
||||||
this.parent.parent.parent instanceof RingMorph;
|
this.parent.parent.parent instanceof RingMorph;
|
||||||
new DialogBoxMorph(
|
new DialogBoxMorph(
|
||||||
this,
|
this,
|
||||||
this.setSpec,
|
this.userSetSpec,
|
||||||
this
|
this
|
||||||
).prompt(
|
).prompt(
|
||||||
isRing ? "Input name" : "Script variable name",
|
isRing ? "Input name" : "Script variable name",
|
||||||
|
|
@ -4987,6 +5018,7 @@ ScriptsMorph.prototype.init = function (owner) {
|
||||||
|
|
||||||
ScriptsMorph.uber.init.call(this);
|
ScriptsMorph.uber.init.call(this);
|
||||||
this.setColor(new Color(70, 70, 70));
|
this.setColor(new Color(70, 70, 70));
|
||||||
|
this.noticesTransparentClick = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ScriptsMorph deep copying:
|
// ScriptsMorph deep copying:
|
||||||
|
|
@ -5180,14 +5212,15 @@ ScriptsMorph.prototype.closestInput = function (reporter, hand) {
|
||||||
all,
|
all,
|
||||||
function (input) {
|
function (input) {
|
||||||
return (input instanceof InputSlotMorph
|
return (input instanceof InputSlotMorph
|
||||||
|| input instanceof ArgMorph
|
|| (input instanceof ArgMorph
|
||||||
|
&& !(input instanceof CommandSlotMorph)
|
||||||
|
&& !(input instanceof MultiArgMorph))
|
||||||
|| (input instanceof RingMorph
|
|| (input instanceof RingMorph
|
||||||
&& !input.contents())
|
&& !input.contents())
|
||||||
|| input.isEmptySlot())
|
|| input.isEmptySlot())
|
||||||
&& !input.isLocked()
|
&& !input.isLocked()
|
||||||
&& input.bounds.containsPoint(handPos)
|
&& input.bounds.containsPoint(handPos)
|
||||||
&& !contains(blackList, input)
|
&& !contains(blackList, input);
|
||||||
&& touchingVariadicArrowsIfAny(input, handPos);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
if (target) {
|
if (target) {
|
||||||
|
|
@ -5550,12 +5583,12 @@ function ArgMorph(type) {
|
||||||
this.init(type);
|
this.init(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgMorph.prototype.init = function (type) {
|
ArgMorph.prototype.init = function (type, silently) {
|
||||||
this.type = type || null;
|
this.type = type || null;
|
||||||
this.isHole = false;
|
this.isHole = false;
|
||||||
ArgMorph.uber.init.call(this);
|
ArgMorph.uber.init.call(this, silently);
|
||||||
this.color = new Color(0, 17, 173);
|
this.color = new Color(0, 17, 173);
|
||||||
this.setExtent(new Point(50, 50));
|
this.setExtent(new Point(50, 50), silently);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ArgMorph drag & drop: for demo puposes only
|
// ArgMorph drag & drop: for demo puposes only
|
||||||
|
|
@ -5663,10 +5696,13 @@ function CommandSlotMorph() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandSlotMorph.prototype.init = function () {
|
CommandSlotMorph.prototype.init = function (silently) {
|
||||||
CommandSlotMorph.uber.init.call(this);
|
CommandSlotMorph.uber.init.call(this, null, true); // silently
|
||||||
this.color = new Color(0, 17, 173);
|
this.color = new Color(0, 17, 173);
|
||||||
this.setExtent(new Point(230, this.corner * 4 + this.cSlotPadding));
|
this.setExtent(
|
||||||
|
new Point(230, this.corner * 4 + this.cSlotPadding),
|
||||||
|
silently
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
CommandSlotMorph.prototype.getSpec = function () {
|
CommandSlotMorph.prototype.getSpec = function () {
|
||||||
|
|
@ -6118,8 +6154,8 @@ function RingCommandSlotMorph() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
RingCommandSlotMorph.prototype.init = function () {
|
RingCommandSlotMorph.prototype.init = function (silently) {
|
||||||
RingCommandSlotMorph.uber.init.call(this);
|
RingCommandSlotMorph.uber.init.call(this, silently);
|
||||||
this.isHole = true;
|
this.isHole = true;
|
||||||
this.noticesTransparentClick = true;
|
this.noticesTransparentClick = true;
|
||||||
this.color = new Color(0, 17, 173);
|
this.color = new Color(0, 17, 173);
|
||||||
|
|
@ -6269,11 +6305,15 @@ function CSlotMorph() {
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSlotMorph.prototype.init = function () {
|
CSlotMorph.prototype.init = function (silently) {
|
||||||
CommandSlotMorph.uber.init.call(this);
|
CommandSlotMorph.uber.init.call(this, null, true); // silently
|
||||||
this.isHole = true;
|
this.isHole = true;
|
||||||
|
this.isLambda = false; // see Process.prototype.evaluateInput
|
||||||
this.color = new Color(0, 17, 173);
|
this.color = new Color(0, 17, 173);
|
||||||
this.setExtent(new Point(230, this.corner * 4 + this.cSlotPadding));
|
this.setExtent(
|
||||||
|
new Point(230, this.corner * 4 + this.cSlotPadding),
|
||||||
|
silently
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
CSlotMorph.prototype.getSpec = function () {
|
CSlotMorph.prototype.getSpec = function () {
|
||||||
|
|
@ -6721,7 +6761,7 @@ InputSlotMorph.prototype.init = function (
|
||||||
this.minWidth = 0; // can be chaged for text-type inputs ("landscape")
|
this.minWidth = 0; // can be chaged for text-type inputs ("landscape")
|
||||||
this.constant = null;
|
this.constant = null;
|
||||||
|
|
||||||
InputSlotMorph.uber.init.call(this);
|
InputSlotMorph.uber.init.call(this, null, true);
|
||||||
this.color = new Color(255, 255, 255);
|
this.color = new Color(255, 255, 255);
|
||||||
this.add(contents);
|
this.add(contents);
|
||||||
this.add(arrow);
|
this.add(arrow);
|
||||||
|
|
@ -7874,7 +7914,7 @@ ArrowMorph.prototype.init = function (direction, size, padding, color) {
|
||||||
this.size = size || ((size === 0) ? 0 : 50);
|
this.size = size || ((size === 0) ? 0 : 50);
|
||||||
this.padding = padding || 0;
|
this.padding = padding || 0;
|
||||||
|
|
||||||
ArrowMorph.uber.init.call(this);
|
ArrowMorph.uber.init.call(this, true); // silently
|
||||||
this.color = color || new Color(0, 0, 0);
|
this.color = color || new Color(0, 0, 0);
|
||||||
this.setExtent(new Point(this.size, this.size));
|
this.setExtent(new Point(this.size, this.size));
|
||||||
};
|
};
|
||||||
|
|
@ -7963,7 +8003,7 @@ TextSlotMorph.prototype.init = function (
|
||||||
this.minWidth = 0; // can be chaged for text-type inputs ("landscape")
|
this.minWidth = 0; // can be chaged for text-type inputs ("landscape")
|
||||||
this.constant = null;
|
this.constant = null;
|
||||||
|
|
||||||
InputSlotMorph.uber.init.call(this);
|
InputSlotMorph.uber.init.call(this, null, null, null, null, true); // sil.
|
||||||
this.color = new Color(255, 255, 255);
|
this.color = new Color(255, 255, 255);
|
||||||
this.add(contents);
|
this.add(contents);
|
||||||
this.add(arrow);
|
this.add(arrow);
|
||||||
|
|
@ -8084,7 +8124,7 @@ SymbolMorph.prototype.init = function (
|
||||||
this.shadowOffset = shadowOffset || new Point(0, 0);
|
this.shadowOffset = shadowOffset || new Point(0, 0);
|
||||||
this.shadowColor = shadowColor || null;
|
this.shadowColor = shadowColor || null;
|
||||||
|
|
||||||
SymbolMorph.uber.init.call(this);
|
SymbolMorph.uber.init.call(this, true); // silently
|
||||||
this.color = color || new Color(0, 0, 0);
|
this.color = color || new Color(0, 0, 0);
|
||||||
this.drawNew();
|
this.drawNew();
|
||||||
};
|
};
|
||||||
|
|
@ -9316,7 +9356,7 @@ function ColorSlotMorph(clr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorSlotMorph.prototype.init = function (clr) {
|
ColorSlotMorph.prototype.init = function (clr) {
|
||||||
ColorSlotMorph.uber.init.call(this);
|
ColorSlotMorph.uber.init.call(this, null, true); // silently
|
||||||
this.setColor(clr || new Color(145, 26, 68));
|
this.setColor(clr || new Color(145, 26, 68));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -9494,7 +9534,7 @@ MultiArgMorph.prototype.init = function (
|
||||||
this.shadowOffset = shadowOffset || null;
|
this.shadowOffset = shadowOffset || null;
|
||||||
|
|
||||||
this.canBeEmpty = true;
|
this.canBeEmpty = true;
|
||||||
MultiArgMorph.uber.init.call(this);
|
MultiArgMorph.uber.init.call(this, null, true); // silently
|
||||||
|
|
||||||
// MultiArgMorphs are transparent by default b/c of zebra coloring
|
// MultiArgMorphs are transparent by default b/c of zebra coloring
|
||||||
this.alpha = isTransparent === false ? 1 : 0;
|
this.alpha = isTransparent === false ? 1 : 0;
|
||||||
|
|
@ -9882,7 +9922,7 @@ ArgLabelMorph.prototype.init = function (argMorph, labelTxt) {
|
||||||
var label;
|
var label;
|
||||||
|
|
||||||
this.labelText = localize(labelTxt || 'input list:');
|
this.labelText = localize(labelTxt || 'input list:');
|
||||||
ArgLabelMorph.uber.init.call(this);
|
ArgLabelMorph.uber.init.call(this, null, true); // silently
|
||||||
|
|
||||||
this.isStatic = true; // I cannot be exchanged
|
this.isStatic = true; // I cannot be exchanged
|
||||||
|
|
||||||
|
|
@ -10008,14 +10048,17 @@ function FunctionSlotMorph(isPredicate) {
|
||||||
this.init(isPredicate);
|
this.init(isPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionSlotMorph.prototype.init = function (isPredicate) {
|
FunctionSlotMorph.prototype.init = function (isPredicate, silently) {
|
||||||
FunctionSlotMorph.uber.init.call(this);
|
FunctionSlotMorph.uber.init.call(this, null, true); // silently
|
||||||
this.isPredicate = isPredicate || false;
|
this.isPredicate = isPredicate || false;
|
||||||
this.color = this.rfColor;
|
this.color = this.rfColor;
|
||||||
this.setExtent(new Point(
|
this.setExtent(
|
||||||
(this.fontSize + this.edge * 2) * 2,
|
new Point(
|
||||||
this.fontSize + this.edge * 2
|
(this.fontSize + this.edge * 2) * 2,
|
||||||
));
|
this.fontSize + this.edge * 2
|
||||||
|
),
|
||||||
|
silently
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
FunctionSlotMorph.prototype.getSpec = function () {
|
FunctionSlotMorph.prototype.getSpec = function () {
|
||||||
|
|
@ -10390,7 +10433,7 @@ function ReporterSlotMorph(isPredicate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReporterSlotMorph.prototype.init = function (isPredicate) {
|
ReporterSlotMorph.prototype.init = function (isPredicate) {
|
||||||
ReporterSlotMorph.uber.init.call(this, isPredicate);
|
ReporterSlotMorph.uber.init.call(this, isPredicate, true);
|
||||||
this.add(this.emptySlot());
|
this.add(this.emptySlot());
|
||||||
this.fixLayout();
|
this.fixLayout();
|
||||||
};
|
};
|
||||||
|
|
@ -10481,7 +10524,7 @@ function RingReporterSlotMorph(isPredicate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RingReporterSlotMorph.prototype.init = function (isPredicate) {
|
RingReporterSlotMorph.prototype.init = function (isPredicate) {
|
||||||
RingReporterSlotMorph.uber.init.call(this, isPredicate);
|
RingReporterSlotMorph.uber.init.call(this, isPredicate, true);
|
||||||
this.alpha = RingMorph.prototype.alpha;
|
this.alpha = RingMorph.prototype.alpha;
|
||||||
this.contrast = RingMorph.prototype.contrast;
|
this.contrast = RingMorph.prototype.contrast;
|
||||||
this.isHole = true;
|
this.isHole = true;
|
||||||
|
|
|
||||||
58
byob.js
58
byob.js
|
|
@ -108,7 +108,7 @@ SymbolMorph, isNil, CursorMorph*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.byob = '2015-October-07';
|
modules.byob = '2015-November-16';
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
|
|
@ -148,6 +148,7 @@ function CustomBlockDefinition(spec, receiver) {
|
||||||
|
|
||||||
// don't serialize (not needed for functionality):
|
// don't serialize (not needed for functionality):
|
||||||
this.receiver = receiver || null; // for serialization only (pointer)
|
this.receiver = receiver || null; // for serialization only (pointer)
|
||||||
|
this.editorDimensions = null; // a rectangle, last bounds of the editor
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomBlockDefinition instantiating blocks
|
// CustomBlockDefinition instantiating blocks
|
||||||
|
|
@ -405,9 +406,7 @@ function CustomCommandBlockMorph(definition, isProto) {
|
||||||
CustomCommandBlockMorph.prototype.init = function (definition, isProto) {
|
CustomCommandBlockMorph.prototype.init = function (definition, isProto) {
|
||||||
this.definition = definition; // mandatory
|
this.definition = definition; // mandatory
|
||||||
this.isPrototype = isProto || false; // optional
|
this.isPrototype = isProto || false; // optional
|
||||||
|
CustomCommandBlockMorph.uber.init.call(this, true); // silently
|
||||||
CustomCommandBlockMorph.uber.init.call(this);
|
|
||||||
|
|
||||||
this.category = definition.category;
|
this.category = definition.category;
|
||||||
this.selector = 'evaluateCustomBlock';
|
this.selector = 'evaluateCustomBlock';
|
||||||
if (definition) { // needed for de-serializing
|
if (definition) { // needed for de-serializing
|
||||||
|
|
@ -415,7 +414,7 @@ CustomCommandBlockMorph.prototype.init = function (definition, isProto) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CustomCommandBlockMorph.prototype.refresh = function () {
|
CustomCommandBlockMorph.prototype.refresh = function (silently) {
|
||||||
var def = this.definition,
|
var def = this.definition,
|
||||||
newSpec = this.isPrototype ?
|
newSpec = this.isPrototype ?
|
||||||
def.spec : def.blockSpec(),
|
def.spec : def.blockSpec(),
|
||||||
|
|
@ -429,7 +428,7 @@ CustomCommandBlockMorph.prototype.refresh = function () {
|
||||||
} else {
|
} else {
|
||||||
this.fixBlockColor();
|
this.fixBlockColor();
|
||||||
}
|
}
|
||||||
this.setSpec(newSpec);
|
this.setSpec(newSpec, silently);
|
||||||
this.fixLabelColor();
|
this.fixLabelColor();
|
||||||
this.restoreInputs(oldInputs);
|
this.restoreInputs(oldInputs);
|
||||||
} else { // update all input slots' drop-downs
|
} else { // update all input slots' drop-downs
|
||||||
|
|
@ -671,7 +670,7 @@ CustomCommandBlockMorph.prototype.mouseClickLeft = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
CustomCommandBlockMorph.prototype.edit = function () {
|
CustomCommandBlockMorph.prototype.edit = function () {
|
||||||
var myself = this, block, hat;
|
var myself = this, editor, block, hat;
|
||||||
|
|
||||||
if (this.isPrototype) {
|
if (this.isPrototype) {
|
||||||
block = this.definition.blockInstance();
|
block = this.definition.blockInstance();
|
||||||
|
|
@ -696,7 +695,11 @@ CustomCommandBlockMorph.prototype.edit = function () {
|
||||||
myself.isInUse()
|
myself.isInUse()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
new BlockEditorMorph(this.definition, this.receiver()).popUp();
|
Morph.prototype.trackChanges = false;
|
||||||
|
editor = new BlockEditorMorph(this.definition, this.receiver());
|
||||||
|
editor.popUp();
|
||||||
|
Morph.prototype.trackChanges = true;
|
||||||
|
editor.changed();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -763,7 +766,7 @@ CustomCommandBlockMorph.prototype.userMenu = function () {
|
||||||
menu.addItem(
|
menu.addItem(
|
||||||
"script pic...",
|
"script pic...",
|
||||||
function () {
|
function () {
|
||||||
window.open(this.topBlock().fullImage().toDataURL());
|
window.open(this.topBlock().scriptPic().toDataURL());
|
||||||
},
|
},
|
||||||
'open a new window\nwith a picture of this script'
|
'open a new window\nwith a picture of this script'
|
||||||
);
|
);
|
||||||
|
|
@ -936,7 +939,7 @@ CustomReporterBlockMorph.prototype.init = function (
|
||||||
this.definition = definition; // mandatory
|
this.definition = definition; // mandatory
|
||||||
this.isPrototype = isProto || false; // optional
|
this.isPrototype = isProto || false; // optional
|
||||||
|
|
||||||
CustomReporterBlockMorph.uber.init.call(this, isPredicate);
|
CustomReporterBlockMorph.uber.init.call(this, isPredicate, true); // sil.
|
||||||
|
|
||||||
this.category = definition.category;
|
this.category = definition.category;
|
||||||
this.selector = 'evaluateCustomBlock';
|
this.selector = 'evaluateCustomBlock';
|
||||||
|
|
@ -946,7 +949,7 @@ CustomReporterBlockMorph.prototype.init = function (
|
||||||
};
|
};
|
||||||
|
|
||||||
CustomReporterBlockMorph.prototype.refresh = function () {
|
CustomReporterBlockMorph.prototype.refresh = function () {
|
||||||
CustomCommandBlockMorph.prototype.refresh.call(this);
|
CustomCommandBlockMorph.prototype.refresh.call(this, true);
|
||||||
if (!this.isPrototype) {
|
if (!this.isPrototype) {
|
||||||
this.isPredicate = (this.definition.type === 'predicate');
|
this.isPredicate = (this.definition.type === 'predicate');
|
||||||
}
|
}
|
||||||
|
|
@ -1726,7 +1729,7 @@ BlockEditorMorph.prototype.init = function (definition, target) {
|
||||||
this.addButton('updateDefinition', 'Apply');
|
this.addButton('updateDefinition', 'Apply');
|
||||||
this.addButton('cancel', 'Cancel');
|
this.addButton('cancel', 'Cancel');
|
||||||
|
|
||||||
this.setExtent(new Point(375, 300));
|
this.setExtent(new Point(375, 300)); // normal initial extent
|
||||||
this.fixLayout();
|
this.fixLayout();
|
||||||
proto.children[0].fixLayout();
|
proto.children[0].fixLayout();
|
||||||
scripts.fixMultiArgs();
|
scripts.fixMultiArgs();
|
||||||
|
|
@ -1737,6 +1740,7 @@ BlockEditorMorph.prototype.popUp = function () {
|
||||||
|
|
||||||
if (world) {
|
if (world) {
|
||||||
BlockEditorMorph.uber.popUp.call(this, world);
|
BlockEditorMorph.uber.popUp.call(this, world);
|
||||||
|
this.setInitialDimensions();
|
||||||
this.handle = new HandleMorph(
|
this.handle = new HandleMorph(
|
||||||
this,
|
this,
|
||||||
280,
|
280,
|
||||||
|
|
@ -1744,9 +1748,18 @@ BlockEditorMorph.prototype.popUp = function () {
|
||||||
this.corner,
|
this.corner,
|
||||||
this.corner
|
this.corner
|
||||||
);
|
);
|
||||||
|
world.keyboardReceiver = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BlockEditorMorph.prototype.justDropped = function () {
|
||||||
|
// override the inherited default behavior, which is to
|
||||||
|
// give keyboard focus to dialog boxes, as in this case
|
||||||
|
// we want Snap-global keyboard-shortcuts like ctrl-f
|
||||||
|
// to still work
|
||||||
|
nop();
|
||||||
|
};
|
||||||
|
|
||||||
// BlockEditorMorph ops
|
// BlockEditorMorph ops
|
||||||
|
|
||||||
BlockEditorMorph.prototype.accept = function (origin) {
|
BlockEditorMorph.prototype.accept = function (origin) {
|
||||||
|
|
@ -1851,6 +1864,7 @@ BlockEditorMorph.prototype.updateDefinition = function () {
|
||||||
this.definition.spec = this.prototypeSpec();
|
this.definition.spec = this.prototypeSpec();
|
||||||
this.definition.declarations = this.prototypeSlots();
|
this.definition.declarations = this.prototypeSlots();
|
||||||
this.definition.scripts = [];
|
this.definition.scripts = [];
|
||||||
|
this.definition.editorDimensions = this.bounds.copy();
|
||||||
|
|
||||||
this.body.contents.children.forEach(function (morph) {
|
this.body.contents.children.forEach(function (morph) {
|
||||||
if (morph instanceof PrototypeHatBlockMorph) {
|
if (morph instanceof PrototypeHatBlockMorph) {
|
||||||
|
|
@ -1927,6 +1941,26 @@ BlockEditorMorph.prototype.prototypeSlots = function () {
|
||||||
|
|
||||||
// BlockEditorMorph layout
|
// BlockEditorMorph layout
|
||||||
|
|
||||||
|
BlockEditorMorph.prototype.setInitialDimensions = function () {
|
||||||
|
var world = this.world(),
|
||||||
|
mex = world.extent().subtract(new Point(this.padding, this.padding)),
|
||||||
|
th = fontHeight(this.titleFontSize) + this.titlePadding * 2,
|
||||||
|
bh = this.buttons.height();
|
||||||
|
|
||||||
|
if (this.definition.editorDimensions) {
|
||||||
|
this.setPosition(this.definition.editorDimensions.origin);
|
||||||
|
this.setExtent(this.definition.editorDimensions.extent().min(mex));
|
||||||
|
this.keepWithin(world);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setExtent(
|
||||||
|
this.body.contents.extent().add(
|
||||||
|
new Point(this.padding, this.padding + th + bh)
|
||||||
|
).min(mex)
|
||||||
|
);
|
||||||
|
this.setCenter(this.world().center());
|
||||||
|
};
|
||||||
|
|
||||||
BlockEditorMorph.prototype.fixLayout = function () {
|
BlockEditorMorph.prototype.fixLayout = function () {
|
||||||
var th = fontHeight(this.titleFontSize) + this.titlePadding * 2;
|
var th = fontHeight(this.titleFontSize) + this.titlePadding * 2;
|
||||||
|
|
||||||
|
|
|
||||||
41
gui.js
41
gui.js
|
|
@ -71,7 +71,7 @@ BlockRemovalDialogMorph*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.gui = '2015-October-07';
|
modules.gui = '2015-November-16';
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
|
|
@ -2227,6 +2227,15 @@ IDE_Morph.prototype.settingsMenu = function () {
|
||||||
'Stage size...',
|
'Stage size...',
|
||||||
'userSetStageSize'
|
'userSetStageSize'
|
||||||
);
|
);
|
||||||
|
if (shiftClicked) {
|
||||||
|
menu.addItem(
|
||||||
|
'Dragging threshold...',
|
||||||
|
'userSetDragThreshold',
|
||||||
|
'specify the distance the hand has to move\n' +
|
||||||
|
'before it picks up an object',
|
||||||
|
new Color(100, 0, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
menu.addLine();
|
menu.addLine();
|
||||||
addPreference(
|
addPreference(
|
||||||
'Blurred shadows',
|
'Blurred shadows',
|
||||||
|
|
@ -2713,7 +2722,7 @@ IDE_Morph.prototype.aboutSnap = function () {
|
||||||
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
|
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
|
||||||
world = this.world();
|
world = this.world();
|
||||||
|
|
||||||
aboutTxt = 'Snap! 4.0.2\nBuild Your Own Blocks\n\n'
|
aboutTxt = 'Snap! 4.0.3\nBuild Your Own Blocks\n\n'
|
||||||
+ 'Copyright \u24B8 2015 Jens M\u00F6nig and '
|
+ 'Copyright \u24B8 2015 Jens M\u00F6nig and '
|
||||||
+ 'Brian Harvey\n'
|
+ 'Brian Harvey\n'
|
||||||
+ 'jens@moenig.org, bh@cs.berkeley.edu\n\n'
|
+ 'jens@moenig.org, bh@cs.berkeley.edu\n\n'
|
||||||
|
|
@ -4201,6 +4210,29 @@ IDE_Morph.prototype.setStageExtent = function (aPoint) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// IDE_Morph dragging threshold (internal feature)
|
||||||
|
|
||||||
|
IDE_Morph.prototype.userSetDragThreshold = function () {
|
||||||
|
new DialogBoxMorph(
|
||||||
|
this,
|
||||||
|
function (num) {
|
||||||
|
MorphicPreferences.grabThreshold = Math.min(
|
||||||
|
Math.max(+num, 0),
|
||||||
|
200
|
||||||
|
);
|
||||||
|
},
|
||||||
|
this
|
||||||
|
).prompt(
|
||||||
|
"Dragging threshold",
|
||||||
|
MorphicPreferences.grabThreshold.toString(),
|
||||||
|
this.world(),
|
||||||
|
null, // pic
|
||||||
|
null, // choices
|
||||||
|
null, // read only
|
||||||
|
true // numeric
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// IDE_Morph cloud interface
|
// IDE_Morph cloud interface
|
||||||
|
|
||||||
IDE_Morph.prototype.initializeCloud = function () {
|
IDE_Morph.prototype.initializeCloud = function () {
|
||||||
|
|
@ -5945,6 +5977,7 @@ SpriteIconMorph.prototype.prepareToBeGrabbed = function () {
|
||||||
var ide = this.parentThatIsA(IDE_Morph),
|
var ide = this.parentThatIsA(IDE_Morph),
|
||||||
idx;
|
idx;
|
||||||
this.mouseClickLeft(); // select me
|
this.mouseClickLeft(); // select me
|
||||||
|
this.alpha = 0.85;
|
||||||
if (ide) {
|
if (ide) {
|
||||||
idx = ide.sprites.asArray().indexOf(this.object);
|
idx = ide.sprites.asArray().indexOf(this.object);
|
||||||
ide.sprites.remove(idx + 1);
|
ide.sprites.remove(idx + 1);
|
||||||
|
|
@ -5953,6 +5986,10 @@ SpriteIconMorph.prototype.prepareToBeGrabbed = function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SpriteIconMorph.prototype.justDropped = function () {
|
||||||
|
this.alpha = 1;
|
||||||
|
};
|
||||||
|
|
||||||
SpriteIconMorph.prototype.wantsDropOf = function (morph) {
|
SpriteIconMorph.prototype.wantsDropOf = function (morph) {
|
||||||
// allow scripts & media to be copied from one sprite to another
|
// allow scripts & media to be copied from one sprite to another
|
||||||
// by drag & drop
|
// by drag & drop
|
||||||
|
|
|
||||||
72
history.txt
72
history.txt
|
|
@ -2603,3 +2603,75 @@ ______
|
||||||
* Store: Fix deserialization support for projects using inheritance
|
* Store: Fix deserialization support for projects using inheritance
|
||||||
* German translation update
|
* German translation update
|
||||||
|
|
||||||
|
|
||||||
|
++++++++++++++++++++++++++
|
||||||
|
new stuff - bulk of 151116
|
||||||
|
++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
151030
|
||||||
|
------
|
||||||
|
* Blocks: Tweak precision of rendering of transparent “holes”
|
||||||
|
* updated Czech translation (remember to integrate from email!)
|
||||||
|
* Morphic: Streamlined nop-stepping
|
||||||
|
* Blocks: Let SyntaxElements step (again), for better input slot editing experience
|
||||||
|
|
||||||
|
151101
|
||||||
|
------
|
||||||
|
* BYOB: Script pic: Always export comments attached to custom block definitions
|
||||||
|
* Blocks: fixed #982 (made %interaction slot static)
|
||||||
|
* Morphic: removed an obsolete line (“dragOrigin”)
|
||||||
|
* BYOB: make block editor big enough to show the whole definition, if possible
|
||||||
|
* BYOB: remember user-set position and size of block editor when pressing “OK”, per session (not serialized in project)
|
||||||
|
* Blocks: speed up stacking of commands (also when done programmatically) by suppressing redraws
|
||||||
|
* Morphic, Blocks, BYOB: Suppress redundant redraws
|
||||||
|
|
||||||
|
151104
|
||||||
|
------
|
||||||
|
* Morphic: new grabTheshold preference to suppress accidental grabbing through micro-movements of the hand
|
||||||
|
* GUI: hidden (shift-click) option to adjust the grabThreshold for the current session
|
||||||
|
* Lists, Blocks: Expand list watchers inside result bubbles to show everything
|
||||||
|
* Objects: Expand list watchers inside speech/thought bubbles to show everything
|
||||||
|
* Morphic: fixed a bug that occasionally expanded the Hand’s bounds when dragging morphs
|
||||||
|
|
||||||
|
151107
|
||||||
|
------
|
||||||
|
* Threads: invoke a block synchronously
|
||||||
|
|
||||||
|
151009
|
||||||
|
------
|
||||||
|
* Morphic: cache fullImage and fullBounds when dragging
|
||||||
|
* Blocks: make reporters semi-transparent while dragging
|
||||||
|
* GUI: make SpriteIcons semi-transparent while dragging
|
||||||
|
* Blocks: make it harder to drop reporters onto filled custom C-slots and variadic slot arrows
|
||||||
|
* Blocks: make ScriptsMorphs notice transparent clicks (addresses #997)
|
||||||
|
* Blocks: fixed “undrop” for replacing C-slots with reporters
|
||||||
|
* BYOB: fixed ctrl-f for the BlockEditor in all situations
|
||||||
|
|
||||||
|
151111
|
||||||
|
------
|
||||||
|
* Objects: fixed a between slideBackTo() and possible running scripts in sprites, thanks, Paul, for reporting it!
|
||||||
|
|
||||||
|
151112
|
||||||
|
------
|
||||||
|
* Blocks, Objects, Threads: new internal slot type: %cl for auto-reifying C-slots that reject reporter drops. Changed (hidden) “for each” to reject reporters in C-slot
|
||||||
|
|
||||||
|
151113
|
||||||
|
------
|
||||||
|
* Frames, snap.html: initial version of a new general purpose prototypal single inheritance object system
|
||||||
|
* snap_slo.html: alternative animation-frame based outer scheduler, experimental
|
||||||
|
* Threads: added optional timeout to the new synchronous invoke(block) function
|
||||||
|
* Blocks: fixed too brutally optimized redraw for “ringify” and “unringify”
|
||||||
|
|
||||||
|
151114
|
||||||
|
------
|
||||||
|
* Frames, snap.html, snap_slo.html: remove initial version for now, needs more low-levelish rewrite (Map-based “shortcut” design doesn’t cut it).
|
||||||
|
|
||||||
|
151116
|
||||||
|
------
|
||||||
|
* Blocks, GUI: Slightly less transparency for dragged reporters and sprite icons
|
||||||
|
|
||||||
|
=== v4.0.3 (unreleased) ===
|
||||||
|
|
||||||
|
++++++++++++++++++++++++++
|
||||||
|
end - bulk of 151116
|
||||||
|
++++++++++++++++++++++++++
|
||||||
|
|
|
||||||
13
lists.js
13
lists.js
|
|
@ -61,7 +61,7 @@ PushButtonMorph, SyntaxElementMorph, Color, Point, WatcherMorph,
|
||||||
StringMorph, SpriteMorph, ScrollFrameMorph, CellMorph, ArrowMorph,
|
StringMorph, SpriteMorph, ScrollFrameMorph, CellMorph, ArrowMorph,
|
||||||
MenuMorph, snapEquals, Morph, isNil, localize, MorphicPreferences*/
|
MenuMorph, snapEquals, Morph, isNil, localize, MorphicPreferences*/
|
||||||
|
|
||||||
modules.lists = '2015-October-07';
|
modules.lists = '2015-November-16';
|
||||||
|
|
||||||
var List;
|
var List;
|
||||||
var ListWatcherMorph;
|
var ListWatcherMorph;
|
||||||
|
|
@ -682,13 +682,14 @@ ListWatcherMorph.prototype.arrangeCells = function () {
|
||||||
this.frame.contents.adjustBounds();
|
this.frame.contents.adjustBounds();
|
||||||
};
|
};
|
||||||
|
|
||||||
ListWatcherMorph.prototype.expand = function () {
|
ListWatcherMorph.prototype.expand = function (maxExtent) {
|
||||||
// make sure to show all (first 100) cells
|
// make sure to show all (first 100) cells
|
||||||
// used for exporting a project summary
|
|
||||||
var fe = this.frame.contents.extent(),
|
var fe = this.frame.contents.extent(),
|
||||||
w = fe.x + 6,
|
ext = new Point(fe.x + 6, fe.y + this.label.height() + 6);
|
||||||
h = fe.y + this.label.height() + 6;
|
if (maxExtent) {
|
||||||
this.setExtent(new Point(w, h));
|
ext = ext.min(maxExtent);
|
||||||
|
}
|
||||||
|
this.setExtent(ext);
|
||||||
this.handle.setRight(this.right() - 3);
|
this.handle.setRight(this.right() - 3);
|
||||||
this.handle.setBottom(this.bottom() - 3);
|
this.handle.setBottom(this.bottom() - 3);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
114
morphic.js
114
morphic.js
|
|
@ -1052,7 +1052,7 @@
|
||||||
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
|
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
|
||||||
FileList, getBlurredShadowSupport*/
|
FileList, getBlurredShadowSupport*/
|
||||||
|
|
||||||
var morphicVersion = '2015-September-23';
|
var morphicVersion = '2015-November-16';
|
||||||
var modules = {}; // keep track of additional loaded modules
|
var modules = {}; // keep track of additional loaded modules
|
||||||
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
||||||
|
|
||||||
|
|
@ -1072,7 +1072,8 @@ var standardSettings = {
|
||||||
useVirtualKeyboard: true,
|
useVirtualKeyboard: true,
|
||||||
isTouchDevice: false, // turned on by touch events, don't set
|
isTouchDevice: false, // turned on by touch events, don't set
|
||||||
rasterizeSVGs: false,
|
rasterizeSVGs: false,
|
||||||
isFlat: false
|
isFlat: false,
|
||||||
|
grabThreshold: 5
|
||||||
};
|
};
|
||||||
|
|
||||||
var touchScreenSettings = {
|
var touchScreenSettings = {
|
||||||
|
|
@ -1091,7 +1092,8 @@ var touchScreenSettings = {
|
||||||
useVirtualKeyboard: true,
|
useVirtualKeyboard: true,
|
||||||
isTouchDevice: false,
|
isTouchDevice: false,
|
||||||
rasterizeSVGs: false,
|
rasterizeSVGs: false,
|
||||||
isFlat: false
|
isFlat: false,
|
||||||
|
grabThreshold: 5
|
||||||
};
|
};
|
||||||
|
|
||||||
var MorphicPreferences = standardSettings;
|
var MorphicPreferences = standardSettings;
|
||||||
|
|
@ -2207,7 +2209,10 @@ function Morph() {
|
||||||
Morph.prototype.init = function (noDraw) {
|
Morph.prototype.init = function (noDraw) {
|
||||||
Morph.uber.init.call(this);
|
Morph.uber.init.call(this);
|
||||||
this.isMorph = true;
|
this.isMorph = true;
|
||||||
|
this.image = null;
|
||||||
this.bounds = new Rectangle(0, 0, 50, 40);
|
this.bounds = new Rectangle(0, 0, 50, 40);
|
||||||
|
this.cachedFullImage = null;
|
||||||
|
this.cachedFullBounds = null;
|
||||||
this.color = new Color(80, 80, 80);
|
this.color = new Color(80, 80, 80);
|
||||||
this.texture = null; // optional url of a fill-image
|
this.texture = null; // optional url of a fill-image
|
||||||
this.cachedTexture = null; // internal cache of actual bg image
|
this.cachedTexture = null; // internal cache of actual bg image
|
||||||
|
|
@ -2284,9 +2289,7 @@ Morph.prototype.nextSteps = function (arrayOfFunctions) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Morph.prototype.step = function () {
|
Morph.prototype.step = nop;
|
||||||
nop();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Morph accessing - geometry getting:
|
// Morph accessing - geometry getting:
|
||||||
|
|
||||||
|
|
@ -2412,6 +2415,9 @@ Morph.prototype.silentMoveBy = function (delta) {
|
||||||
var children = this.children,
|
var children = this.children,
|
||||||
i = children.length;
|
i = children.length;
|
||||||
this.bounds = this.bounds.translateBy(delta);
|
this.bounds = this.bounds.translateBy(delta);
|
||||||
|
if (this.cachedFullBounds) {
|
||||||
|
this.cachedFullBounds = this.cachedFullBounds.translateBy(delta);
|
||||||
|
}
|
||||||
// ugly optimization avoiding forEach()
|
// ugly optimization avoiding forEach()
|
||||||
for (i; i > 0; i -= 1) {
|
for (i; i > 0; i -= 1) {
|
||||||
children[i - 1].silentMoveBy(delta);
|
children[i - 1].silentMoveBy(delta);
|
||||||
|
|
@ -2533,7 +2539,12 @@ Morph.prototype.scrollIntoView = function () {
|
||||||
|
|
||||||
// Morph accessing - dimensional changes requiring a complete redraw
|
// Morph accessing - dimensional changes requiring a complete redraw
|
||||||
|
|
||||||
Morph.prototype.setExtent = function (aPoint) {
|
Morph.prototype.setExtent = function (aPoint, silently) {
|
||||||
|
// silently avoids redrawing the receiver
|
||||||
|
if (silently) {
|
||||||
|
this.silentSetExtent(aPoint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!aPoint.eq(this.extent())) {
|
if (!aPoint.eq(this.extent())) {
|
||||||
this.changed();
|
this.changed();
|
||||||
this.silentSetExtent(aPoint);
|
this.silentSetExtent(aPoint);
|
||||||
|
|
@ -2640,29 +2651,31 @@ Morph.prototype.drawCachedTexture = function () {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Morph.prototype.drawOn = function (aCanvas, aRect) {
|
Morph.prototype.drawOn = function (aCanvas, aRect) {
|
||||||
var rectangle, area, delta, src, context, w, h, sl, st;
|
var rectangle, area, delta, src, context, w, h, sl, st,
|
||||||
|
pic = this.cachedFullImage || this.image,
|
||||||
|
bounds = this.cachedFullBounds || this.bounds;
|
||||||
if (!this.isVisible) {
|
if (!this.isVisible) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
rectangle = aRect || this.bounds();
|
rectangle = aRect || bounds;
|
||||||
area = rectangle.intersect(this.bounds);
|
area = rectangle.intersect(bounds);
|
||||||
if (area.extent().gt(new Point(0, 0))) {
|
if (area.extent().gt(new Point(0, 0))) {
|
||||||
delta = this.position().neg();
|
delta = bounds.position().neg();
|
||||||
src = area.copy().translateBy(delta);
|
src = area.copy().translateBy(delta);
|
||||||
context = aCanvas.getContext('2d');
|
context = aCanvas.getContext('2d');
|
||||||
context.globalAlpha = this.alpha;
|
context.globalAlpha = this.alpha;
|
||||||
|
|
||||||
sl = src.left();
|
sl = src.left();
|
||||||
st = src.top();
|
st = src.top();
|
||||||
w = Math.min(src.width(), this.image.width - sl);
|
w = Math.min(src.width(), pic.width - sl);
|
||||||
h = Math.min(src.height(), this.image.height - st);
|
h = Math.min(src.height(), pic.height - st);
|
||||||
|
|
||||||
if (w < 1 || h < 1) {
|
if (w < 1 || h < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.drawImage(
|
context.drawImage(
|
||||||
this.image,
|
pic,
|
||||||
sl,
|
sl,
|
||||||
st,
|
st,
|
||||||
w,
|
w,
|
||||||
|
|
@ -2672,42 +2685,6 @@ Morph.prototype.drawOn = function (aCanvas, aRect) {
|
||||||
w,
|
w,
|
||||||
h
|
h
|
||||||
);
|
);
|
||||||
|
|
||||||
/* "for debugging purposes:"
|
|
||||||
|
|
||||||
try {
|
|
||||||
context.drawImage(
|
|
||||||
this.image,
|
|
||||||
sl,
|
|
||||||
st,
|
|
||||||
w,
|
|
||||||
h,
|
|
||||||
area.left(),
|
|
||||||
area.top(),
|
|
||||||
w,
|
|
||||||
h
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
alert('internal error\n\n' + err
|
|
||||||
+ '\n ---'
|
|
||||||
+ '\n canvas: ' + aCanvas
|
|
||||||
+ '\n canvas.width: ' + aCanvas.width
|
|
||||||
+ '\n canvas.height: ' + aCanvas.height
|
|
||||||
+ '\n ---'
|
|
||||||
+ '\n image: ' + this.image
|
|
||||||
+ '\n image.width: ' + this.image.width
|
|
||||||
+ '\n image.height: ' + this.image.height
|
|
||||||
+ '\n ---'
|
|
||||||
+ '\n w: ' + w
|
|
||||||
+ '\n h: ' + h
|
|
||||||
+ '\n sl: ' + sl
|
|
||||||
+ '\n st: ' + st
|
|
||||||
+ '\n area.left: ' + area.left()
|
|
||||||
+ '\n area.top ' + area.top()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2716,8 +2693,9 @@ Morph.prototype.fullDrawOn = function (aCanvas, aRect) {
|
||||||
if (!this.isVisible) {
|
if (!this.isVisible) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
rectangle = aRect || this.fullBounds();
|
rectangle = aRect || this.cachedFullBounds || this.fullBounds();
|
||||||
this.drawOn(aCanvas, rectangle);
|
this.drawOn(aCanvas, rectangle);
|
||||||
|
if (this.cachedFullImage) {return; }
|
||||||
this.children.forEach(function (child) {
|
this.children.forEach(function (child) {
|
||||||
child.fullDrawOn(aCanvas, rectangle);
|
child.fullDrawOn(aCanvas, rectangle);
|
||||||
});
|
});
|
||||||
|
|
@ -2911,7 +2889,9 @@ Morph.prototype.fullChanged = function () {
|
||||||
if (this.trackChanges) {
|
if (this.trackChanges) {
|
||||||
var w = this.root();
|
var w = this.root();
|
||||||
if (w instanceof WorldMorph) {
|
if (w instanceof WorldMorph) {
|
||||||
w.broken.push(this.fullBounds().spread());
|
w.broken.push(
|
||||||
|
(this.cachedFullBounds || this.fullBounds()).spread()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -9448,7 +9428,7 @@ function HandMorph(aWorld) {
|
||||||
// HandMorph initialization:
|
// HandMorph initialization:
|
||||||
|
|
||||||
HandMorph.prototype.init = function (aWorld) {
|
HandMorph.prototype.init = function (aWorld) {
|
||||||
HandMorph.uber.init.call(this);
|
HandMorph.uber.init.call(this, true);
|
||||||
this.bounds = new Rectangle();
|
this.bounds = new Rectangle();
|
||||||
|
|
||||||
// additional properties:
|
// additional properties:
|
||||||
|
|
@ -9456,6 +9436,7 @@ HandMorph.prototype.init = function (aWorld) {
|
||||||
this.mouseButton = null;
|
this.mouseButton = null;
|
||||||
this.mouseOverList = [];
|
this.mouseOverList = [];
|
||||||
this.morphToGrab = null;
|
this.morphToGrab = null;
|
||||||
|
this.grabPosition = null;
|
||||||
this.grabOrigin = null;
|
this.grabOrigin = null;
|
||||||
this.temporaries = [];
|
this.temporaries = [];
|
||||||
this.touchHoldTimeout = null;
|
this.touchHoldTimeout = null;
|
||||||
|
|
@ -9520,6 +9501,8 @@ HandMorph.prototype.grab = function (aMorph) {
|
||||||
if (aMorph.prepareToBeGrabbed) {
|
if (aMorph.prepareToBeGrabbed) {
|
||||||
aMorph.prepareToBeGrabbed(this);
|
aMorph.prepareToBeGrabbed(this);
|
||||||
}
|
}
|
||||||
|
aMorph.cachedFullImage = aMorph.fullImageClassic();
|
||||||
|
aMorph.cachedFullBounds = aMorph.fullBounds();
|
||||||
this.add(aMorph);
|
this.add(aMorph);
|
||||||
this.changed();
|
this.changed();
|
||||||
if (oldParent && oldParent.reactToGrabOf) {
|
if (oldParent && oldParent.reactToGrabOf) {
|
||||||
|
|
@ -9535,6 +9518,8 @@ HandMorph.prototype.drop = function () {
|
||||||
target = this.dropTargetFor(morphToDrop);
|
target = this.dropTargetFor(morphToDrop);
|
||||||
this.changed();
|
this.changed();
|
||||||
target.add(morphToDrop);
|
target.add(morphToDrop);
|
||||||
|
morphToDrop.cachedFullImage = null;
|
||||||
|
morphToDrop.cachedFullBounds = null;
|
||||||
morphToDrop.changed();
|
morphToDrop.changed();
|
||||||
morphToDrop.removeShadow();
|
morphToDrop.removeShadow();
|
||||||
this.children = [];
|
this.children = [];
|
||||||
|
|
@ -9545,7 +9530,6 @@ HandMorph.prototype.drop = function () {
|
||||||
if (target.reactToDropOf) {
|
if (target.reactToDropOf) {
|
||||||
target.reactToDropOf(morphToDrop, this);
|
target.reactToDropOf(morphToDrop, this);
|
||||||
}
|
}
|
||||||
this.dragOrigin = null;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -9572,6 +9556,7 @@ HandMorph.prototype.processMouseDown = function (event) {
|
||||||
this.destroyTemporaries();
|
this.destroyTemporaries();
|
||||||
this.contextMenuEnabled = true;
|
this.contextMenuEnabled = true;
|
||||||
this.morphToGrab = null;
|
this.morphToGrab = null;
|
||||||
|
this.grabPosition = null;
|
||||||
if (this.children.length !== 0) {
|
if (this.children.length !== 0) {
|
||||||
this.drop();
|
this.drop();
|
||||||
this.mouseButton = null;
|
this.mouseButton = null;
|
||||||
|
|
@ -9599,6 +9584,7 @@ HandMorph.prototype.processMouseDown = function (event) {
|
||||||
}
|
}
|
||||||
if (!morph.mouseMove) {
|
if (!morph.mouseMove) {
|
||||||
this.morphToGrab = morph.rootForGrab();
|
this.morphToGrab = morph.rootForGrab();
|
||||||
|
this.grabPosition = this.bounds.origin.copy();
|
||||||
}
|
}
|
||||||
if (event.button === 2 || event.ctrlKey) {
|
if (event.button === 2 || event.ctrlKey) {
|
||||||
this.mouseButton = 'right';
|
this.mouseButton = 'right';
|
||||||
|
|
@ -9708,8 +9694,7 @@ HandMorph.prototype.processMouseMove = function (event) {
|
||||||
mouseOverNew,
|
mouseOverNew,
|
||||||
myself = this,
|
myself = this,
|
||||||
morph,
|
morph,
|
||||||
topMorph,
|
topMorph;
|
||||||
fb;
|
|
||||||
|
|
||||||
pos = new Point(
|
pos = new Point(
|
||||||
event.pageX - posInDocument.x,
|
event.pageX - posInDocument.x,
|
||||||
|
|
@ -9733,7 +9718,11 @@ HandMorph.prototype.processMouseMove = function (event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if a morph is marked for grabbing, just grab it
|
// if a morph is marked for grabbing, just grab it
|
||||||
if (this.mouseButton === 'left' && this.morphToGrab) {
|
if (this.mouseButton === 'left' &&
|
||||||
|
this.morphToGrab &&
|
||||||
|
(this.grabPosition.distanceTo(this.bounds.origin) >
|
||||||
|
MorphicPreferences.grabThreshold)) {
|
||||||
|
this.setPosition(this.grabPosition);
|
||||||
if (this.morphToGrab.isDraggable) {
|
if (this.morphToGrab.isDraggable) {
|
||||||
morph = this.morphToGrab;
|
morph = this.morphToGrab;
|
||||||
this.grab(morph);
|
this.grab(morph);
|
||||||
|
|
@ -9747,16 +9736,7 @@ HandMorph.prototype.processMouseMove = function (event) {
|
||||||
this.grab(morph);
|
this.grab(morph);
|
||||||
this.grabOrigin = this.morphToGrab.situation();
|
this.grabOrigin = this.morphToGrab.situation();
|
||||||
}
|
}
|
||||||
if (morph) {
|
this.setPosition(pos);
|
||||||
// if the mouse has left its fullBounds, allow to center it
|
|
||||||
fb = morph.fullBounds();
|
|
||||||
if (!fb.containsPoint(pos) &&
|
|
||||||
morph.isCorrectingOutsideDrag()) {
|
|
||||||
this.bounds.origin = fb.center();
|
|
||||||
this.grab(morph);
|
|
||||||
this.setPosition(pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
23
objects.js
23
objects.js
|
|
@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.objects = '2015-October-07';
|
modules.objects = '2015-November-16';
|
||||||
|
|
||||||
var SpriteMorph;
|
var SpriteMorph;
|
||||||
var StageMorph;
|
var StageMorph;
|
||||||
|
|
@ -1184,7 +1184,7 @@ SpriteMorph.prototype.initBlocks = function () {
|
||||||
dev: true,
|
dev: true,
|
||||||
type: 'command',
|
type: 'command',
|
||||||
category: 'lists',
|
category: 'lists',
|
||||||
spec: 'for %upvar in %l %cs',
|
spec: 'for %upvar in %l %cl',
|
||||||
defaults: [localize('each item')]
|
defaults: [localize('each item')]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -2326,7 +2326,7 @@ SpriteMorph.prototype.freshPalette = function (category) {
|
||||||
x = block.right() + unit / 2;
|
x = block.right() + unit / 2;
|
||||||
ry = block.bottom();
|
ry = block.bottom();
|
||||||
} else {
|
} else {
|
||||||
if (block.fixLayout) {block.fixLayout(); }
|
// if (block.fixLayout) {block.fixLayout(); }
|
||||||
x = 0;
|
x = 0;
|
||||||
y += block.height();
|
y += block.height();
|
||||||
}
|
}
|
||||||
|
|
@ -3249,7 +3249,7 @@ SpriteMorph.prototype.bubble = function (data, isThought, isQuestion) {
|
||||||
if (data === '' || isNil(data)) {return; }
|
if (data === '' || isNil(data)) {return; }
|
||||||
bubble = new SpriteBubbleMorph(
|
bubble = new SpriteBubbleMorph(
|
||||||
data,
|
data,
|
||||||
stage ? stage.scale : 1,
|
stage,
|
||||||
isThought,
|
isThought,
|
||||||
isQuestion
|
isQuestion
|
||||||
);
|
);
|
||||||
|
|
@ -3539,6 +3539,7 @@ SpriteMorph.prototype.gotoXY = function (x, y, justMe) {
|
||||||
newY,
|
newY,
|
||||||
dest;
|
dest;
|
||||||
|
|
||||||
|
if (!stage) {return; }
|
||||||
newX = stage.center().x + (+x || 0) * stage.scale;
|
newX = stage.center().x + (+x || 0) * stage.scale;
|
||||||
newY = stage.center().y - (+y || 0) * stage.scale;
|
newY = stage.center().y - (+y || 0) * stage.scale;
|
||||||
if (this.costume) {
|
if (this.costume) {
|
||||||
|
|
@ -6054,18 +6055,19 @@ SpriteBubbleMorph.uber = SpeechBubbleMorph.prototype;
|
||||||
|
|
||||||
// SpriteBubbleMorph instance creation:
|
// SpriteBubbleMorph instance creation:
|
||||||
|
|
||||||
function SpriteBubbleMorph(data, scale, isThought, isQuestion) {
|
function SpriteBubbleMorph(data, stage, isThought, isQuestion) {
|
||||||
this.init(data, scale, isThought, isQuestion);
|
this.init(data, stage, isThought, isQuestion);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteBubbleMorph.prototype.init = function (
|
SpriteBubbleMorph.prototype.init = function (
|
||||||
data,
|
data,
|
||||||
scale,
|
stage,
|
||||||
isThought,
|
isThought,
|
||||||
isQuestion
|
isQuestion
|
||||||
) {
|
) {
|
||||||
var sprite = SpriteMorph.prototype;
|
var sprite = SpriteMorph.prototype;
|
||||||
this.scale = scale || 1;
|
this.stage = stage;
|
||||||
|
this.scale = stage ? stage.scale : 1;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.isQuestion = isQuestion;
|
this.isQuestion = isQuestion;
|
||||||
|
|
||||||
|
|
@ -6125,6 +6127,11 @@ SpriteBubbleMorph.prototype.dataAsMorph = function (data) {
|
||||||
contents.isDraggable = false;
|
contents.isDraggable = false;
|
||||||
contents.update(true);
|
contents.update(true);
|
||||||
contents.step = contents.update;
|
contents.step = contents.update;
|
||||||
|
if (this.stage) {
|
||||||
|
contents.expand(this.stage.extent().translateBy(
|
||||||
|
-2 * (this.edge + this.border + this.padding)
|
||||||
|
));
|
||||||
|
}
|
||||||
} else if (data instanceof Context) {
|
} else if (data instanceof Context) {
|
||||||
img = data.image();
|
img = data.image();
|
||||||
contents = new Morph();
|
contents = new Morph();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Snap! Build Your Own Blocks</title>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico">
|
||||||
|
<script type="text/javascript" src="morphic.js"></script>
|
||||||
|
<script type="text/javascript" src="widgets.js"></script>
|
||||||
|
<script type="text/javascript" src="blocks.js"></script>
|
||||||
|
<script type="text/javascript" src="threads.js"></script>
|
||||||
|
<script type="text/javascript" src="objects.js"></script>
|
||||||
|
<script type="text/javascript" src="gui.js"></script>
|
||||||
|
<script type="text/javascript" src="paint.js"></script>
|
||||||
|
<script type="text/javascript" src="lists.js"></script>
|
||||||
|
<script type="text/javascript" src="byob.js"></script>
|
||||||
|
<script type="text/javascript" src="xml.js"></script>
|
||||||
|
<script type="text/javascript" src="store.js"></script>
|
||||||
|
<script type="text/javascript" src="locale.js"></script>
|
||||||
|
<script type="text/javascript" src="cloud.js"></script>
|
||||||
|
<script type="text/javascript" src="sha512.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var world;
|
||||||
|
window.onload = function () {
|
||||||
|
world = new WorldMorph(document.getElementById('world'));
|
||||||
|
world.worldCanvas.focus();
|
||||||
|
new IDE_Morph().openIn(world);
|
||||||
|
loop();
|
||||||
|
};
|
||||||
|
function loop() {
|
||||||
|
requestAnimationFrame(loop);
|
||||||
|
world.doOneCycle();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body style="margin: 0;">
|
||||||
|
<canvas id="world" tabindex="1" style="position: absolute;" />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
25
threads.js
25
threads.js
|
|
@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.threads = '2015-October-02';
|
modules.threads = '2015-November-16';
|
||||||
|
|
||||||
var ThreadManager;
|
var ThreadManager;
|
||||||
var Process;
|
var Process;
|
||||||
|
|
@ -128,6 +128,26 @@ function snapEquals(a, b) {
|
||||||
return x === y;
|
return x === y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke(block, timeout) {
|
||||||
|
// exectue the given block synchronously, i.e. without yielding.
|
||||||
|
// if a timeout (in milliseconds) is specified, abort execution
|
||||||
|
// after the timeout has been reached and throw an error.
|
||||||
|
// For debugging purposes only.
|
||||||
|
// Caution: Kids, do not try this at home!
|
||||||
|
// use ThreadManager::startProcess instead
|
||||||
|
var proc = new Process(block),
|
||||||
|
startTime = Date.now();
|
||||||
|
while (proc.isRunning()) {
|
||||||
|
if (timeout && ((Date.now() - startTime) > timeout)) {
|
||||||
|
throw (new Error("a synchronous Snap! script has timed out"));
|
||||||
|
}
|
||||||
|
proc.runStep();
|
||||||
|
}
|
||||||
|
if (block instanceof ReporterBlockMorph) {
|
||||||
|
return proc.homeContext.inputs[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ThreadManager ///////////////////////////////////////////////////////
|
// ThreadManager ///////////////////////////////////////////////////////
|
||||||
|
|
||||||
function ThreadManager() {
|
function ThreadManager() {
|
||||||
|
|
@ -638,7 +658,8 @@ Process.prototype.evaluateInput = function (input) {
|
||||||
if (contains(
|
if (contains(
|
||||||
[CommandSlotMorph, ReporterSlotMorph],
|
[CommandSlotMorph, ReporterSlotMorph],
|
||||||
input.constructor
|
input.constructor
|
||||||
) || (input instanceof CSlotMorph && !input.isStatic)) {
|
) || (input instanceof CSlotMorph &&
|
||||||
|
(!input.isStatic || input.isLambda))) {
|
||||||
// I know, this still needs yet to be done right....
|
// I know, this still needs yet to be done right....
|
||||||
ans = this.reify(ans, new List());
|
ans = this.reify(ans, new List());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue