kopia lustrzana https://github.com/backface/turtlestitch
auto-wrapping
also: treat JS-function blocks the same as variable getters wrt rings, i.e. auto-remove the ring in a CALL block when dropping a JS-function block on itpull/29/head
rodzic
1a6aff47dd
commit
50e94a93ad
132
blocks.js
132
blocks.js
|
@ -149,7 +149,7 @@ isSnapObject, copy, PushButtonMorph, SpriteIconMorph, Process*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.blocks = '2016-October-31';
|
||||
modules.blocks = '2016-November-10';
|
||||
|
||||
var SyntaxElementMorph;
|
||||
var BlockMorph;
|
||||
|
@ -3709,6 +3709,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 +3736,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 +3805,8 @@ CommandBlockMorph.prototype.closestAttachTarget = function (newParent) {
|
|||
),
|
||||
dist,
|
||||
ref = [],
|
||||
minDist = 1000;
|
||||
minDist = 1000,
|
||||
wrap;
|
||||
|
||||
if (!(this instanceof HatBlockMorph)) {
|
||||
ref.push(
|
||||
|
@ -3789,6 +3815,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 +3833,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;
|
||||
|
@ -3816,6 +3855,7 @@ CommandBlockMorph.prototype.closestAttachTarget = function (newParent) {
|
|||
CommandBlockMorph.prototype.snap = function () {
|
||||
var target = this.closestAttachTarget(),
|
||||
scripts = this.parentThatIsA(ScriptsMorph),
|
||||
before,
|
||||
next,
|
||||
offsetY,
|
||||
affected;
|
||||
|
@ -3860,6 +3900,31 @@ 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') {
|
||||
var 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();
|
||||
|
@ -5159,7 +5224,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 +5283,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 +5303,7 @@ ScriptsMorph.prototype.init = function (owner) {
|
|||
this.lastDropTarget = null;
|
||||
this.lastPreservedBlocks = null;
|
||||
this.lastNextBlock = null;
|
||||
this.lastWrapParent = null;
|
||||
|
||||
// keyboard editing support:
|
||||
this.focus = null;
|
||||
|
@ -5347,6 +5417,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 +5477,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(),
|
||||
|
@ -5697,6 +5789,29 @@ ScriptsMorph.prototype.undrop = function () {
|
|||
}
|
||||
} else if (this.lastDropTarget.loc === 'top') {
|
||||
this.add(this.lastDropTarget.element);
|
||||
} else if (this.lastDropTarget.loc === 'wrap') {
|
||||
var cslot = detect( // could be cached...
|
||||
this.lastDroppedBlock.inputs(), // ...although these are
|
||||
function (each) {return each instanceof CSlotMorph; }
|
||||
);
|
||||
if (this.lastWrapParent instanceof CommandBlockMorph) {
|
||||
this.lastWrapParent.nextBlock(
|
||||
this.lastDropTarget.element
|
||||
);
|
||||
} else if (this.lastWrapParent instanceof CommandSlotMorph) {
|
||||
this.lastWrapParent.nestedBlock(
|
||||
this.lastDropTarget.element
|
||||
);
|
||||
} else {
|
||||
this.add(this.lastDropTarget.element);
|
||||
}
|
||||
|
||||
// fix zebra coloring.
|
||||
// this could be generalized into the fixBlockColor mechanism
|
||||
this.lastDropTarget.element.blockSequence().forEach(
|
||||
function (cmd) {cmd.fixBlockColor(); }
|
||||
);
|
||||
cslot.fixLayout();
|
||||
}
|
||||
}
|
||||
} else { // ReporterBlockMorph
|
||||
|
@ -5717,13 +5832,13 @@ ScriptsMorph.prototype.undrop = function () {
|
|||
this.clearDropHistory();
|
||||
};
|
||||
|
||||
|
||||
ScriptsMorph.prototype.clearDropHistory = function () {
|
||||
this.lastDroppedBlock = null;
|
||||
this.lastReplacedInput = null;
|
||||
this.lastDropTarget = null;
|
||||
this.lastPreservedBlocks = null;
|
||||
this.lastNextBlock = null;
|
||||
this.lastWrapParent = null;
|
||||
};
|
||||
|
||||
// ScriptsMorph sorting blocks and comments
|
||||
|
@ -5860,7 +5975,6 @@ ArgMorph.prototype.reactToSliderEdit = function () {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
// ArgMorph drag & drop: for demo puposes only
|
||||
|
||||
ArgMorph.prototype.justDropped = function () {
|
||||
|
|
28
gui.js
28
gui.js
|
@ -1947,7 +1947,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 +2009,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 +2517,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 +3073,7 @@ IDE_Morph.prototype.aboutSnap = function () {
|
|||
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
|
||||
world = this.world();
|
||||
|
||||
aboutTxt = 'Snap! 4.0.9.2\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'
|
||||
|
|
|
@ -817,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':
|
||||
|
|
Ładowanie…
Reference in New Issue