Merge remote-tracking branch 'jmoenig/master'

pull/29/head
Manuel Menezes de Sequeira 2016-11-24 21:36:28 +00:00
commit ad5e32203e
12 zmienionych plików z 2497 dodań i 115 usunięć

1
.gitignore vendored
Wyświetl plik

@ -1,2 +1,3 @@
.DS_Store
*.swp
.tern-port

479
blocks.js
Wyświetl plik

@ -149,7 +149,7 @@ isSnapObject, copy, PushButtonMorph, SpriteIconMorph, Process*/
// Global stuff ////////////////////////////////////////////////////////
modules.blocks = '2016-October-31';
modules.blocks = '2016-November-24';
var SyntaxElementMorph;
var BlockMorph;
@ -1480,22 +1480,19 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
// allow GUI symbols as label icons
// usage: $symbolName[-size-r-g-b], size and color values are optional
// If there isn't a symbol under that name, it just styles whatever is
// after "$", so you can add unicode icons to your blocks, for example
// ☺️
tokens = spec.slice(1).split('-');
if (!contains(SymbolMorph.prototype.names, tokens[0])) {
part = new StringMorph(spec);
part = new StringMorph(tokens[0]);
part.fontName = this.labelFontName;
part.fontStyle = this.labelFontStyle;
part.fontSize = this.fontSize;
part.color = new Color(255, 255, 255);
part.isBold = true;
part.shadowColor = this.color.darker(this.labelContrast);
part.shadowOffset = MorphicPreferences.isFlat ?
new Point() : this.embossing;
part.drawNew();
return part;
part.fontSize = this.fontSize * (+tokens[1] || 1);
} else {
part = new SymbolMorph(tokens[0]);
part.size = this.fontSize * (+tokens[1] || 1.2);
}
part = new SymbolMorph(tokens[0]);
part.size = this.fontSize * (+tokens[1] || 1.2);
part.color = new Color(
+tokens[2] === 0 ? 0 : +tokens[2] || 255,
+tokens[3] === 0 ? 0 : +tokens[3] || 255,
@ -2381,8 +2378,15 @@ BlockMorph.prototype.userMenu = function () {
"duplicate",
function () {
var dup = myself.fullCopy(),
ide = myself.parentThatIsA(IDE_Morph);
ide = myself.parentThatIsA(IDE_Morph),
blockEditor = myself.parentThatIsA(BlockEditorMorph);
dup.pickUp(world);
// register the drop-origin, so the block can
// slide back to its former situation if dropped
// somewhere where it gets rejected
if (!ide && blockEditor) {
ide = blockEditor.target.parentThatIsA(IDE_Morph);
}
if (ide) {
world.hand.grabOrigin = {
origin: ide.palette,
@ -3491,12 +3495,14 @@ BlockMorph.prototype.reactToDropOf = function (droppedMorph) {
BlockMorph.prototype.situation = function () {
// answer a dictionary specifying where I am right now, so
// I can slide back to it if I'm dropped somewhere else
var scripts = this.parentThatIsA(ScriptsMorph);
if (scripts) {
return {
origin: scripts,
position: this.position().subtract(scripts.position())
};
if (!(this.parent instanceof TemplateSlotMorph)) {
var scripts = this.parentThatIsA(ScriptsMorph);
if (scripts) {
return {
origin: scripts,
position: this.position().subtract(scripts.position())
};
}
}
return BlockMorph.uber.situation.call(this);
};
@ -3709,6 +3715,20 @@ CommandBlockMorph.prototype.bottomAttachPoint = function () {
);
};
CommandBlockMorph.prototype.wrapAttachPoint = function () {
var cslot = detect( // could be a method making uses of caching...
this.inputs(), // ... although these already are cached
function (each) {return each instanceof CSlotMorph; }
);
if (cslot && !cslot.nestedBlock()) {
return new Point(
cslot.left() + (cslot.inset * 2) + cslot.corner,
cslot.top() + (cslot.corner * 2)
);
}
return null;
};
CommandBlockMorph.prototype.dentLeft = function () {
return this.left()
+ this.corner
@ -3722,16 +3742,27 @@ CommandBlockMorph.prototype.dentCenter = function () {
};
CommandBlockMorph.prototype.attachTargets = function () {
var answer = [];
var answer = [],
tp;
if (!(this instanceof HatBlockMorph)) {
tp = this.topAttachPoint();
if (!(this.parent instanceof SyntaxElementMorph)) {
answer.push({
point: this.topAttachPoint(),
point: tp,
element: this,
loc: 'top',
type: 'block'
});
}
if (ScriptsMorph.prototype.enableNestedAutoWrapping ||
!this.parentThatIsA(CommandSlotMorph)) {
answer.push({
point: tp,
element: this,
loc: 'wrap',
type: 'block'
});
}
}
if (!this.isStop()) {
answer.push({
@ -3780,7 +3811,8 @@ CommandBlockMorph.prototype.closestAttachTarget = function (newParent) {
),
dist,
ref = [],
minDist = 1000;
minDist = 1000,
wrap;
if (!(this instanceof HatBlockMorph)) {
ref.push(
@ -3789,6 +3821,15 @@ CommandBlockMorph.prototype.closestAttachTarget = function (newParent) {
loc: 'top'
}
);
wrap = this.wrapAttachPoint();
if (wrap) {
ref.push(
{
point: wrap,
loc: 'wrap'
}
);
}
}
if (!bottomBlock.isStop()) {
ref.push(
@ -3798,10 +3839,14 @@ CommandBlockMorph.prototype.closestAttachTarget = function (newParent) {
}
);
}
this.allAttachTargets(target).forEach(function (eachTarget) {
ref.forEach(function (eachRef) {
if (eachRef.loc !== eachTarget.loc) {
// match: either both locs are 'wrap' or both are different,
// none being 'wrap' (can this be expressed any better?)
if ((eachRef.loc === 'wrap' && (eachTarget.loc === 'wrap')) ||
((eachRef.loc !== eachTarget.loc) &&
(eachRef.loc !== 'wrap') && (eachTarget.loc !== 'wrap'))
) {
dist = eachRef.point.distanceTo(eachTarget.point);
if ((dist < thresh) && (dist < minDist)) {
minDist = dist;
@ -3813,21 +3858,25 @@ CommandBlockMorph.prototype.closestAttachTarget = function (newParent) {
return answer;
};
CommandBlockMorph.prototype.snap = function () {
CommandBlockMorph.prototype.snap = function (hand) {
var target = this.closestAttachTarget(),
scripts = this.parentThatIsA(ScriptsMorph),
before,
next,
offsetY,
cslot,
affected;
scripts.clearDropHistory();
scripts.clearDropInfo();
scripts.lastDroppedBlock = this;
if (target === null) {
this.startLayout();
this.fixBlockColor();
this.endLayout();
CommandBlockMorph.uber.snap.call(this); // align stuck comments
if (hand) {
scripts.recordDrop(hand.grabOrigin);
}
return;
}
@ -3860,10 +3909,38 @@ CommandBlockMorph.prototype.snap = function () {
this.setBottom(target.element.top() + this.corner - offsetY);
this.setLeft(target.element.left());
this.bottomBlock().nextBlock(target.element);
} else if (target.loc === 'wrap') {
cslot = detect( // this should be a method making use of caching
this.inputs(), // these are already cached, so maybe it's okay
function (each) {return each instanceof CSlotMorph; }
);
// assume the cslot is (still) empty, was checked determining the target
before = (target.element.parent);
scripts.lastWrapParent = before;
// adjust position of wrapping block
this.moveBy(target.point.subtract(cslot.slotAttachPoint()));
// wrap c-slot around target
cslot.nestedBlock(target.element);
if (before instanceof CommandBlockMorph) {
before.nextBlock(this);
} else if (before instanceof CommandSlotMorph) {
before.nestedBlock(this);
}
// fix zebra coloring.
// this could probably be generalized into the fixBlockColor mechanism
target.element.blockSequence().forEach(
function (cmd) {cmd.fixBlockColor(); }
);
}
this.fixBlockColor();
this.endLayout();
CommandBlockMorph.uber.snap.call(this); // align stuck comments
if (hand) {
scripts.recordDrop(hand.grabOrigin);
}
if (this.snapSound) {
this.snapSound.play();
}
@ -3888,7 +3965,18 @@ CommandBlockMorph.prototype.userDestroy = function () {
this.userDestroyJustThis();
return;
}
var cslot = this.parentThatIsA(CSlotMorph);
var scripts = this.parentThatIsA(ScriptsMorph),
cslot = this.parentThatIsA(CSlotMorph);
// for undrop / redrop
if (scripts) {
scripts.clearDropInfo();
scripts.lastDroppedBlock = this;
scripts.recordDrop(this.situation());
scripts.dropRecord.action = 'delete';
}
this.destroy();
if (cslot) {
cslot.fixLayout();
@ -3904,6 +3992,15 @@ CommandBlockMorph.prototype.userDestroyJustThis = function () {
above,
cslot = this.parentThatIsA(CSlotMorph);
// for undrop / redrop
if (scripts) {
scripts.clearDropInfo();
scripts.lastDroppedBlock = this;
scripts.recordDrop(this.situation());
scripts.dropRecord.lastNextBlock = nb;
scripts.dropRecord.action = 'delete';
}
this.topBlock().fullChanged();
if (this.parent) {
pb = this.parent.parentThatIsA(CommandBlockMorph);
@ -4525,7 +4622,7 @@ ReporterBlockMorph.prototype.snap = function (hand) {
return null;
}
scripts.clearDropHistory();
scripts.clearDropInfo();
scripts.lastDroppedBlock = this;
target = scripts.closestInput(this, hand);
@ -4555,6 +4652,9 @@ ReporterBlockMorph.prototype.snap = function (hand) {
this.fixBlockColor();
this.endLayout();
ReporterBlockMorph.uber.snap.call(this);
if (hand) {
scripts.recordDrop(hand.grabOrigin);
}
};
ReporterBlockMorph.prototype.prepareToBeGrabbed = function (handMorph) {
@ -4693,6 +4793,16 @@ ReporterBlockMorph.prototype.ExportResultPic = function () {
ReporterBlockMorph.prototype.userDestroy = function () {
// make sure to restore default slot of parent block
// for undrop / redrop
var scripts = this.parentThatIsA(ScriptsMorph);
if (scripts) {
scripts.clearDropInfo();
scripts.lastDroppedBlock = this;
scripts.recordDrop(this.situation());
scripts.dropRecord.action = 'delete';
}
this.topBlock().fullChanged();
this.prepareToBeGrabbed(this.world().hand);
this.destroy();
@ -5159,7 +5269,10 @@ RingMorph.prototype.vanishForSimilar = function () {
|| (this.parent instanceof RingCommandSlotMorph)) {
return null;
}
if (block.selector === 'reportGetVar' || (block instanceof RingMorph)) {
if (block.selector === 'reportGetVar' ||
block.selector === 'reportJSFunction' ||
(block instanceof RingMorph)
) {
this.parent.silentReplaceInput(this, block);
}
};
@ -5215,6 +5328,7 @@ ScriptsMorph.prototype.cleanUpMargin = 20;
ScriptsMorph.prototype.cleanUpSpacing = 15;
ScriptsMorph.prototype.isPreferringEmptySlots = true;
ScriptsMorph.prototype.enableKeyboard = true;
ScriptsMorph.prototype.enableNestedAutoWrapping = false;
// ScriptsMorph instance creation:
@ -5234,6 +5348,7 @@ ScriptsMorph.prototype.init = function (owner) {
this.lastDropTarget = null;
this.lastPreservedBlocks = null;
this.lastNextBlock = null;
this.lastWrapParent = null;
// keyboard editing support:
this.focus = null;
@ -5241,6 +5356,9 @@ ScriptsMorph.prototype.init = function (owner) {
ScriptsMorph.uber.init.call(this);
this.setColor(new Color(70, 70, 70));
this.noticesTransparentClick = true;
// initialize "undrop" queue
this.recordDrop();
};
// ScriptsMorph deep copying:
@ -5347,6 +5465,10 @@ ScriptsMorph.prototype.showCommandDropFeedback = function (block) {
if (!target) {
return null;
}
if (target.loc === 'wrap') {
this.showCSlotWrapFeedback(block, target.element);
return;
}
this.add(this.feedbackMorph);
this.feedbackMorph.border = 0;
this.feedbackMorph.edge = 0;
@ -5403,6 +5525,24 @@ ScriptsMorph.prototype.showCommentDropFeedback = function (comment, hand) {
this.feedbackMorph.changed();
};
ScriptsMorph.prototype.showCSlotWrapFeedback = function (srcBlock, trgBlock) {
var clr;
this.feedbackMorph.bounds = trgBlock.fullBounds()
.expandBy(BlockMorph.prototype.corner);
this.feedbackMorph.edge = SyntaxElementMorph.prototype.corner;
this.feedbackMorph.border = Math.max(
SyntaxElementMorph.prototype.edge,
3
);
this.add(this.feedbackMorph);
clr = srcBlock.color.lighter(40);
this.feedbackMorph.color = clr.copy();
this.feedbackMorph.color.a = 0.1;
this.feedbackMorph.borderColor = clr;
this.feedbackMorph.drawNew();
this.feedbackMorph.changed();
};
ScriptsMorph.prototype.closestInput = function (reporter, hand) {
// passing the hand is optional (when dragging reporters)
var fb = reporter.fullBoundsNoShadow(),
@ -5552,6 +5692,7 @@ ScriptsMorph.prototype.userMenu = function () {
blockEditor,
myself = this,
obj = this.owner,
hasUndropQueue,
stage = obj.parentThatIsA(StageMorph);
if (!ide) {
@ -5560,15 +5701,30 @@ ScriptsMorph.prototype.userMenu = function () {
ide = blockEditor.target.parentThatIsA(IDE_Morph);
}
}
if (this.dropRecord) {
if (this.dropRecord.lastRecord) {
hasUndropQueue = true;
menu.addItem(
'undrop',
'undrop',
'undo the last\nblock drop\nin this pane'
);
}
if (this.dropRecord.nextRecord) {
hasUndropQueue = true;
menu.addItem(
'redrop',
'redrop',
'redo the last undone\nblock drop\nin this pane'
);
}
if (hasUndropQueue) {
menu.addLine();
}
}
menu.addItem('clean up', 'cleanUp', 'arrange scripts\nvertically');
menu.addItem('add comment', 'addComment');
if (this.lastDroppedBlock) {
menu.addItem(
'undrop',
'undrop',
'undo the last\nblock drop\nin this pane'
);
}
menu.addItem(
'scripts pic...',
'exportScriptsPicture',
@ -5671,59 +5827,210 @@ ScriptsMorph.prototype.scriptsPicture = function () {
};
ScriptsMorph.prototype.addComment = function () {
new CommentMorph().pickUp(this.world());
var ide = this.parentThatIsA(IDE_Morph),
blockEditor = this.parentThatIsA(BlockEditorMorph),
world = this.world();
new CommentMorph().pickUp(world);
// register the drop-origin, so the element can
// slide back to its former situation if dropped
// somewhere where it gets rejected
if (!ide && blockEditor) {
ide = blockEditor.target.parentThatIsA(IDE_Morph);
}
if (ide) {
world.hand.grabOrigin = {
origin: ide.palette,
position: ide.palette.center()
};
}
};
ScriptsMorph.prototype.undrop = function () {
if (!this.lastDroppedBlock) {return; }
if (this.lastDroppedBlock instanceof CommandBlockMorph) {
if (this.lastNextBlock) {
this.add(this.lastNextBlock);
if (!this.dropRecord || !this.dropRecord.lastRecord) {return; }
if (!this.dropRecord.situation) {
this.dropRecord.situation =
this.dropRecord.lastDroppedBlock.situation();
}
this.dropRecord.lastDroppedBlock.slideBackTo(
this.dropRecord.lastOrigin,
null,
this.recoverLastDrop()
);
this.dropRecord = this.dropRecord.lastRecord;
};
ScriptsMorph.prototype.redrop = function () {
if (!this.dropRecord || !this.dropRecord.nextRecord) {return; }
this.dropRecord = this.dropRecord.nextRecord;
if (this.dropRecord.action === 'delete') {
this.recoverLastDrop(true);
this.dropRecord.lastDroppedBlock.destroy();
} else {
this.dropRecord.lastDroppedBlock.slideBackTo(
this.dropRecord.situation,
null,
this.recoverLastDrop(true)
);
}
};
ScriptsMorph.prototype.recoverLastDrop = function (forRedrop) {
// retrieve the block last touched by the user and answer a function
// to be called after the animation that moves it back right before
// dropping it into its former situation
var rec = this.dropRecord,
dropped,
onBeforeDrop,
parent;
if (!rec || !rec.lastDroppedBlock) {
throw new Error('nothing to undrop');
}
dropped = rec.lastDroppedBlock;
parent = dropped.parent;
if (dropped instanceof CommandBlockMorph) {
if (rec.lastNextBlock) {
if (rec.action === 'delete') {
if (forRedrop) {
this.add(rec.lastNextBlock);
}
} else {
this.add(rec.lastNextBlock);
}
}
if (this.lastDropTarget) {
if (this.lastDropTarget.loc === 'bottom') {
if (this.lastDropTarget.type === 'slot') {
if (this.lastNextBlock) {
this.lastDropTarget.element.nestedBlock(
this.lastNextBlock
if (rec.lastDropTarget) {
if (rec.lastDropTarget.loc === 'bottom') {
if (rec.lastDropTarget.type === 'slot') {
if (rec.lastNextBlock) {
rec.lastDropTarget.element.nestedBlock(
rec.lastNextBlock
);
}
} else { // 'block'
if (this.lastNextBlock) {
this.lastDropTarget.element.nextBlock(
this.lastNextBlock
if (rec.lastNextBlock) {
rec.lastDropTarget.element.nextBlock(
rec.lastNextBlock
);
}
}
} else if (this.lastDropTarget.loc === 'top') {
this.add(this.lastDropTarget.element);
} else if (rec.lastDropTarget.loc === 'top') {
this.add(rec.lastDropTarget.element);
} else if (rec.lastDropTarget.loc === 'wrap') {
var cslot = detect( // could be cached...
rec.lastDroppedBlock.inputs(), // ...although these are
function (each) {return each instanceof CSlotMorph; }
);
if (rec.lastWrapParent instanceof CommandBlockMorph) {
if (forRedrop) {
onBeforeDrop = function () {
cslot.nestedBlock(rec.lastDropTarget.element);
};
} else {
rec.lastWrapParent.nextBlock(
rec.lastDropTarget.element
);
}
} else if (rec.lastWrapParent instanceof CommandSlotMorph) {
if (forRedrop) {
onBeforeDrop = function () {
cslot.nestedBlock(rec.lastDropTarget.element);
};
} else {
rec.lastWrapParent.nestedBlock(
rec.lastDropTarget.element
);
}
} else {
this.add(rec.lastDropTarget.element);
}
// fix zebra coloring.
// this could be generalized into the fixBlockColor mechanism
rec.lastDropTarget.element.blockSequence().forEach(
function (cmd) {cmd.fixBlockColor(); }
);
cslot.fixLayout();
}
}
} else { // ReporterBlockMorph
if (this.lastDropTarget) {
this.lastDropTarget.replaceInput(
this.lastDroppedBlock,
this.lastReplacedInput
} else if (dropped instanceof ReporterBlockMorph) {
if (rec.lastDropTarget) {
rec.lastDropTarget.replaceInput(
rec.lastDroppedBlock,
rec.lastReplacedInput
);
this.lastDropTarget.fixBlockColor(null, true);
if (this.lastPreservedBlocks) {
this.lastPreservedBlocks.forEach(function (morph) {
rec.lastDropTarget.fixBlockColor(null, true);
if (rec.lastPreservedBlocks) {
rec.lastPreservedBlocks.forEach(function (morph) {
morph.destroy();
});
}
}
} else if (dropped instanceof CommentMorph) {
if (forRedrop && rec.lastDropTarget) {
onBeforeDrop = function () {
rec.lastDropTarget.element.comment = dropped;
dropped.block = rec.lastDropTarget.element;
dropped.align();
};
}
} else {
throw new Error('unsupported action for ' + dropped);
}
this.lastDroppedBlock.pickUp(this.world());
this.clearDropHistory();
this.clearDropInfo();
dropped.prepareToBeGrabbed(this.world().hand);
if (dropped instanceof CommentMorph) {
dropped.removeShadow();
}
this.add(dropped);
parent.reactToGrabOf(dropped);
if (dropped instanceof ReporterBlockMorph && parent instanceof BlockMorph) {
parent.changed();
}
if (rec.action === 'delete') {
if (forRedrop && rec.lastNextBlock) {
if (parent instanceof CommandBlockMorph) {
parent.nextBlock(rec.lastNextBlock);
} else if (parent instanceof CommandSlotMorph) {
parent.nestedBlock(rec.lastNextBlock);
}
}
// animate "undelete"
if (!forRedrop) {
dropped.moveBy(new Point(-100, -20));
}
}
return onBeforeDrop;
};
ScriptsMorph.prototype.clearDropHistory = function () {
ScriptsMorph.prototype.clearDropInfo = function () {
this.lastDroppedBlock = null;
this.lastReplacedInput = null;
this.lastDropTarget = null;
this.lastPreservedBlocks = null;
this.lastNextBlock = null;
this.lastWrapParent = null;
};
ScriptsMorph.prototype.recordDrop = function (lastGrabOrigin) {
// support for "undrop" / "redrop"
var record = {
lastDroppedBlock: this.lastDroppedBlock,
lastReplacedInput: this.lastReplacedInput,
lastDropTarget: this.lastDropTarget,
lastPreservedBlocks: this.lastPreservedBlocks,
lastNextBlock: this.lastNextBlock,
lastWrapParent: this.lastWrapParent,
lastOrigin: lastGrabOrigin,
action: null,
situation: null,
lastRecord: this.dropRecord,
nextRecord: null
};
if (this.dropRecord) {
this.dropRecord.nextRecord = record;
}
this.dropRecord = record;
};
// ScriptsMorph sorting blocks and comments
@ -5860,7 +6167,6 @@ ArgMorph.prototype.reactToSliderEdit = function () {
}
};
// ArgMorph drag & drop: for demo puposes only
ArgMorph.prototype.justDropped = function () {
@ -8020,6 +8326,18 @@ TemplateSlotMorph.prototype.fixLayout = function () {
}
};
// TemplateSlotMorph drop behavior:
TemplateSlotMorph.prototype.wantsDropOf = function (aMorph) {
return aMorph.selector === 'reportGetVar';
};
TemplateSlotMorph.prototype.reactToDropOf = function (droppedMorph) {
if (droppedMorph.selector === 'reportGetVar') {
droppedMorph.destroy();
}
};
// TemplateSlotMorph drawing:
TemplateSlotMorph.prototype.drawNew = function () {
@ -11829,7 +12147,7 @@ CommentMorph.prototype.show = function () {
// CommentMorph dragging & dropping
CommentMorph.prototype.prepareToBeGrabbed = function () {
CommentMorph.prototype.prepareToBeGrabbed = function (hand) {
// disassociate from the block I'm posted to
if (this.block) {
this.block.comment = null;
@ -11852,19 +12170,22 @@ CommentMorph.prototype.snap = function (hand) {
if (!(scripts instanceof ScriptsMorph)) {
return null;
}
scripts.clearDropHistory();
scripts.lastDroppedBlock = this;
scripts.clearDropInfo();
target = scripts.closestBlock(this, hand);
if (target !== null) {
target.comment = this;
this.block = target;
if (this.snapSound) {
this.snapSound.play();
}
scripts.lastDropTarget = {element: target};
}
this.align();
scripts.lastDroppedBlock = this;
if (hand) {
scripts.recordDrop(hand.grabOrigin);
}
};
// CommentMorph sticking to blocks
@ -12542,6 +12863,16 @@ ScriptFocusMorph.prototype.sortedScripts = function () {
return scripts;
};
// ScriptFocusMorph undo / redo
ScriptFocusMorph.prototype.undrop = function () {
this.editor.undrop();
};
ScriptFocusMorph.prototype.redrop = function () {
this.editor.redrop();
};
// ScriptFocusMorph block types
ScriptFocusMorph.prototype.blockTypes = function () {
@ -12685,6 +13016,12 @@ ScriptFocusMorph.prototype.reactToKeyEvent = function (key) {
return this.lastScript();
case 'backspace':
return this.deleteLastElement();
case 'ctrl z':
return this.undrop();
case 'ctrl shift z':
return this.redrop();
case 'ctrl [': // ignore the first press of the Mac cmd key
return;
default:
types = this.blockTypes();
if (!(this.element instanceof ScriptsMorph) &&

66
gui.js
Wyświetl plik

@ -72,7 +72,7 @@ isRetinaSupported, SliderMorph*/
// Global stuff ////////////////////////////////////////////////////////
modules.gui = '2016-October-31';
modules.gui = '2016-November-22';
// Declarations
@ -454,6 +454,20 @@ IDE_Morph.prototype.openIn = function (world) {
},
this.cloudError()
);
} else if (location.hash.substr(0, 4) === '#dl:') {
myself.showMessage('Fetching project\nfrom the cloud...');
// make sure to lowercase the username
dict = SnapCloud.parseDict(location.hash.substr(4));
dict.Username = dict.Username.toLowerCase();
SnapCloud.getPublicProject(
SnapCloud.encodeDict(dict),
function (projectData) {
window.open('data:text/xml,' + projectData);
},
this.cloudError()
);
} else if (location.hash.substr(0, 6) === '#lang:') {
urlLanguage = location.hash.substr(6);
this.setLanguage(urlLanguage);
@ -1023,7 +1037,7 @@ IDE_Morph.prototype.createPalette = function (forSearching) {
this.palette.enableAutoScrolling = false;
this.palette.contents.acceptsDrops = false;
this.palette.reactToDropOf = function (droppedMorph) {
this.palette.reactToDropOf = function (droppedMorph, hand) {
if (droppedMorph instanceof DialogBoxMorph) {
myself.world().add(droppedMorph);
} else if (droppedMorph instanceof SpriteMorph) {
@ -1034,11 +1048,25 @@ IDE_Morph.prototype.createPalette = function (forSearching) {
} else if (droppedMorph instanceof CostumeIconMorph) {
myself.currentSprite.wearCostume(null);
droppedMorph.destroy();
} else if (droppedMorph instanceof BlockMorph) {
if (hand && hand.grabOrigin.origin instanceof ScriptsMorph) {
hand.grabOrigin.origin.clearDropInfo();
hand.grabOrigin.origin.lastDroppedBlock = droppedMorph;
hand.grabOrigin.origin.recordDrop(hand.grabOrigin);
}
droppedMorph.destroy();
} else {
droppedMorph.destroy();
}
};
this.palette.contents.reactToDropOf = function (droppedMorph) {
// for "undrop" operation
if (droppedMorph instanceof BlockMorph) {
droppedMorph.destroy();
}
};
this.palette.setWidth(this.logo.width());
this.add(this.palette);
return this.palette;
@ -1947,7 +1975,8 @@ IDE_Morph.prototype.applySavedSettings = function () {
plainprototype = this.getSetting('plainprototype'),
keyboard = this.getSetting('keyboard'),
tables = this.getSetting('tables'),
tableLines = this.getSetting('tableLines');
tableLines = this.getSetting('tableLines'),
autoWrapping = this.getSetting('autowrapping');
// design
if (design === 'flat') {
@ -2008,6 +2037,13 @@ IDE_Morph.prototype.applySavedSettings = function () {
TableMorph.prototype.highContrast = false;
}
// nested auto-wrapping
if (autoWrapping) {
ScriptsMorph.prototype.enableNestedAutoWrapping = true;
} else {
ScriptsMorph.prototype.enableNestedAutoWrapping = false;
}
// plain prototype labels
if (plainprototype) {
BlockLabelPlaceHolderMorph.prototype.plainLabel = true;
@ -2509,6 +2545,22 @@ IDE_Morph.prototype.settingsMenu = function () {
'check for alternative\nGUI design',
false
);
addPreference(
'Nested auto-wrapping',
function () {
ScriptsMorph.prototype.enableNestedAutoWrapping =
!ScriptsMorph.prototype.enableNestedAutoWrapping;
if (ScriptsMorph.prototype.enableNestedAutoWrapping) {
myself.saveSetting('autowrapping', true);
} else {
myself.removeSetting('autowrapping');
}
},
ScriptsMorph.prototype.enableNestedAutoWrapping,
'uncheck to confine auto-wrapping\nto top-level block stacks',
'check to enable auto-wrapping\ninside nested block stacks',
false
);
addPreference(
'Project URLs',
function () {
@ -3049,7 +3101,7 @@ IDE_Morph.prototype.aboutSnap = function () {
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
world = this.world();
aboutTxt = 'Snap! 4.0.9.1\nBuild Your Own Blocks\n\n'
aboutTxt = 'Snap! 4.0.10 - dev -\nBuild Your Own Blocks\n\n'
+ 'Copyright \u24B8 2016 Jens M\u00F6nig and '
+ 'Brian Harvey\n'
+ 'jens@moenig.org, bh@cs.berkeley.edu\n\n'
@ -3579,13 +3631,13 @@ IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
pname = this.projectName || localize('untitled');
html = new XML_Element('html');
html.attributes.lang = SnapTranslator.language;
// html.attributes.contenteditable = 'true';
head = addNode('head', html);
meta = addNode('meta', head);
meta.attributes['http-equiv'] = 'Content-Type';
meta.attributes.content = 'text/html; charset=UTF-8';
meta.attributes.charset = 'UTF-8';
if (useDropShadows) {
css = 'img {' +
@ -3752,7 +3804,7 @@ IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
this.saveFileAs(
'<!DOCTYPE html>' + html.toString(),
'text/html;charset=utf-8,',
'text/html;charset=utf-8',
pname,
true // request opening a new window.
);

Wyświetl plik

@ -3090,3 +3090,48 @@ http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=rotation
161027
------
== v4.0.9 ====
== v4.0.9.1 ====
161110
------
* new Galician translation, yay!! Thanks, tecnoloxia.org!
* Italian translation update
* German translation update
== v4.0.9.2 ====
*** in development ***
161107
------
* New C-Slot auto-wrapping / snapping feature (similar to Scratch)
161109
------
* Blocks, GUI: preference setting to enable auto-wrapping inside nested block stacks
* Blocks: Treat JS-function reporters the same as variable getters wrt rings
* German translation update
161114
------
* Blocks, Objects: Unlimited “Undrop / Redrop” of block drops per script pane and session (under construction)
* GUI: new url switch #dl: for downloading raw shared projects
161121
------
* Blocks: Delete variable getter blocks if the user drops them on template slots (e.g. script vars)
161122
------
* Blocks, GUI: “Undrop / Redrop” for deleting blocks via the context menu or in keyboard edit mode
* Morphic: support “onBeforeDrop” callback parameter in slideBackTo()
161123
------
* Blocks, Morphic: “Undrop / Redrop” support for sticky comments
161124
------
* Morphic, Store: work around a dreaded FF NS_ERROR_FAILURE for supporting retina
* Blocks: drag-origin support for blocks and comments duplicated inside a block editor

Wyświetl plik

@ -185,7 +185,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org', // optional
'last_changed':
'2016-10-27', // this, too, will appear in the Translators tab
'2016-11-22', // this, too, will appear in the Translators tab
// GUI
// control bar:
@ -225,6 +225,8 @@ SnapTranslator.dict.de = {
'Skripte',
'Costumes':
'Kost\u00fcme',
'Backgrounds':
'Hintergr\u00fcnde',
'Sounds':
'Kl\u00e4nge',
@ -815,6 +817,8 @@ SnapTranslator.dict.de = {
'einschalten um IDE-\nAnimationen zu erlauben',
'Flat design':
'Helles Design',
'Nested auto-wrapping':
'Automatisches Umklammern',
'Keyboard Editing':
'Tastaturunterstützung',
'Table support':
@ -929,6 +933,8 @@ SnapTranslator.dict.de = {
'R\u00fcckg\u00e4ngig',
'undo the last\nblock drop\nin this pane':
'Setzen des letzten Blocks\nwiderrufen',
'redrop':
'Wiederherstellen',
'scripts pic...':
'Bild aller Scripte...',
'open a new window\nwith a picture of all scripts':

1909
lang-gl.js 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -185,7 +185,7 @@ SnapTranslator.dict.it = {
'translator_e-mail':
's_federici@yahoo.com, albertofirpo12@gmail.com, zairik@gmail.com', // optional
'last_changed':
'2016-05-10', // this, too, will appear in the Translators tab
'2016-10-31', // this, too, will appear in the Translators tab
// GUI
// control bar:
@ -683,6 +683,11 @@ SnapTranslator.dict.it = {
'enable Morphic\ncontext menus\nand inspectors,\nnot user-friendly!':
'Abilita i menu contestuali\ndi Morphic e l\'inspector,\n non user-friendly',
'Export summary...':
'Esporta sommario...',
'open a new browser browser window\n with a summary of this project':
'apre una nuova finestra del browser\ncon un sommario del progetto',
// project menu
'Project notes...':
'Note di Progetto...',
@ -859,6 +864,12 @@ SnapTranslator.dict.it = {
'Supporto per le tabelle',
'Table lines':
'Tabelle con linee',
'Visible stepping':
'Evidenzia esecuzione',
'uncheck to turn off\nvisible stepping':
'Deseleziona per disattivare la\nevidenziazione dell\'esecuzione',
'check to turn on\n visible stepping (slow)':
'Seleziona per attivare la\nevidenziazione dell\'esecuzione',
'check for multi-column\nlist view support':
'attiva la vista multicolonna',
'uncheck to disable\nmulti-column list views':

Wyświetl plik

@ -42,7 +42,7 @@
/*global modules, contains*/
modules.locale = '2016-October-31';
modules.locale = '2016-November-22';
// Global stuff
@ -160,7 +160,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org',
'last_changed':
'2016-10-27'
'2016-11-22'
};
SnapTranslator.dict.it = {
@ -558,3 +558,14 @@ SnapTranslator.dict.et = {
'last_changed':
'2016-05-03'
};
SnapTranslator.dict.gl = {
'language_name':
'Galego',
'language_translator':
'tecnoloxia',
'translator_e-mail':
'',
'last_changed':
'2016-11-09'
};

Wyświetl plik

@ -1,13 +0,0 @@
CACHE MANIFEST
snap.html
blocks.js
byob.js
gui.js
lists.js
morphic.js
objects.js
threads.js
widgets.js
store.js
xml.js
snap_logo_sm.png

Wyświetl plik

@ -1103,7 +1103,7 @@
/*global window, HTMLCanvasElement, FileReader, Audio, FileList*/
var morphicVersion = '2016-October-27';
var morphicVersion = '2016-November-24';
var modules = {}; // keep track of additional loaded modules
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
@ -1508,9 +1508,9 @@ function enableRetinaSupport() {
return this._isRetinaEnabled;
},
set: function(enabled) {
var prevPixelRatio = getPixelRatio(this);
var prevWidth = this.width;
var prevHeight = this.height;
var prevPixelRatio = getPixelRatio(this),
prevWidth = this.width,
prevHeight = this.height;
this._isRetinaEnabled = enabled;
if (getPixelRatio(this) != prevPixelRatio) {
@ -1526,12 +1526,19 @@ function enableRetinaSupport() {
return uber.width.get.call(this) / getPixelRatio(this);
},
set: function(width) {
var pixelRatio = getPixelRatio(this);
uber.width.set.call(this, width * pixelRatio);
var context = this.getContext('2d');
context.restore();
context.save();
context.scale(pixelRatio, pixelRatio);
try { // workaround one of FF's dreaded NS_ERROR_FAILURE bugs
// this should be taken out as soon as FF gets fixed again
var pixelRatio = getPixelRatio(this),
context;
uber.width.set.call(this, width * pixelRatio);
context = this.getContext('2d');
context.restore();
context.save();
context.scale(pixelRatio, pixelRatio);
} catch (err) {
console.log('Retina Display Support Problem', err);
uber.width.set.call(this, width);
}
}
});
@ -1540,9 +1547,10 @@ function enableRetinaSupport() {
return uber.height.get.call(this) / getPixelRatio(this);
},
set: function(height) {
var pixelRatio = getPixelRatio(this);
var pixelRatio = getPixelRatio(this),
context;
uber.height.set.call(this, height * pixelRatio);
var context = this.getContext('2d');
context = this.getContext('2d');
context.restore();
context.save();
context.scale(pixelRatio, pixelRatio);
@ -3605,7 +3613,7 @@ Morph.prototype.situation = function () {
return null;
};
Morph.prototype.slideBackTo = function (situation, inSteps) {
Morph.prototype.slideBackTo = function (situation, inSteps, onBeforeDrop) {
var steps = inSteps || 5,
pos = situation.origin.position().add(situation.position),
xStep = -(this.left() - pos.x) / steps,
@ -3621,6 +3629,8 @@ Morph.prototype.slideBackTo = function (situation, inSteps) {
stepCount += 1;
if (stepCount === steps) {
situation.origin.add(myself);
if (onBeforeDrop) {onBeforeDrop(); }
if (myself.justDropped) {myself.justDropped(); }
if (situation.origin.reactToDropOf) {
situation.origin.reactToDropOf(myself);
}

Wyświetl plik

@ -82,7 +82,7 @@ SpeechBubbleMorph, RingMorph, isNil, FileReader, TableDialogMorph,
BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph*/
modules.objects = '2016-October-27';
modules.objects = '2016-November-22';
var SpriteMorph;
var StageMorph;
@ -5629,6 +5629,14 @@ StageMorph.prototype.fireKeyEvent = function (key) {
if (!ide.isAppMode) {ide.currentSprite.searchBlocks(); }
return;
}
if (evt === 'ctrl z') {
if (!ide.isAppMode) {ide.currentSprite.scripts.undrop(); }
return;
}
if (evt === 'ctrl shift z') {
if (!ide.isAppMode) {ide.currentSprite.scripts.redrop(); }
return;
}
if (evt === 'ctrl n') {
if (!ide.isAppMode) {ide.createNewProject(); }
return;

Wyświetl plik

@ -61,7 +61,7 @@ normalizeCanvas*/
// Global stuff ////////////////////////////////////////////////////////
modules.store = '2016-October-27';
modules.store = '2016-November-24';
// XML_Serializer ///////////////////////////////////////////////////////
@ -390,10 +390,12 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
if (model.pentrails) {
project.pentrails = new Image();
project.pentrails.onload = function () {
normalizeCanvas(project.stage.trailsCanvas);
var context = project.stage.trailsCanvas.getContext('2d');
context.drawImage(project.pentrails, 0, 0);
project.stage.changed();
if (project.stage.trailsCanvas) { // work-around a bug in FF
normalizeCanvas(project.stage.trailsCanvas);
var context = project.stage.trailsCanvas.getContext('2d');
context.drawImage(project.pentrails, 0, 0);
project.stage.changed();
}
};
project.pentrails.src = model.pentrails.contents;
}
@ -1128,7 +1130,10 @@ SnapSerializer.prototype.loadInput = function (model, input, block) {
input.setColor(this.loadColor(model.contents));
} else {
val = this.loadValue(model);
if (!isNil(val) && input.setContents) {
if (!isNil(val) && !isNil(input) && input.setContents) {
// checking whether "input" is nil should not
// be necessary, but apparently is after retina support
// was added.
input.setContents(this.loadValue(model));
}
}