kopia lustrzana https://github.com/backface/turtlestitch
Merge in 4.0.3, resolve conflicts with scriptpics
commit
fa6f168bc0
|
@ -0,0 +1,12 @@
|
|||
atom-playground.jpg Atom Playground
|
||||
bedroom1.gif Bedroom 1
|
||||
bedroom2.gif Bedroom 2
|
||||
berkeley-mural.jpg Berkeley Mural
|
||||
brick-wall-and-stairs.jpg Brick Wall and Stairs
|
||||
brick-wall1.jpg Brick Wall 1
|
||||
brick-wall2.jpg Brick Wall 2
|
||||
desert.gif Desert
|
||||
night-city-with-street.gif Night City with Street
|
||||
party-room.jpg Party Room
|
||||
pathway.jpg Pathway
|
||||
xy-grid.gif XY Grid
|
|
@ -0,0 +1,32 @@
|
|||
alonzo.png Alonzo
|
||||
bat1-a.png Bat 1a
|
||||
bat1-b.png Bat 1b
|
||||
bat2-a.png Bat 2a
|
||||
bat2-b.png Bat 2b
|
||||
boy1-standing.gif Boy 1 Standing
|
||||
boy1-walking.gif Boy 1 Walking
|
||||
boy2.gif Boy 2
|
||||
boy3.gif Boy 3
|
||||
cat2.gif Cat 2
|
||||
cat3.png Cat 3
|
||||
cat4.png Cat 4
|
||||
cat5.gif Cat 5
|
||||
dog1-a.png Dog 1a
|
||||
dog1-b.png Dog 1b
|
||||
dog2-a.png Dog 2a
|
||||
dog2-b.png Dog 2b
|
||||
dog2-c.png Dog 2c
|
||||
dragon1-a.png Dragon 1a
|
||||
dragon1-b.png Dragon 1b
|
||||
dragon2.gif Dragon 2
|
||||
girl1-standing.gif Girl 1 Standing
|
||||
girl1-walking.gif Girl 1 Walking
|
||||
girl2-shouting.gif Girl 2 Shouting
|
||||
girl2-standing.gif Girl 2 Standing
|
||||
girl3-basketball.gif Girl 3 Basketball
|
||||
girl3-running.gif Girl 3 Running
|
||||
girl3-standing.gif Girl 3 Standing
|
||||
marissa-crouching.gif Marissa Crouching
|
||||
marissa-sitting.gif Marissa Sitting
|
||||
marissa.gif Marissa
|
||||
unicorn1.png Unicorn
|
|
@ -0,0 +1,10 @@
|
|||
animal-game.xml Animal Game
|
||||
Codification.xml Codification
|
||||
copter.xml Copter
|
||||
count-change.xml Count Change
|
||||
icecream-visual.xml Icecream Visual
|
||||
JSfunctions.xml JSfunctions
|
||||
live-tree.xml Live Tree
|
||||
swimmer.xml Swimmer
|
||||
tree.xml Tree
|
||||
vee.xml Vee
|
|
@ -0,0 +1,12 @@
|
|||
Cat.mp3 Cat
|
||||
Chord.wav Chord
|
||||
Dog1.wav Dog 1
|
||||
Dog2.wav Dog 2
|
||||
FingerSnap.wav Finger Snap
|
||||
Kitten.wav Kitten
|
||||
Laugh-female.wav Laugh Female
|
||||
Laugh-male1.wav Laugh Male 1
|
||||
Laugh-male2.wav Laugh Male 2
|
||||
Laugh-male3.mp3 Laugh Male 3
|
||||
Meow.wav Meow
|
||||
Pop.wav Pop
|
197
blocks.js
197
blocks.js
|
@ -156,7 +156,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.blocks = '2015-October-02';
|
||||
modules.blocks = '2015-November-16';
|
||||
|
||||
var SyntaxElementMorph;
|
||||
var BlockMorph;
|
||||
|
@ -349,22 +349,18 @@ function SyntaxElementMorph() {
|
|||
this.init();
|
||||
}
|
||||
|
||||
SyntaxElementMorph.prototype.init = function () {
|
||||
SyntaxElementMorph.prototype.init = function (silently) {
|
||||
this.cachedClr = null;
|
||||
this.cachedClrBright = null;
|
||||
this.cachedClrDark = null;
|
||||
this.isStatic = false; // if true, I cannot be exchanged
|
||||
|
||||
SyntaxElementMorph.uber.init.call(this);
|
||||
SyntaxElementMorph.uber.init.call(this, silently);
|
||||
|
||||
this.defaults = [];
|
||||
this.cachedInputs = null;
|
||||
};
|
||||
|
||||
// SyntaxElementMorph stepping:
|
||||
|
||||
SyntaxElementMorph.prototype.step = null;
|
||||
|
||||
// SyntaxElementMorph accessing:
|
||||
|
||||
SyntaxElementMorph.prototype.parts = function () {
|
||||
|
@ -472,8 +468,7 @@ SyntaxElementMorph.prototype.replaceInput = function (oldArg, newArg) {
|
|||
var scripts = this.parentThatIsA(ScriptsMorph),
|
||||
replacement = newArg,
|
||||
idx = this.children.indexOf(oldArg),
|
||||
i = 0,
|
||||
nb;
|
||||
i = 0;
|
||||
|
||||
// try to find the ArgLabel embedding the newArg,
|
||||
// used for the undrop() feature
|
||||
|
@ -511,13 +506,6 @@ SyntaxElementMorph.prototype.replaceInput = function (oldArg, newArg) {
|
|||
oldArg.moveBy(replacement.extent());
|
||||
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
|
||||
|| replacement instanceof ArgLabelMorph
|
||||
|
@ -703,14 +691,16 @@ SyntaxElementMorph.prototype.dark = function () {
|
|||
|
||||
// SyntaxElementMorph color changing:
|
||||
|
||||
SyntaxElementMorph.prototype.setColor = function (aColor) {
|
||||
SyntaxElementMorph.prototype.setColor = function (aColor, silently) {
|
||||
if (aColor) {
|
||||
if (!this.color.eq(aColor)) {
|
||||
this.color = aColor;
|
||||
this.drawNew();
|
||||
if (!silently) {this.drawNew(); }
|
||||
this.children.forEach(function (child) {
|
||||
child.drawNew();
|
||||
child.changed();
|
||||
if (!silently || child instanceof TemplateSlotMorph) {
|
||||
child.drawNew();
|
||||
child.changed();
|
||||
}
|
||||
});
|
||||
this.changed();
|
||||
}
|
||||
|
@ -942,6 +932,7 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
|
|||
},
|
||||
true // read-only
|
||||
);
|
||||
part.isStatic = true;
|
||||
break;
|
||||
case '%dates':
|
||||
part = new InputSlotMorph(
|
||||
|
@ -1302,6 +1293,11 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
|
|||
case '%cs':
|
||||
part = new CSlotMorph(); // non-static
|
||||
break;
|
||||
case '%cl':
|
||||
part = new CSlotMorph();
|
||||
part.isStatic = true; // rejects reporter drops
|
||||
part.isLambda = true; // auto-reifies nested script
|
||||
break;
|
||||
case '%clr':
|
||||
part = new ColorSlotMorph();
|
||||
part.isStatic = true;
|
||||
|
@ -1501,7 +1497,7 @@ SyntaxElementMorph.prototype.isObjInputFragment = function () {
|
|||
|
||||
// SyntaxElementMorph layout:
|
||||
|
||||
SyntaxElementMorph.prototype.fixLayout = function () {
|
||||
SyntaxElementMorph.prototype.fixLayout = function (silently) {
|
||||
var nb,
|
||||
parts = this.parts(),
|
||||
myself = this,
|
||||
|
@ -1682,8 +1678,8 @@ SyntaxElementMorph.prototype.fixLayout = function () {
|
|||
}
|
||||
}
|
||||
|
||||
// set my extent:
|
||||
this.setExtent(new Point(blockWidth, blockHeight));
|
||||
// set my extent (silently, because we'll redraw later anyway):
|
||||
this.silentSetExtent(new Point(blockWidth, blockHeight));
|
||||
|
||||
// adjust CSlots
|
||||
parts.forEach(function (part) {
|
||||
|
@ -1697,7 +1693,7 @@ SyntaxElementMorph.prototype.fixLayout = function () {
|
|||
});
|
||||
|
||||
// redraw in order to erase CSlot backgrounds
|
||||
this.drawNew();
|
||||
if (!silently) {this.drawNew(); }
|
||||
|
||||
// position next block:
|
||||
if (nb) {
|
||||
|
@ -1777,6 +1773,7 @@ SyntaxElementMorph.prototype.showBubble = function (value, exportPic) {
|
|||
morphToShow.update(true);
|
||||
morphToShow.step = value.update;
|
||||
morphToShow.isDraggable = false;
|
||||
morphToShow.expand(this.parentThatIsA(ScrollFrameMorph).extent());
|
||||
isClickable = true;
|
||||
} else if (value instanceof Morph) {
|
||||
img = value.fullImage();
|
||||
|
@ -1956,7 +1953,9 @@ SyntaxElementMorph.prototype.endLayout = function () {
|
|||
%lst - chameleon colored rectangular drop-down for list names
|
||||
%b - chameleon colored hexagonal slot (for predicates)
|
||||
%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
|
||||
%t - inline variable reporter template
|
||||
%anyUE - white rectangular type-in slot, unevaluated if replaced
|
||||
|
@ -2029,7 +2028,7 @@ function BlockMorph() {
|
|||
this.init();
|
||||
}
|
||||
|
||||
BlockMorph.prototype.init = function () {
|
||||
BlockMorph.prototype.init = function (silently) {
|
||||
this.selector = null; // name of method to be triggered
|
||||
this.blockSpec = ''; // formal description of label and arguments
|
||||
this.comment = null; // optional "sticky" comment morph
|
||||
|
@ -2038,7 +2037,7 @@ BlockMorph.prototype.init = function () {
|
|||
this.instantiationSpec = null; // spec to set upon fullCopy() of template
|
||||
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.cashedInputs = null;
|
||||
};
|
||||
|
@ -2103,7 +2102,7 @@ BlockMorph.prototype.parseSpec = function (spec) {
|
|||
return result;
|
||||
};
|
||||
|
||||
BlockMorph.prototype.setSpec = function (spec) {
|
||||
BlockMorph.prototype.setSpec = function (spec, silently) {
|
||||
var myself = this,
|
||||
part,
|
||||
inputIdx = -1;
|
||||
|
@ -2146,10 +2145,17 @@ BlockMorph.prototype.setSpec = function (spec) {
|
|||
}
|
||||
});
|
||||
this.blockSpec = spec;
|
||||
this.fixLayout();
|
||||
this.fixLayout(silently);
|
||||
this.cachedInputs = null;
|
||||
};
|
||||
|
||||
BlockMorph.prototype.userSetSpec = function (spec) {
|
||||
var tb = this.topBlock();
|
||||
tb.fullChanged();
|
||||
this.setSpec(spec);
|
||||
tb.fullChanged();
|
||||
};
|
||||
|
||||
BlockMorph.prototype.buildSpec = function () {
|
||||
// create my blockSpec from my parts - for demo purposes only
|
||||
var myself = this;
|
||||
|
@ -2455,6 +2461,7 @@ BlockMorph.prototype.ringify = function () {
|
|||
center = top.fullBounds().center();
|
||||
|
||||
if (this.parent === null) {return null; }
|
||||
top.fullChanged();
|
||||
if (this.parent instanceof SyntaxElementMorph) {
|
||||
if (this instanceof ReporterBlockMorph) {
|
||||
this.parent.silentReplaceInput(this, ring);
|
||||
|
@ -2470,11 +2477,14 @@ BlockMorph.prototype.ringify = function () {
|
|||
ring.setCenter(center);
|
||||
}
|
||||
this.fixBlockColor(null, true);
|
||||
top.fullChanged();
|
||||
|
||||
};
|
||||
|
||||
BlockMorph.prototype.unringify = function () {
|
||||
// remove a Ring around me, if any
|
||||
var ring = this.parentThatIsA(RingMorph),
|
||||
top = this.topBlock(),
|
||||
scripts = this.parentThatIsA(ScriptsMorph),
|
||||
block,
|
||||
center;
|
||||
|
@ -2483,6 +2493,7 @@ BlockMorph.prototype.unringify = function () {
|
|||
block = ring.contents();
|
||||
center = ring.center();
|
||||
|
||||
top.fullChanged();
|
||||
if (ring.parent instanceof SyntaxElementMorph) {
|
||||
if (block instanceof ReporterBlockMorph) {
|
||||
ring.parent.silentReplaceInput(ring, block);
|
||||
|
@ -2498,6 +2509,7 @@ BlockMorph.prototype.unringify = function () {
|
|||
ring.destroy();
|
||||
}
|
||||
this.fixBlockColor(null, true);
|
||||
top.fullChanged();
|
||||
};
|
||||
|
||||
BlockMorph.prototype.relabel = function (alternativeSelectors) {
|
||||
|
@ -2566,6 +2578,7 @@ BlockMorph.prototype.restoreInputs = function (oldInputs) {
|
|||
|
||||
BlockMorph.prototype.showHelp = function () {
|
||||
var myself = this,
|
||||
ide = this.parentThatIsA(IDE_Morph),
|
||||
pic = new Image(),
|
||||
help,
|
||||
comment,
|
||||
|
@ -2603,7 +2616,7 @@ BlockMorph.prototype.showHelp = function () {
|
|||
block.fullImage()
|
||||
);
|
||||
} else {
|
||||
pic.src = 'help/' + spec + '.png';
|
||||
pic.src = ide.resourceURL('help', spec + '.png');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2894,12 +2907,13 @@ BlockMorph.prototype.eraseHoles = function (context) {
|
|||
var w = hole.width(),
|
||||
h = Math.floor(hole.height()) - 2; // Opera needs this
|
||||
context.clearRect(
|
||||
Math.floor(hole.bounds.origin.x - myself.bounds.origin.x) + 1,
|
||||
Math.floor(hole.bounds.origin.y - myself.bounds.origin.y) + 1,
|
||||
isReporter ? w - 1 : w + 1,
|
||||
hole.bounds.origin.x - myself.bounds.origin.x + 1,
|
||||
hole.bounds.origin.y - myself.bounds.origin.y + 1,
|
||||
isReporter ? w - 2 : w + 1,
|
||||
h
|
||||
);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// BlockMorph highlighting
|
||||
|
@ -3088,7 +3102,7 @@ BlockMorph.prototype.fixBlockColor = function (nearestBlock, isForced) {
|
|||
|
||||
BlockMorph.prototype.forceNormalColoring = function () {
|
||||
var clr = SpriteMorph.prototype.blockColor[this.category];
|
||||
this.setColor(clr);
|
||||
this.setColor(clr, true); // silently
|
||||
this.setLabelColor(
|
||||
new Color(255, 255, 255),
|
||||
clr.darker(this.labelContrast),
|
||||
|
@ -3103,10 +3117,11 @@ BlockMorph.prototype.alternateBlockColor = function () {
|
|||
if (this.color.eq(clr)) {
|
||||
this.setColor(
|
||||
this.zebraContrast < 0 ? clr.darker(Math.abs(this.zebraContrast))
|
||||
: clr.lighter(this.zebraContrast)
|
||||
: clr.lighter(this.zebraContrast),
|
||||
true // silently
|
||||
);
|
||||
} else {
|
||||
this.setColor(clr);
|
||||
this.setColor(clr, true); // silently
|
||||
}
|
||||
this.fixLabelColor();
|
||||
this.fixChildrensBlockColor(true); // has issues if not forced
|
||||
|
@ -3363,6 +3378,7 @@ BlockMorph.prototype.prepareToBeGrabbed = function (hand) {
|
|||
};
|
||||
|
||||
BlockMorph.prototype.justDropped = function () {
|
||||
this.alpha = 1;
|
||||
this.allComments().forEach(function (comment) {
|
||||
comment.stopFollowing();
|
||||
});
|
||||
|
@ -3451,9 +3467,9 @@ function CommandBlockMorph() {
|
|||
this.init();
|
||||
}
|
||||
|
||||
CommandBlockMorph.prototype.init = function () {
|
||||
CommandBlockMorph.uber.init.call(this);
|
||||
this.setExtent(new Point(200, 100));
|
||||
CommandBlockMorph.prototype.init = function (silently) {
|
||||
CommandBlockMorph.uber.init.call(this, silently);
|
||||
this.setExtent(new Point(200, 100), silently);
|
||||
this.partOfCustomCommand = false;
|
||||
this.exitTag = null;
|
||||
};
|
||||
|
@ -3486,7 +3502,12 @@ CommandBlockMorph.prototype.nextBlock = function (block) {
|
|||
if (nb) {
|
||||
block.bottomBlock().nextBlock(nb);
|
||||
}
|
||||
this.fixLayout();
|
||||
block.setPosition(
|
||||
new Point(
|
||||
this.left(),
|
||||
this.bottom() - (this.corner)
|
||||
)
|
||||
);
|
||||
if (affected) {
|
||||
affected.fixLayout();
|
||||
}
|
||||
|
@ -4132,7 +4153,7 @@ function HatBlockMorph() {
|
|||
}
|
||||
|
||||
HatBlockMorph.prototype.init = function () {
|
||||
HatBlockMorph.uber.init.call(this);
|
||||
HatBlockMorph.uber.init.call(this, true); // silently
|
||||
this.setExtent(new Point(300, 150));
|
||||
};
|
||||
|
||||
|
@ -4309,10 +4330,10 @@ function ReporterBlockMorph(isPredicate) {
|
|||
this.init(isPredicate);
|
||||
}
|
||||
|
||||
ReporterBlockMorph.prototype.init = function (isPredicate) {
|
||||
ReporterBlockMorph.uber.init.call(this);
|
||||
ReporterBlockMorph.prototype.init = function (isPredicate, silently) {
|
||||
ReporterBlockMorph.uber.init.call(this, silently);
|
||||
this.isPredicate = isPredicate || false;
|
||||
this.setExtent(new Point(200, 80));
|
||||
this.setExtent(new Point(200, 80), silently);
|
||||
};
|
||||
|
||||
// ReporterBlockMorph drag & drop:
|
||||
|
@ -4320,6 +4341,7 @@ ReporterBlockMorph.prototype.init = function (isPredicate) {
|
|||
ReporterBlockMorph.prototype.snap = function (hand) {
|
||||
// passing the hand is optional (for when blocks are dragged & dropped)
|
||||
var scripts = this.parent,
|
||||
nb,
|
||||
target;
|
||||
|
||||
if (!scripts instanceof ScriptsMorph) {
|
||||
|
@ -4336,6 +4358,16 @@ ReporterBlockMorph.prototype.snap = function (hand) {
|
|||
if (target instanceof MultiArgMorph) {
|
||||
scripts.lastPreservedBlocks = target.inputs();
|
||||
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);
|
||||
if (this.snapSound) {
|
||||
|
@ -4359,6 +4391,7 @@ ReporterBlockMorph.prototype.prepareToBeGrabbed = function (handMorph) {
|
|||
this.setPosition(oldPos);
|
||||
}
|
||||
ReporterBlockMorph.uber.prepareToBeGrabbed.call(this, handMorph);
|
||||
this.alpha = 0.85;
|
||||
};
|
||||
|
||||
// ReporterBlockMorph enumerating
|
||||
|
@ -4420,7 +4453,7 @@ ReporterBlockMorph.prototype.mouseClickLeft = function (pos) {
|
|||
this.parent.parent.parent instanceof RingMorph;
|
||||
new DialogBoxMorph(
|
||||
this,
|
||||
this.setSpec,
|
||||
this.userSetSpec,
|
||||
this
|
||||
).prompt(
|
||||
isRing ? "Input name" : "Script variable name",
|
||||
|
@ -4941,9 +4974,7 @@ RingMorph.prototype.dataType = function () {
|
|||
RingMorph.prototype.fixBlockColor = function (nearest, isForced) {
|
||||
var slot = this.parts()[0];
|
||||
RingMorph.uber.fixBlockColor.call(this, nearest, isForced);
|
||||
if (slot instanceof RingCommandSlotMorph) {
|
||||
slot.fixLayout();
|
||||
}
|
||||
slot.fixLayout();
|
||||
};
|
||||
|
||||
// ScriptsMorph ////////////////////////////////////////////////////////
|
||||
|
@ -4994,6 +5025,7 @@ ScriptsMorph.prototype.init = function (owner) {
|
|||
|
||||
ScriptsMorph.uber.init.call(this);
|
||||
this.setColor(new Color(70, 70, 70));
|
||||
this.noticesTransparentClick = true;
|
||||
};
|
||||
|
||||
// ScriptsMorph deep copying:
|
||||
|
@ -5187,14 +5219,15 @@ ScriptsMorph.prototype.closestInput = function (reporter, hand) {
|
|||
all,
|
||||
function (input) {
|
||||
return (input instanceof InputSlotMorph
|
||||
|| input instanceof ArgMorph
|
||||
|| (input instanceof ArgMorph
|
||||
&& !(input instanceof CommandSlotMorph)
|
||||
&& !(input instanceof MultiArgMorph))
|
||||
|| (input instanceof RingMorph
|
||||
&& !input.contents())
|
||||
|| input.isEmptySlot())
|
||||
&& !input.isLocked()
|
||||
&& input.bounds.containsPoint(handPos)
|
||||
&& !contains(blackList, input)
|
||||
&& touchingVariadicArrowsIfAny(input, handPos);
|
||||
&& !contains(blackList, input);
|
||||
}
|
||||
);
|
||||
if (target) {
|
||||
|
@ -5562,12 +5595,12 @@ function ArgMorph(type) {
|
|||
this.init(type);
|
||||
}
|
||||
|
||||
ArgMorph.prototype.init = function (type) {
|
||||
ArgMorph.prototype.init = function (type, silently) {
|
||||
this.type = type || null;
|
||||
this.isHole = false;
|
||||
ArgMorph.uber.init.call(this);
|
||||
ArgMorph.uber.init.call(this, silently);
|
||||
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
|
||||
|
@ -5675,10 +5708,13 @@ function CommandSlotMorph() {
|
|||
this.init();
|
||||
}
|
||||
|
||||
CommandSlotMorph.prototype.init = function () {
|
||||
CommandSlotMorph.uber.init.call(this);
|
||||
CommandSlotMorph.prototype.init = function (silently) {
|
||||
CommandSlotMorph.uber.init.call(this, null, true); // silently
|
||||
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 () {
|
||||
|
@ -6130,8 +6166,8 @@ function RingCommandSlotMorph() {
|
|||
this.init();
|
||||
}
|
||||
|
||||
RingCommandSlotMorph.prototype.init = function () {
|
||||
RingCommandSlotMorph.uber.init.call(this);
|
||||
RingCommandSlotMorph.prototype.init = function (silently) {
|
||||
RingCommandSlotMorph.uber.init.call(this, silently);
|
||||
this.isHole = true;
|
||||
this.noticesTransparentClick = true;
|
||||
this.color = new Color(0, 17, 173);
|
||||
|
@ -6281,11 +6317,15 @@ function CSlotMorph() {
|
|||
this.init();
|
||||
}
|
||||
|
||||
CSlotMorph.prototype.init = function () {
|
||||
CommandSlotMorph.uber.init.call(this);
|
||||
CSlotMorph.prototype.init = function (silently) {
|
||||
CommandSlotMorph.uber.init.call(this, null, true); // silently
|
||||
this.isHole = true;
|
||||
this.isLambda = false; // see Process.prototype.evaluateInput
|
||||
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 () {
|
||||
|
@ -6733,7 +6773,7 @@ InputSlotMorph.prototype.init = function (
|
|||
this.minWidth = 0; // can be chaged for text-type inputs ("landscape")
|
||||
this.constant = null;
|
||||
|
||||
InputSlotMorph.uber.init.call(this);
|
||||
InputSlotMorph.uber.init.call(this, null, true);
|
||||
this.color = new Color(255, 255, 255);
|
||||
this.add(contents);
|
||||
this.add(arrow);
|
||||
|
@ -7886,7 +7926,7 @@ ArrowMorph.prototype.init = function (direction, size, padding, color) {
|
|||
this.size = size || ((size === 0) ? 0 : 50);
|
||||
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.setExtent(new Point(this.size, this.size));
|
||||
};
|
||||
|
@ -7975,7 +8015,7 @@ TextSlotMorph.prototype.init = function (
|
|||
this.minWidth = 0; // can be chaged for text-type inputs ("landscape")
|
||||
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.add(contents);
|
||||
this.add(arrow);
|
||||
|
@ -8096,7 +8136,7 @@ SymbolMorph.prototype.init = function (
|
|||
this.shadowOffset = shadowOffset || new Point(0, 0);
|
||||
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.drawNew();
|
||||
};
|
||||
|
@ -9328,7 +9368,7 @@ function ColorSlotMorph(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));
|
||||
};
|
||||
|
||||
|
@ -9506,7 +9546,7 @@ MultiArgMorph.prototype.init = function (
|
|||
this.shadowOffset = shadowOffset || null;
|
||||
|
||||
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
|
||||
this.alpha = isTransparent === false ? 1 : 0;
|
||||
|
@ -9894,7 +9934,7 @@ ArgLabelMorph.prototype.init = function (argMorph, labelTxt) {
|
|||
var label;
|
||||
|
||||
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
|
||||
|
||||
|
@ -10020,14 +10060,17 @@ function FunctionSlotMorph(isPredicate) {
|
|||
this.init(isPredicate);
|
||||
}
|
||||
|
||||
FunctionSlotMorph.prototype.init = function (isPredicate) {
|
||||
FunctionSlotMorph.uber.init.call(this);
|
||||
FunctionSlotMorph.prototype.init = function (isPredicate, silently) {
|
||||
FunctionSlotMorph.uber.init.call(this, null, true); // silently
|
||||
this.isPredicate = isPredicate || false;
|
||||
this.color = this.rfColor;
|
||||
this.setExtent(new Point(
|
||||
(this.fontSize + this.edge * 2) * 2,
|
||||
this.fontSize + this.edge * 2
|
||||
));
|
||||
this.setExtent(
|
||||
new Point(
|
||||
(this.fontSize + this.edge * 2) * 2,
|
||||
this.fontSize + this.edge * 2
|
||||
),
|
||||
silently
|
||||
);
|
||||
};
|
||||
|
||||
FunctionSlotMorph.prototype.getSpec = function () {
|
||||
|
@ -10402,7 +10445,7 @@ function ReporterSlotMorph(isPredicate) {
|
|||
}
|
||||
|
||||
ReporterSlotMorph.prototype.init = function (isPredicate) {
|
||||
ReporterSlotMorph.uber.init.call(this, isPredicate);
|
||||
ReporterSlotMorph.uber.init.call(this, isPredicate, true);
|
||||
this.add(this.emptySlot());
|
||||
this.fixLayout();
|
||||
};
|
||||
|
@ -10493,7 +10536,7 @@ function RingReporterSlotMorph(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.contrast = RingMorph.prototype.contrast;
|
||||
this.isHole = true;
|
||||
|
|
61
byob.js
61
byob.js
|
@ -108,7 +108,7 @@ SymbolMorph, isNil, CursorMorph*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.byob = '2015-October-07';
|
||||
modules.byob = '2015-November-16';
|
||||
|
||||
// Declarations
|
||||
|
||||
|
@ -148,6 +148,7 @@ function CustomBlockDefinition(spec, receiver) {
|
|||
|
||||
// don't serialize (not needed for functionality):
|
||||
this.receiver = receiver || null; // for serialization only (pointer)
|
||||
this.editorDimensions = null; // a rectangle, last bounds of the editor
|
||||
}
|
||||
|
||||
// CustomBlockDefinition instantiating blocks
|
||||
|
@ -405,9 +406,7 @@ function CustomCommandBlockMorph(definition, isProto) {
|
|||
CustomCommandBlockMorph.prototype.init = function (definition, isProto) {
|
||||
this.definition = definition; // mandatory
|
||||
this.isPrototype = isProto || false; // optional
|
||||
|
||||
CustomCommandBlockMorph.uber.init.call(this);
|
||||
|
||||
CustomCommandBlockMorph.uber.init.call(this, true); // silently
|
||||
this.category = definition.category;
|
||||
this.selector = 'evaluateCustomBlock';
|
||||
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,
|
||||
newSpec = this.isPrototype ?
|
||||
def.spec : def.blockSpec(),
|
||||
|
@ -429,7 +428,7 @@ CustomCommandBlockMorph.prototype.refresh = function () {
|
|||
} else {
|
||||
this.fixBlockColor();
|
||||
}
|
||||
this.setSpec(newSpec);
|
||||
this.setSpec(newSpec, silently);
|
||||
this.fixLabelColor();
|
||||
this.restoreInputs(oldInputs);
|
||||
} else { // update all input slots' drop-downs
|
||||
|
@ -671,7 +670,7 @@ CustomCommandBlockMorph.prototype.mouseClickLeft = function () {
|
|||
};
|
||||
|
||||
CustomCommandBlockMorph.prototype.edit = function () {
|
||||
var myself = this, block, hat;
|
||||
var myself = this, editor, block, hat;
|
||||
|
||||
if (this.isPrototype) {
|
||||
block = this.definition.blockInstance();
|
||||
|
@ -696,7 +695,11 @@ CustomCommandBlockMorph.prototype.edit = function () {
|
|||
myself.isInUse()
|
||||
);
|
||||
} 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,12 +766,16 @@ CustomCommandBlockMorph.prototype.userMenu = function () {
|
|||
menu.addItem(
|
||||
"script pic...",
|
||||
function () {
|
||||
<<<<<<< HEAD
|
||||
var ide = this.parentThatIsA(IDE_Morph);
|
||||
ide.saveCanvasAs(
|
||||
this.topBlock().fullImage(),
|
||||
this.projectName + ' ' + localize('script pic'),
|
||||
true // request opening a new window
|
||||
);
|
||||
=======
|
||||
window.open(this.topBlock().scriptPic().toDataURL());
|
||||
>>>>>>> master
|
||||
},
|
||||
'open a new window\nwith a picture of this script'
|
||||
);
|
||||
|
@ -943,7 +950,7 @@ CustomReporterBlockMorph.prototype.init = function (
|
|||
this.definition = definition; // mandatory
|
||||
this.isPrototype = isProto || false; // optional
|
||||
|
||||
CustomReporterBlockMorph.uber.init.call(this, isPredicate);
|
||||
CustomReporterBlockMorph.uber.init.call(this, isPredicate, true); // sil.
|
||||
|
||||
this.category = definition.category;
|
||||
this.selector = 'evaluateCustomBlock';
|
||||
|
@ -953,7 +960,7 @@ CustomReporterBlockMorph.prototype.init = function (
|
|||
};
|
||||
|
||||
CustomReporterBlockMorph.prototype.refresh = function () {
|
||||
CustomCommandBlockMorph.prototype.refresh.call(this);
|
||||
CustomCommandBlockMorph.prototype.refresh.call(this, true);
|
||||
if (!this.isPrototype) {
|
||||
this.isPredicate = (this.definition.type === 'predicate');
|
||||
}
|
||||
|
@ -1705,6 +1712,7 @@ BlockEditorMorph.prototype.init = function (definition, target) {
|
|||
|
||||
scripts.add(proto);
|
||||
proto.fixBlockColor(null, true);
|
||||
proto.drawNew();
|
||||
|
||||
this.definition.scripts.forEach(function (element) {
|
||||
block = element.fullCopy();
|
||||
|
@ -1733,7 +1741,7 @@ BlockEditorMorph.prototype.init = function (definition, target) {
|
|||
this.addButton('updateDefinition', 'Apply');
|
||||
this.addButton('cancel', 'Cancel');
|
||||
|
||||
this.setExtent(new Point(375, 300));
|
||||
this.setExtent(new Point(375, 300)); // normal initial extent
|
||||
this.fixLayout();
|
||||
proto.children[0].fixLayout();
|
||||
scripts.fixMultiArgs();
|
||||
|
@ -1744,6 +1752,7 @@ BlockEditorMorph.prototype.popUp = function () {
|
|||
|
||||
if (world) {
|
||||
BlockEditorMorph.uber.popUp.call(this, world);
|
||||
this.setInitialDimensions();
|
||||
this.handle = new HandleMorph(
|
||||
this,
|
||||
280,
|
||||
|
@ -1751,9 +1760,18 @@ BlockEditorMorph.prototype.popUp = function () {
|
|||
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.prototype.accept = function (origin) {
|
||||
|
@ -1858,6 +1876,7 @@ BlockEditorMorph.prototype.updateDefinition = function () {
|
|||
this.definition.spec = this.prototypeSpec();
|
||||
this.definition.declarations = this.prototypeSlots();
|
||||
this.definition.scripts = [];
|
||||
this.definition.editorDimensions = this.bounds.copy();
|
||||
|
||||
this.body.contents.children.forEach(function (morph) {
|
||||
if (morph instanceof PrototypeHatBlockMorph) {
|
||||
|
@ -1934,6 +1953,26 @@ BlockEditorMorph.prototype.prototypeSlots = function () {
|
|||
|
||||
// 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 () {
|
||||
var th = fontHeight(this.titleFontSize) + this.titlePadding * 2;
|
||||
|
||||
|
|
288
gui.js
288
gui.js
|
@ -71,7 +71,7 @@ BlockRemovalDialogMorph, saveAs*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.gui = '2015-October-07';
|
||||
modules.gui = '2015-November-16';
|
||||
|
||||
// Declarations
|
||||
|
||||
|
@ -85,16 +85,6 @@ var SoundIconMorph;
|
|||
var JukeboxMorph;
|
||||
var StageHandleMorph;
|
||||
|
||||
// Get the full url without "snap.html"
|
||||
var baseURL = (function getPath(location) {
|
||||
var origin, path, slash;
|
||||
path = location.pathname; // starts with a /
|
||||
origin = location.origin; // has no trailing /
|
||||
slash = path.lastIndexOf('/');
|
||||
path = path.slice(0, slash + 1); // keep a trailing /
|
||||
return origin + path;
|
||||
}(window.location));
|
||||
|
||||
|
||||
// IDE_Morph ///////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -2012,6 +2002,7 @@ IDE_Morph.prototype.userMenu = function () {
|
|||
|
||||
IDE_Morph.prototype.snapMenu = function () {
|
||||
var menu,
|
||||
myself = this,
|
||||
world = this.world();
|
||||
|
||||
menu = new MenuMorph(this);
|
||||
|
@ -2020,7 +2011,8 @@ IDE_Morph.prototype.snapMenu = function () {
|
|||
menu.addItem(
|
||||
'Reference manual',
|
||||
function () {
|
||||
window.open('help/SnapManual.pdf', 'SnapReferenceManual');
|
||||
var url = myself.resourceURL('help', 'SnapManual.pdf');
|
||||
window.open(url, 'SnapReferenceManual');
|
||||
}
|
||||
);
|
||||
menu.addItem(
|
||||
|
@ -2227,6 +2219,15 @@ IDE_Morph.prototype.settingsMenu = function () {
|
|||
'Stage size...',
|
||||
'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();
|
||||
addPreference(
|
||||
'Blurred shadows',
|
||||
|
@ -2469,6 +2470,27 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
'Costumes' : 'Backgrounds',
|
||||
shiftClicked = (world.currentKey === 16);
|
||||
|
||||
// Utility for creating Costumes, etc menus.
|
||||
// loadFunction takes in two parameters: a file URL, and a canonical name
|
||||
function createMediaMenu(mediaType, loadFunction) {
|
||||
return function () {
|
||||
var names = this.getMediaList(mediaType),
|
||||
mediaMenu = new MenuMorph(
|
||||
myself,
|
||||
localize('Import') + ' ' + localize(mediaType)
|
||||
);
|
||||
|
||||
names.forEach(function (item) {
|
||||
mediaMenu.addItem(
|
||||
item.name,
|
||||
function () {loadFunction(item.file, item.name); },
|
||||
item.help
|
||||
);
|
||||
});
|
||||
mediaMenu.popup(world, pos);
|
||||
};
|
||||
}
|
||||
|
||||
menu = new MenuMorph(this);
|
||||
menu.addItem('Project notes...', 'editProjectNotes');
|
||||
menu.addLine();
|
||||
|
@ -2589,9 +2611,7 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
'Import tools',
|
||||
function () {
|
||||
myself.droppedText(
|
||||
myself.getURLsbeOrRelative(
|
||||
'tools.xml'
|
||||
),
|
||||
myself.getURL('tools.xml'),
|
||||
'tools'
|
||||
);
|
||||
},
|
||||
|
@ -2599,46 +2619,22 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
);
|
||||
menu.addItem(
|
||||
'Libraries...',
|
||||
function () {
|
||||
// read a list of libraries from an external file,
|
||||
var libMenu = new MenuMorph(this, 'Import library'),
|
||||
libUrl = baseURL + 'libraries/' + 'LIBRARIES';
|
||||
|
||||
function loadLib(name) {
|
||||
var url = baseURL + 'libraries/' + name + '.xml';
|
||||
createMediaMenu(
|
||||
'libraries',
|
||||
function loadLib(file, name) {
|
||||
var url = myself.resourceURL('libraries', file);
|
||||
myself.droppedText(myself.getURL(url), name);
|
||||
}
|
||||
|
||||
myself.getURL(libUrl).split('\n').forEach(function (line) {
|
||||
if (line.length > 0) {
|
||||
libMenu.addItem(
|
||||
line.substring(line.indexOf('\t') + 1),
|
||||
function () {
|
||||
loadLib(
|
||||
line.substring(0, line.indexOf('\t'))
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
libMenu.popup(world, pos);
|
||||
},
|
||||
),
|
||||
'Select categories of additional blocks to add to this project.'
|
||||
);
|
||||
|
||||
menu.addItem(
|
||||
localize(graphicsName) + '...',
|
||||
function () {
|
||||
var dir = graphicsName,
|
||||
names = myself.getCostumesList(dir),
|
||||
libMenu = new MenuMorph(
|
||||
myself,
|
||||
localize('Import') + ' ' + localize(dir)
|
||||
);
|
||||
|
||||
function loadCostume(name) {
|
||||
var url = dir + '/' + name,
|
||||
createMediaMenu(
|
||||
graphicsName,
|
||||
function loadCostume(file, name) {
|
||||
var url = myself.resourceURL(graphicsName, file),
|
||||
img = new Image();
|
||||
img.onload = function () {
|
||||
var canvas = newCanvas(new Point(img.width, img.height));
|
||||
|
@ -2647,74 +2643,84 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
};
|
||||
img.src = url;
|
||||
}
|
||||
|
||||
names.forEach(function (line) {
|
||||
if (line.length > 0) {
|
||||
libMenu.addItem(
|
||||
line,
|
||||
function () {loadCostume(line); }
|
||||
);
|
||||
}
|
||||
});
|
||||
libMenu.popup(world, pos);
|
||||
},
|
||||
),
|
||||
'Select a costume from the media library'
|
||||
);
|
||||
menu.addItem(
|
||||
localize('Sounds') + '...',
|
||||
function () {
|
||||
var names = this.getCostumesList('Sounds'),
|
||||
libMenu = new MenuMorph(this, 'Import sound');
|
||||
|
||||
function loadSound(name) {
|
||||
var url = 'Sounds/' + name,
|
||||
createMediaMenu(
|
||||
'Sounds',
|
||||
function loadSound(file, name) {
|
||||
var url = myself.resourceURL('Sounds', file),
|
||||
audio = new Audio();
|
||||
audio.src = url;
|
||||
audio.load();
|
||||
myself.droppedAudio(audio, name);
|
||||
}
|
||||
|
||||
names.forEach(function (line) {
|
||||
if (line.length > 0) {
|
||||
libMenu.addItem(
|
||||
line,
|
||||
function () {loadSound(line); }
|
||||
);
|
||||
}
|
||||
});
|
||||
libMenu.popup(world, pos);
|
||||
},
|
||||
),
|
||||
'Select a sound from the media library'
|
||||
);
|
||||
|
||||
menu.popup(world, pos);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.getCostumesList = function (dirname) {
|
||||
var dir,
|
||||
costumes = [];
|
||||
|
||||
dir = this.getURL(dirname);
|
||||
dir.split('\n').forEach(
|
||||
function (line) {
|
||||
var startIdx = line.search(new RegExp('href="[^./?].*"')),
|
||||
endIdx,
|
||||
name;
|
||||
|
||||
if (startIdx > 0) {
|
||||
name = line.substring(startIdx + 6);
|
||||
endIdx = name.search(new RegExp('"'));
|
||||
name = name.substring(0, endIdx);
|
||||
costumes.push(name);
|
||||
}
|
||||
}
|
||||
);
|
||||
costumes.sort(function (x, y) {
|
||||
return x < y ? -1 : 1;
|
||||
});
|
||||
return costumes;
|
||||
IDE_Morph.prototype.resourceURL = function (folder, file) {
|
||||
// Give a path a file in subfolders.
|
||||
// Method can be easily overridden if running in a custom location.
|
||||
return folder + '/' + file;
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.getMediaList = function (dirname) {
|
||||
// Return a list of files in a directory based on the contents file
|
||||
var url, data;
|
||||
|
||||
url = this.resourceURL(dirname, dirname.toUpperCase());
|
||||
data = this.parseResourceFile(this.getURL(url));
|
||||
|
||||
data.sort(function (x, y) {
|
||||
return x.name.toLowerCase() < y.name.toLowerCase() ? -1 : 1;
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.parseResourceFile = function (text) {
|
||||
// A Resource File lists all the files that could be loaded in a submenu
|
||||
// Examples are libraries/LIBRARIES, Costumes/COSTUMES, etc
|
||||
// A File is very simple:
|
||||
// A "//" starts a comment line, that is ignored.
|
||||
// All lines have 3 fields: file-name, Display Name, Help Text
|
||||
// These fields are delimited by tabs.
|
||||
var parts,
|
||||
items = [],
|
||||
comment = '//',
|
||||
delimter = '\t';
|
||||
|
||||
text = text.split(/\n|\r\n/);
|
||||
|
||||
text.map(function (line) {
|
||||
return line.trim();
|
||||
}).filter(function (line) {
|
||||
return line.length > 0 && line[0] !== comment;
|
||||
}).forEach(function (line) {
|
||||
parts = line.split(delimter);
|
||||
parts = parts.map(function (str) { return str.trim(); });
|
||||
|
||||
if (parts.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
items.push({
|
||||
file: parts[0],
|
||||
name: parts[1],
|
||||
help: parts.length > 2 ? parts[2] : ''
|
||||
});
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
|
||||
// IDE_Morph menu actions
|
||||
|
||||
IDE_Morph.prototype.aboutSnap = function () {
|
||||
|
@ -2722,7 +2728,7 @@ IDE_Morph.prototype.aboutSnap = function () {
|
|||
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
|
||||
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 '
|
||||
+ 'Brian Harvey\n'
|
||||
+ 'jens@moenig.org, bh@cs.berkeley.edu\n\n'
|
||||
|
@ -4179,6 +4185,7 @@ IDE_Morph.prototype.userSetBlocksScale = function () {
|
|||
block.drawNew();
|
||||
block.setSpec(block.blockSpec);
|
||||
});
|
||||
scrpt.changed();
|
||||
};
|
||||
|
||||
new DialogBoxMorph(
|
||||
|
@ -4288,6 +4295,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.prototype.initializeCloud = function () {
|
||||
|
@ -4678,7 +4708,7 @@ IDE_Morph.prototype.setCloudURL = function () {
|
|||
);
|
||||
};
|
||||
|
||||
// IDE_Morph synchronous Http data fetching
|
||||
// IDE_Morph synchronous HTTP data fetching
|
||||
|
||||
IDE_Morph.prototype.getURL = function (url) {
|
||||
var request = new XMLHttpRequest(),
|
||||
|
@ -4696,22 +4726,6 @@ IDE_Morph.prototype.getURL = function (url) {
|
|||
}
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.getURLsbeOrRelative = function (url) {
|
||||
var request = new XMLHttpRequest(),
|
||||
myself = this;
|
||||
try {
|
||||
request.open('GET', baseURL + url, false);
|
||||
request.send();
|
||||
if (request.status === 200) {
|
||||
return request.responseText;
|
||||
}
|
||||
return myself.getURL(url);
|
||||
} catch (err) {
|
||||
myself.showMessage(err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// IDE_Morph user dialog shortcuts
|
||||
|
||||
IDE_Morph.prototype.showMessage = function (message, secs) {
|
||||
|
@ -5133,7 +5147,7 @@ ProjectDialogMorph.prototype.setSource = function (source) {
|
|||
}
|
||||
myself.edit();
|
||||
};
|
||||
} else { // 'examples', 'cloud' is initialized elsewhere
|
||||
} else { // 'examples'; 'cloud' is initialized elsewhere
|
||||
this.listField.action = function (item) {
|
||||
var src, xml;
|
||||
if (item === undefined) {return; }
|
||||
|
@ -5141,7 +5155,7 @@ ProjectDialogMorph.prototype.setSource = function (source) {
|
|||
myself.nameField.setContents(item.name || '');
|
||||
}
|
||||
src = myself.ide.getURL(
|
||||
baseURL + 'Examples/' + item.name + '.xml'
|
||||
myself.ide.resourceURL('Examples', item.file)
|
||||
);
|
||||
|
||||
xml = myself.ide.serializer.parse(src);
|
||||
|
@ -5193,33 +5207,7 @@ ProjectDialogMorph.prototype.getLocalProjectList = function () {
|
|||
};
|
||||
|
||||
ProjectDialogMorph.prototype.getExamplesProjectList = function () {
|
||||
var dir,
|
||||
projects = [];
|
||||
//alert(baseURL);
|
||||
|
||||
dir = this.ide.getURL(baseURL + 'Examples/');
|
||||
dir.split('\n').forEach(
|
||||
function (line) {
|
||||
var startIdx = line.search(new RegExp('href=".*xml"')),
|
||||
endIdx,
|
||||
name,
|
||||
dta;
|
||||
if (startIdx > 0) {
|
||||
endIdx = line.search(new RegExp('.xml'));
|
||||
name = line.substring(startIdx + 6, endIdx);
|
||||
dta = {
|
||||
name: name,
|
||||
thumb: null,
|
||||
notes: null
|
||||
};
|
||||
projects.push(dta);
|
||||
}
|
||||
}
|
||||
);
|
||||
projects = projects.sort(function (x, y) {
|
||||
return x.name.toLowerCase() < y.name.toLowerCase() ? -1 : 1;
|
||||
});
|
||||
return projects;
|
||||
return this.ide.getMediaList('Examples');
|
||||
};
|
||||
|
||||
ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
|
||||
|
@ -5316,7 +5304,8 @@ ProjectDialogMorph.prototype.openProject = function () {
|
|||
if (this.source === 'cloud') {
|
||||
this.openCloudProject(proj);
|
||||
} else if (this.source === 'examples') {
|
||||
src = this.ide.getURL(baseURL + 'Examples/' + proj.name + '.xml');
|
||||
// Note "file" is a property of the parseResourceFile function.
|
||||
src = this.ide.getURL(this.ide.resourceURL('Examples', proj.file));
|
||||
this.ide.openProjectString(src);
|
||||
this.destroy();
|
||||
} else { // 'local'
|
||||
|
@ -6009,6 +5998,7 @@ SpriteIconMorph.prototype.prepareToBeGrabbed = function () {
|
|||
var ide = this.parentThatIsA(IDE_Morph),
|
||||
idx;
|
||||
this.mouseClickLeft(); // select me
|
||||
this.alpha = 0.85;
|
||||
if (ide) {
|
||||
idx = ide.sprites.asArray().indexOf(this.object);
|
||||
ide.sprites.remove(idx + 1);
|
||||
|
@ -6017,6 +6007,10 @@ SpriteIconMorph.prototype.prepareToBeGrabbed = function () {
|
|||
}
|
||||
};
|
||||
|
||||
SpriteIconMorph.prototype.justDropped = function () {
|
||||
this.alpha = 1;
|
||||
};
|
||||
|
||||
SpriteIconMorph.prototype.wantsDropOf = function (morph) {
|
||||
// allow scripts & media to be copied from one sprite to another
|
||||
// by drag & drop
|
||||
|
|
80
history.txt
80
history.txt
|
@ -2603,3 +2603,83 @@ ______
|
|||
* Store: Fix deserialization support for projects using inheritance
|
||||
* German translation update
|
||||
|
||||
|
||||
++++++++++++++++++++++++++
|
||||
new stuff - bulk of 151116
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
151030
|
||||
------
|
||||
* Blocks: Tweak precision of rendering of transparent “holes”
|
||||
* updated Czech translation
|
||||
* 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
|
||||
++++++++++++++++++++++++++
|
||||
|
||||
151116 community contributions
|
||||
------
|
||||
* new Bulgarian and Romanian translations contributed!
|
||||
* fix for IE backspace and tab errors contributed!
|
||||
* better resource loading mechanism contributed!
|
||||
|
||||
|
||||
|
|
16
index.html
16
index.html
|
@ -1,7 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta HTTP-EQUIV="REFRESH" content="0.1; url=snap.html">
|
||||
</head>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
if (window.location) {
|
||||
window.location = 'snap.html' + window.location.hash;
|
||||
}
|
||||
</script>
|
||||
<meta HTTP-EQUIV="REFRESH" content="0.1; url=snap.html">
|
||||
<title>Redirecting to Snap!</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>If you are no automatically redirected to Snap<i>!</i>,
|
||||
<a href="snap.html">please click here.</a> </p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -185,7 +185,7 @@ SnapTranslator.dict.cs = {
|
|||
'translator_e-mail':
|
||||
'info@iguru.eu, jan.tomsa.1976@gmail.com', // optional
|
||||
'last_changed':
|
||||
'2015-09-22', // this, too, will appear in the Translators tab
|
||||
'2015-11-16', // this, too, will appear in the Translators tab
|
||||
|
||||
// GUI
|
||||
// control bar:
|
||||
|
@ -451,19 +451,23 @@ SnapTranslator.dict.cs = {
|
|||
'repeat %n %c':
|
||||
'opakuj %n krát %c',
|
||||
'repeat until %b %c':
|
||||
'opakuj dokud %b %c',
|
||||
'opakuj dokud nenastane %b %c',
|
||||
'if %b %c':
|
||||
'když %b %c',
|
||||
'if %b %c else %c':
|
||||
'když %b %c jinak %c',
|
||||
'report %s':
|
||||
'vrátit %s',
|
||||
'stop block':
|
||||
'zastav blok',
|
||||
'stop script':
|
||||
'zastav skript',
|
||||
'stop all %stop':
|
||||
'zastav vše %stop',
|
||||
'stop %stopChoices':
|
||||
'stop %stopChoices',
|
||||
'all':
|
||||
'vše',
|
||||
'this script':
|
||||
'tento skript',
|
||||
'this block':
|
||||
'tento blok',
|
||||
'stop %stopOthersChoices':
|
||||
'stop %stopOthersChoices',
|
||||
'run %cmdRing %inputs':
|
||||
'spusť %cmdRing %inputs',
|
||||
'launch %cmdRing %inputs':
|
||||
|
@ -471,9 +475,9 @@ SnapTranslator.dict.cs = {
|
|||
'call %repRing %inputs':
|
||||
'zavolat %repRing %inputs',
|
||||
'run %cmdRing w/continuation':
|
||||
'spustit %cmdRing s podmínkou',
|
||||
'spustit %cmdRing s pokračováním',
|
||||
'call %cmdRing w/continuation':
|
||||
'zavolat %cmdRing s podmínkou',
|
||||
'zavolat %cmdRing s pokračováním',
|
||||
'warp %c':
|
||||
'obal %c',
|
||||
'when I start as a clone':
|
||||
|
@ -487,9 +491,9 @@ SnapTranslator.dict.cs = {
|
|||
'all but this script':
|
||||
'vše kromě tohoto skriptu',
|
||||
'other scripts in sprite':
|
||||
'ostatní skripty v tomto objektu',
|
||||
'ostatní skripty tohoto objektu',
|
||||
'pause all %pause':
|
||||
'zastavit všechny %pause',
|
||||
'zastavit vše %pause',
|
||||
|
||||
|
||||
// sensing:
|
||||
|
@ -593,6 +597,8 @@ SnapTranslator.dict.cs = {
|
|||
'Vytvoř proměnnou',
|
||||
'Variable name':
|
||||
'Jméno proměnné',
|
||||
'Script variable name':
|
||||
'Jméno skriptové proměnné',
|
||||
'Delete a variable':
|
||||
'Smaž proměnnou',
|
||||
|
||||
|
@ -605,19 +611,19 @@ SnapTranslator.dict.cs = {
|
|||
'hide variable %var':
|
||||
'schovej proměnnou %var',
|
||||
'script variables %scriptVars':
|
||||
'Vytvoř seznam %scriptVars',
|
||||
'Vytvoř skriptové proměnné %scriptVars',
|
||||
|
||||
// lists:
|
||||
'list %exp':
|
||||
'seznam %exp',
|
||||
'%s in front of %l':
|
||||
'%s v popředí z %l',
|
||||
'%s na začátek %l',
|
||||
'item %idx of %l':
|
||||
'položka %idx ze %l',
|
||||
'položka %idx z %l',
|
||||
'all but first of %l':
|
||||
'vše kromě první položky z %l',
|
||||
'length of %l':
|
||||
'velikost %l',
|
||||
'délka %l',
|
||||
'%l contains %s':
|
||||
'%l obsahuje %s',
|
||||
'thing':
|
||||
|
@ -627,9 +633,9 @@ SnapTranslator.dict.cs = {
|
|||
'delete %ida of %l':
|
||||
'smazat %ida z %l',
|
||||
'insert %s at %idx of %l':
|
||||
'vložit %s na %idx v %l',
|
||||
'vložit %s na %idx pozici v %l',
|
||||
'replace item %idx of %l with %s':
|
||||
'nahraď prvek %idx v %l za %s',
|
||||
'nahraď položku %idx v %l hodnotou %s',
|
||||
|
||||
// other
|
||||
'Make a block':
|
||||
|
@ -1192,8 +1198,17 @@ SnapTranslator.dict.cs = {
|
|||
'želva',
|
||||
|
||||
// graphical effects
|
||||
'brightness':
|
||||
'jas',
|
||||
'ghost':
|
||||
'duch',
|
||||
'negative':
|
||||
'negativ',
|
||||
'comic':
|
||||
'moaré',
|
||||
'confetti':
|
||||
'barevnost',
|
||||
|
||||
|
||||
// keys
|
||||
'space':
|
||||
|
@ -1286,6 +1301,10 @@ SnapTranslator.dict.cs = {
|
|||
// math functions
|
||||
'abs':
|
||||
'absolutní hodnota',
|
||||
'ceiling':
|
||||
'zaokrouhlit nahoru',
|
||||
'floor':
|
||||
'zaokrouhlit dolů',
|
||||
'sqrt':
|
||||
'odmocnina',
|
||||
'sin':
|
||||
|
@ -1325,5 +1344,5 @@ SnapTranslator.dict.cs = {
|
|||
'last':
|
||||
'poslední',
|
||||
'any':
|
||||
'jakýkoliv'
|
||||
'kterákoli'
|
||||
};
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -1,7 +1,7 @@
|
|||
iteration-composition Iteration, composition
|
||||
list-utilities List utilities
|
||||
stream-tools Streams (lazy lists)
|
||||
variadic-reporters Variadic reporters
|
||||
word-sentence Words, sentences
|
||||
cases Multi-branched conditional (switch)
|
||||
leap-library LEAP Motion controller
|
||||
iteration-composition.xml Iteration, composition
|
||||
list-utilities.xml List utilities
|
||||
stream-tools.xml Streams (lazy lists)
|
||||
variadic-reporters.xml Variadic reporters
|
||||
word-sentence.xml Words, sentences
|
||||
cases.xml Multi-branched conditional (switch)
|
||||
leap-library.xml LEAP Motion controller
|
||||
|
|
13
lists.js
13
lists.js
|
@ -61,7 +61,7 @@ PushButtonMorph, SyntaxElementMorph, Color, Point, WatcherMorph,
|
|||
StringMorph, SpriteMorph, ScrollFrameMorph, CellMorph, ArrowMorph,
|
||||
MenuMorph, snapEquals, Morph, isNil, localize, MorphicPreferences*/
|
||||
|
||||
modules.lists = '2015-October-07';
|
||||
modules.lists = '2015-November-16';
|
||||
|
||||
var List;
|
||||
var ListWatcherMorph;
|
||||
|
@ -682,13 +682,14 @@ ListWatcherMorph.prototype.arrangeCells = function () {
|
|||
this.frame.contents.adjustBounds();
|
||||
};
|
||||
|
||||
ListWatcherMorph.prototype.expand = function () {
|
||||
ListWatcherMorph.prototype.expand = function (maxExtent) {
|
||||
// make sure to show all (first 100) cells
|
||||
// used for exporting a project summary
|
||||
var fe = this.frame.contents.extent(),
|
||||
w = fe.x + 6,
|
||||
h = fe.y + this.label.height() + 6;
|
||||
this.setExtent(new Point(w, h));
|
||||
ext = new Point(fe.x + 6, fe.y + this.label.height() + 6);
|
||||
if (maxExtent) {
|
||||
ext = ext.min(maxExtent);
|
||||
}
|
||||
this.setExtent(ext);
|
||||
this.handle.setRight(this.right() - 3);
|
||||
this.handle.setBottom(this.bottom() - 3);
|
||||
};
|
||||
|
|
27
locale.js
27
locale.js
|
@ -42,7 +42,7 @@
|
|||
|
||||
/*global modules, contains*/
|
||||
|
||||
modules.locale = '2015-October-07';
|
||||
modules.locale = '2015-November-16';
|
||||
|
||||
// Global stuff
|
||||
|
||||
|
@ -225,7 +225,7 @@ SnapTranslator.dict.cs = {
|
|||
'translator_e-mail':
|
||||
'info@iguru.eu, jan.tomsa.1976@gmail.com',
|
||||
'last_changed':
|
||||
'2015-09-23'
|
||||
'2015-11-16'
|
||||
};
|
||||
|
||||
SnapTranslator.dict.zh = {
|
||||
|
@ -526,3 +526,26 @@ SnapTranslator.dict.hr = {
|
|||
'last_changed':
|
||||
'2015-09-15'
|
||||
};
|
||||
|
||||
SnapTranslator.dict.bg = {
|
||||
'language_name':
|
||||
'Български',
|
||||
'language_translator':
|
||||
'Ivan Savov',
|
||||
'translator_e-mail':
|
||||
'ivan.savov@gmail.com',
|
||||
'last_changed':
|
||||
'2015-11-16'
|
||||
};
|
||||
|
||||
SnapTranslator.dict.ro = {
|
||||
'language_name':
|
||||
'Român',
|
||||
'language_translator':
|
||||
'Cristian Macarascu',
|
||||
'translator_e-mail':
|
||||
'',
|
||||
'last_changed':
|
||||
'2015-10-24'
|
||||
};
|
||||
|
||||
|
|
128
morphic.js
128
morphic.js
|
@ -1052,7 +1052,7 @@
|
|||
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
|
||||
FileList, getBlurredShadowSupport*/
|
||||
|
||||
var morphicVersion = '2015-September-23';
|
||||
var morphicVersion = '2015-November-16';
|
||||
var modules = {}; // keep track of additional loaded modules
|
||||
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
||||
|
||||
|
@ -1072,7 +1072,8 @@ var standardSettings = {
|
|||
useVirtualKeyboard: true,
|
||||
isTouchDevice: false, // turned on by touch events, don't set
|
||||
rasterizeSVGs: false,
|
||||
isFlat: false
|
||||
isFlat: false,
|
||||
grabThreshold: 5
|
||||
};
|
||||
|
||||
var touchScreenSettings = {
|
||||
|
@ -1091,7 +1092,8 @@ var touchScreenSettings = {
|
|||
useVirtualKeyboard: true,
|
||||
isTouchDevice: false,
|
||||
rasterizeSVGs: false,
|
||||
isFlat: false
|
||||
isFlat: false,
|
||||
grabThreshold: 5
|
||||
};
|
||||
|
||||
var MorphicPreferences = standardSettings;
|
||||
|
@ -2207,7 +2209,10 @@ function Morph() {
|
|||
Morph.prototype.init = function (noDraw) {
|
||||
Morph.uber.init.call(this);
|
||||
this.isMorph = true;
|
||||
this.image = null;
|
||||
this.bounds = new Rectangle(0, 0, 50, 40);
|
||||
this.cachedFullImage = null;
|
||||
this.cachedFullBounds = null;
|
||||
this.color = new Color(80, 80, 80);
|
||||
this.texture = null; // optional url of a fill-image
|
||||
this.cachedTexture = null; // internal cache of actual bg image
|
||||
|
@ -2284,9 +2289,7 @@ Morph.prototype.nextSteps = function (arrayOfFunctions) {
|
|||
}
|
||||
};
|
||||
|
||||
Morph.prototype.step = function () {
|
||||
nop();
|
||||
};
|
||||
Morph.prototype.step = nop;
|
||||
|
||||
// Morph accessing - geometry getting:
|
||||
|
||||
|
@ -2412,6 +2415,9 @@ Morph.prototype.silentMoveBy = function (delta) {
|
|||
var children = this.children,
|
||||
i = children.length;
|
||||
this.bounds = this.bounds.translateBy(delta);
|
||||
if (this.cachedFullBounds) {
|
||||
this.cachedFullBounds = this.cachedFullBounds.translateBy(delta);
|
||||
}
|
||||
// ugly optimization avoiding forEach()
|
||||
for (i; i > 0; i -= 1) {
|
||||
children[i - 1].silentMoveBy(delta);
|
||||
|
@ -2533,7 +2539,12 @@ Morph.prototype.scrollIntoView = function () {
|
|||
|
||||
// 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())) {
|
||||
this.changed();
|
||||
this.silentSetExtent(aPoint);
|
||||
|
@ -2640,29 +2651,31 @@ Morph.prototype.drawCachedTexture = function () {
|
|||
*/
|
||||
|
||||
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) {
|
||||
return null;
|
||||
}
|
||||
rectangle = aRect || this.bounds();
|
||||
area = rectangle.intersect(this.bounds);
|
||||
rectangle = aRect || bounds;
|
||||
area = rectangle.intersect(bounds);
|
||||
if (area.extent().gt(new Point(0, 0))) {
|
||||
delta = this.position().neg();
|
||||
delta = bounds.position().neg();
|
||||
src = area.copy().translateBy(delta);
|
||||
context = aCanvas.getContext('2d');
|
||||
context.globalAlpha = this.alpha;
|
||||
|
||||
sl = src.left();
|
||||
st = src.top();
|
||||
w = Math.min(src.width(), this.image.width - sl);
|
||||
h = Math.min(src.height(), this.image.height - st);
|
||||
w = Math.min(src.width(), pic.width - sl);
|
||||
h = Math.min(src.height(), pic.height - st);
|
||||
|
||||
if (w < 1 || h < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
context.drawImage(
|
||||
this.image,
|
||||
pic,
|
||||
sl,
|
||||
st,
|
||||
w,
|
||||
|
@ -2672,42 +2685,6 @@ Morph.prototype.drawOn = function (aCanvas, aRect) {
|
|||
w,
|
||||
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) {
|
||||
return null;
|
||||
}
|
||||
rectangle = aRect || this.fullBounds();
|
||||
rectangle = aRect || this.cachedFullBounds || this.fullBounds();
|
||||
this.drawOn(aCanvas, rectangle);
|
||||
if (this.cachedFullImage) {return; }
|
||||
this.children.forEach(function (child) {
|
||||
child.fullDrawOn(aCanvas, rectangle);
|
||||
});
|
||||
|
@ -2911,7 +2889,9 @@ Morph.prototype.fullChanged = function () {
|
|||
if (this.trackChanges) {
|
||||
var w = this.root();
|
||||
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.prototype.init = function (aWorld) {
|
||||
HandMorph.uber.init.call(this);
|
||||
HandMorph.uber.init.call(this, true);
|
||||
this.bounds = new Rectangle();
|
||||
|
||||
// additional properties:
|
||||
|
@ -9456,6 +9436,7 @@ HandMorph.prototype.init = function (aWorld) {
|
|||
this.mouseButton = null;
|
||||
this.mouseOverList = [];
|
||||
this.morphToGrab = null;
|
||||
this.grabPosition = null;
|
||||
this.grabOrigin = null;
|
||||
this.temporaries = [];
|
||||
this.touchHoldTimeout = null;
|
||||
|
@ -9520,6 +9501,8 @@ HandMorph.prototype.grab = function (aMorph) {
|
|||
if (aMorph.prepareToBeGrabbed) {
|
||||
aMorph.prepareToBeGrabbed(this);
|
||||
}
|
||||
aMorph.cachedFullImage = aMorph.fullImageClassic();
|
||||
aMorph.cachedFullBounds = aMorph.fullBounds();
|
||||
this.add(aMorph);
|
||||
this.changed();
|
||||
if (oldParent && oldParent.reactToGrabOf) {
|
||||
|
@ -9535,6 +9518,8 @@ HandMorph.prototype.drop = function () {
|
|||
target = this.dropTargetFor(morphToDrop);
|
||||
this.changed();
|
||||
target.add(morphToDrop);
|
||||
morphToDrop.cachedFullImage = null;
|
||||
morphToDrop.cachedFullBounds = null;
|
||||
morphToDrop.changed();
|
||||
morphToDrop.removeShadow();
|
||||
this.children = [];
|
||||
|
@ -9545,7 +9530,6 @@ HandMorph.prototype.drop = function () {
|
|||
if (target.reactToDropOf) {
|
||||
target.reactToDropOf(morphToDrop, this);
|
||||
}
|
||||
this.dragOrigin = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9572,6 +9556,7 @@ HandMorph.prototype.processMouseDown = function (event) {
|
|||
this.destroyTemporaries();
|
||||
this.contextMenuEnabled = true;
|
||||
this.morphToGrab = null;
|
||||
this.grabPosition = null;
|
||||
if (this.children.length !== 0) {
|
||||
this.drop();
|
||||
this.mouseButton = null;
|
||||
|
@ -9599,6 +9584,7 @@ HandMorph.prototype.processMouseDown = function (event) {
|
|||
}
|
||||
if (!morph.mouseMove) {
|
||||
this.morphToGrab = morph.rootForGrab();
|
||||
this.grabPosition = this.bounds.origin.copy();
|
||||
}
|
||||
if (event.button === 2 || event.ctrlKey) {
|
||||
this.mouseButton = 'right';
|
||||
|
@ -9708,8 +9694,7 @@ HandMorph.prototype.processMouseMove = function (event) {
|
|||
mouseOverNew,
|
||||
myself = this,
|
||||
morph,
|
||||
topMorph,
|
||||
fb;
|
||||
topMorph;
|
||||
|
||||
pos = new Point(
|
||||
event.pageX - posInDocument.x,
|
||||
|
@ -9733,7 +9718,11 @@ HandMorph.prototype.processMouseMove = function (event) {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
morph = this.morphToGrab;
|
||||
this.grab(morph);
|
||||
|
@ -9747,16 +9736,7 @@ HandMorph.prototype.processMouseMove = function (event) {
|
|||
this.grab(morph);
|
||||
this.grabOrigin = this.morphToGrab.situation();
|
||||
}
|
||||
if (morph) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
this.setPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10224,14 +10204,12 @@ WorldMorph.prototype.initVirtualKeyboard = function () {
|
|||
myself.keyboardReceiver.processKeyDown(event);
|
||||
}
|
||||
// supress backspace override
|
||||
if (event.keyIdentifier === 'U+0008' ||
|
||||
event.keyIdentifier === 'Backspace') {
|
||||
if (event.keyCode === 8) {
|
||||
event.preventDefault();
|
||||
}
|
||||
// supress tab override and make sure tab gets
|
||||
// received by all browsers
|
||||
if (event.keyIdentifier === 'U+0009' ||
|
||||
event.keyIdentifier === 'Tab') {
|
||||
if (event.keyCode === 9) {
|
||||
if (myself.keyboardReceiver) {
|
||||
myself.keyboardReceiver.processKeyPress(event);
|
||||
}
|
||||
|
@ -10356,21 +10334,19 @@ WorldMorph.prototype.initEventListeners = function () {
|
|||
myself.keyboardReceiver.processKeyDown(event);
|
||||
}
|
||||
// supress backspace override
|
||||
if (event.keyIdentifier === 'U+0008' ||
|
||||
event.keyIdentifier === 'Backspace') {
|
||||
if (event.keyCode === 8) {
|
||||
event.preventDefault();
|
||||
}
|
||||
// supress tab override and make sure tab gets
|
||||
// received by all browsers
|
||||
if (event.keyIdentifier === 'U+0009' ||
|
||||
event.keyIdentifier === 'Tab') {
|
||||
if (event.keyCode === 9) {
|
||||
if (myself.keyboardReceiver) {
|
||||
myself.keyboardReceiver.processKeyPress(event);
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
if ((event.ctrlKey || event.metaKey) &&
|
||||
(event.keyIdentifier !== 'U+0056')) { // allow pasting-in
|
||||
(event.keyCode !== 86)) { // allow pasting-in
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
|
23
objects.js
23
objects.js
|
@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.objects = '2015-October-07';
|
||||
modules.objects = '2015-November-16';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -1184,7 +1184,7 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
dev: true,
|
||||
type: 'command',
|
||||
category: 'lists',
|
||||
spec: 'for %upvar in %l %cs',
|
||||
spec: 'for %upvar in %l %cl',
|
||||
defaults: [localize('each item')]
|
||||
},
|
||||
|
||||
|
@ -2326,7 +2326,7 @@ SpriteMorph.prototype.freshPalette = function (category) {
|
|||
x = block.right() + unit / 2;
|
||||
ry = block.bottom();
|
||||
} else {
|
||||
if (block.fixLayout) {block.fixLayout(); }
|
||||
// if (block.fixLayout) {block.fixLayout(); }
|
||||
x = 0;
|
||||
y += block.height();
|
||||
}
|
||||
|
@ -3249,7 +3249,7 @@ SpriteMorph.prototype.bubble = function (data, isThought, isQuestion) {
|
|||
if (data === '' || isNil(data)) {return; }
|
||||
bubble = new SpriteBubbleMorph(
|
||||
data,
|
||||
stage ? stage.scale : 1,
|
||||
stage,
|
||||
isThought,
|
||||
isQuestion
|
||||
);
|
||||
|
@ -3539,6 +3539,7 @@ SpriteMorph.prototype.gotoXY = function (x, y, justMe) {
|
|||
newY,
|
||||
dest;
|
||||
|
||||
if (!stage) {return; }
|
||||
newX = stage.center().x + (+x || 0) * stage.scale;
|
||||
newY = stage.center().y - (+y || 0) * stage.scale;
|
||||
if (this.costume) {
|
||||
|
@ -6055,18 +6056,19 @@ SpriteBubbleMorph.uber = SpeechBubbleMorph.prototype;
|
|||
|
||||
// SpriteBubbleMorph instance creation:
|
||||
|
||||
function SpriteBubbleMorph(data, scale, isThought, isQuestion) {
|
||||
this.init(data, scale, isThought, isQuestion);
|
||||
function SpriteBubbleMorph(data, stage, isThought, isQuestion) {
|
||||
this.init(data, stage, isThought, isQuestion);
|
||||
}
|
||||
|
||||
SpriteBubbleMorph.prototype.init = function (
|
||||
data,
|
||||
scale,
|
||||
stage,
|
||||
isThought,
|
||||
isQuestion
|
||||
) {
|
||||
var sprite = SpriteMorph.prototype;
|
||||
this.scale = scale || 1;
|
||||
this.stage = stage;
|
||||
this.scale = stage ? stage.scale : 1;
|
||||
this.data = data;
|
||||
this.isQuestion = isQuestion;
|
||||
|
||||
|
@ -6126,6 +6128,11 @@ SpriteBubbleMorph.prototype.dataAsMorph = function (data) {
|
|||
contents.isDraggable = false;
|
||||
contents.update(true);
|
||||
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) {
|
||||
img = data.image();
|
||||
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 ////////////////////////////////////////////////////////
|
||||
|
||||
modules.threads = '2015-October-02';
|
||||
modules.threads = '2015-November-16';
|
||||
|
||||
var ThreadManager;
|
||||
var Process;
|
||||
|
@ -128,6 +128,26 @@ function snapEquals(a, b) {
|
|||
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 ///////////////////////////////////////////////////////
|
||||
|
||||
function ThreadManager() {
|
||||
|
@ -638,7 +658,8 @@ Process.prototype.evaluateInput = function (input) {
|
|||
if (contains(
|
||||
[CommandSlotMorph, ReporterSlotMorph],
|
||||
input.constructor
|
||||
) || (input instanceof CSlotMorph && !input.isStatic)) {
|
||||
) || (input instanceof CSlotMorph &&
|
||||
(!input.isStatic || input.isLambda))) {
|
||||
// I know, this still needs yet to be done right....
|
||||
ans = this.reify(ans, new List());
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue