kopia lustrzana https://github.com/backface/turtlestitch
Merge branch 'manual-chapter2' into manual-chapter3
commit
c04698ea26
17
byob.js
17
byob.js
|
@ -102,11 +102,11 @@ ArrowMorph, PushButtonMorph, contains, InputSlotMorph, ShadowMorph,
|
|||
ToggleButtonMorph, IDE_Morph, MenuMorph, copy, ToggleElementMorph,
|
||||
Morph, fontHeight, StageMorph, SyntaxElementMorph, SnapSerializer,
|
||||
CommentMorph, localize, CSlotMorph, SpeechBubbleMorph, MorphicPreferences,
|
||||
SymbolMorph, isNil*/
|
||||
SymbolMorph, isNil, CursorMorph*/
|
||||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.byob = '2015-June-25';
|
||||
modules.byob = '2015-July-28';
|
||||
|
||||
// Declarations
|
||||
|
||||
|
@ -1727,8 +1727,9 @@ BlockEditorMorph.prototype.popUp = function () {
|
|||
|
||||
// BlockEditorMorph ops
|
||||
|
||||
BlockEditorMorph.prototype.accept = function () {
|
||||
BlockEditorMorph.prototype.accept = function (origin) {
|
||||
// check DialogBoxMorph comment for accept()
|
||||
if (origin instanceof CursorMorph) {return; }
|
||||
if (this.action) {
|
||||
if (typeof this.target === 'function') {
|
||||
if (typeof this.action === 'function') {
|
||||
|
@ -1747,7 +1748,8 @@ BlockEditorMorph.prototype.accept = function () {
|
|||
this.close();
|
||||
};
|
||||
|
||||
BlockEditorMorph.prototype.cancel = function () {
|
||||
BlockEditorMorph.prototype.cancel = function (origin) {
|
||||
if (origin instanceof CursorMorph) {return; }
|
||||
//this.refreshAllBlockInstances();
|
||||
this.close();
|
||||
};
|
||||
|
@ -1966,8 +1968,13 @@ PrototypeHatBlockMorph.prototype.init = function (definition) {
|
|||
|
||||
PrototypeHatBlockMorph.prototype.mouseClickLeft = function () {
|
||||
// relay the mouse click to my prototype block to
|
||||
// pop-up a Block Dialog
|
||||
// pop-up a Block Dialog, unless the shift key
|
||||
// is pressed, in which case initiate keyboard
|
||||
// editing support
|
||||
|
||||
if (this.world().currentKey === 16) { // shift-clicked
|
||||
return this.focus();
|
||||
}
|
||||
this.children[0].mouseClickLeft();
|
||||
};
|
||||
|
||||
|
|
349
gui.js
349
gui.js
|
@ -43,6 +43,7 @@
|
|||
TurtleIconMorph
|
||||
CostumeIconMorph
|
||||
WardrobeMorph
|
||||
StageHandleMorph;
|
||||
|
||||
|
||||
credits
|
||||
|
@ -65,11 +66,11 @@ ScriptsMorph, isNil, SymbolMorph, BlockExportDialogMorph,
|
|||
BlockImportDialogMorph, SnapTranslator, localize, List, InputSlotMorph,
|
||||
SnapCloud, Uint8Array, HandleMorph, SVG_Costume, fontHeight, hex_sha512,
|
||||
sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph, Audio,
|
||||
SpeechBubbleMorph*/
|
||||
SpeechBubbleMorph, ScriptFocusMorph*/
|
||||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.gui = '2015-June-25';
|
||||
modules.gui = '2015-July-28';
|
||||
|
||||
// Declarations
|
||||
|
||||
|
@ -81,11 +82,18 @@ var TurtleIconMorph;
|
|||
var WardrobeMorph;
|
||||
var SoundIconMorph;
|
||||
var JukeboxMorph;
|
||||
var StageHandleMorph;
|
||||
|
||||
// Get the full url without "snap.html"
|
||||
var baseUrl = document.URL.split('/');
|
||||
baseUrl.pop(baseUrl.length - 1);
|
||||
baseUrl = baseUrl.join('/') + '/';
|
||||
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 ///////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -230,6 +238,7 @@ IDE_Morph.prototype.init = function (isAutoFill) {
|
|||
this.spriteBar = null;
|
||||
this.spriteEditor = null;
|
||||
this.stage = null;
|
||||
this.stageHandle = null;
|
||||
this.corralBar = null;
|
||||
this.corral = null;
|
||||
|
||||
|
@ -975,9 +984,7 @@ IDE_Morph.prototype.createPalette = function (forSearching) {
|
|||
|
||||
IDE_Morph.prototype.createStage = function () {
|
||||
// assumes that the logo pane has already been created
|
||||
if (this.stage) {
|
||||
this.stage.destroy();
|
||||
}
|
||||
if (this.stage) {this.stage.destroy(); }
|
||||
StageMorph.prototype.frameRate = 0;
|
||||
this.stage = new StageMorph(this.globalVariables);
|
||||
this.stage.setExtent(this.stage.dimensions); // dimensions are fixed
|
||||
|
@ -992,6 +999,13 @@ IDE_Morph.prototype.createStage = function () {
|
|||
this.add(this.stage);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.createStageHandle = function () {
|
||||
// assumes that the stage has already been created
|
||||
if (this.stageHandle) {this.stageHandle.destroy(); }
|
||||
this.stageHandle = new StageHandleMorph(this.stage);
|
||||
this.add(this.stageHandle);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.createSpriteBar = function () {
|
||||
// assumes that the categories pane has already been created
|
||||
var rotationStyleButtons = [],
|
||||
|
@ -1355,6 +1369,7 @@ IDE_Morph.prototype.createCorral = function () {
|
|||
// assumes the corral bar has already been created
|
||||
var frame, template, padding = 5, myself = this;
|
||||
|
||||
this.createStageHandle();
|
||||
if (this.corral) {
|
||||
this.corral.destroy();
|
||||
}
|
||||
|
@ -1486,10 +1501,10 @@ IDE_Morph.prototype.fixLayout = function (situation) {
|
|||
) * 10) / 10);
|
||||
this.stage.setCenter(this.center());
|
||||
} else {
|
||||
// this.stage.setScale(this.isSmallStage ? 0.5 : 1);
|
||||
this.stage.setScale(this.isSmallStage ? this.stageRatio : 1);
|
||||
this.stage.setTop(this.logo.bottom() + padding);
|
||||
this.stage.setRight(this.right());
|
||||
this.stageHandle.fixLayout();
|
||||
}
|
||||
|
||||
// spriteBar
|
||||
|
@ -1538,7 +1553,12 @@ IDE_Morph.prototype.setProjectName = function (string) {
|
|||
IDE_Morph.prototype.setExtent = function (point) {
|
||||
var padding = new Point(430, 110),
|
||||
minExt,
|
||||
ext;
|
||||
ext,
|
||||
maxWidth,
|
||||
minWidth,
|
||||
maxHeight,
|
||||
minRatio,
|
||||
maxRatio;
|
||||
|
||||
// determine the minimum dimensions making sense for the current mode
|
||||
if (this.isAppMode) {
|
||||
|
@ -1546,21 +1566,29 @@ IDE_Morph.prototype.setExtent = function (point) {
|
|||
this.controlBar.height() + 10
|
||||
);
|
||||
} else {
|
||||
/* // auto-switches to small stage mode, commented out b/c I don't like it
|
||||
if (point.x < 910) {
|
||||
this.isSmallStage = true;
|
||||
this.stageRatio = 0.5;
|
||||
if (this.stageRatio > 1) {
|
||||
minExt = padding.add(StageMorph.prototype.dimensions);
|
||||
} else {
|
||||
minExt = padding.add(
|
||||
StageMorph.prototype.dimensions.multiplyBy(this.stageRatio)
|
||||
);
|
||||
}
|
||||
*/
|
||||
minExt = this.isSmallStage ?
|
||||
padding.add(StageMorph.prototype.dimensions.divideBy(2))
|
||||
: padding.add(StageMorph.prototype.dimensions);
|
||||
/*
|
||||
minExt = this.isSmallStage ?
|
||||
new Point(700, 350) : new Point(910, 490);
|
||||
*/
|
||||
}
|
||||
ext = point.max(minExt);
|
||||
|
||||
// adjust stage ratio if necessary
|
||||
maxWidth = ext.x - (this.spriteBar.tabBar.fullBounds().right() -
|
||||
this.left());
|
||||
minWidth = SpriteIconMorph.prototype.thumbSize.x * 3;
|
||||
maxHeight = (ext.y - SpriteIconMorph.prototype.thumbSize.y * 3.5);
|
||||
minRatio = minWidth / this.stage.dimensions.x;
|
||||
maxRatio = Math.min(
|
||||
(maxWidth / this.stage.dimensions.x),
|
||||
(maxHeight / this.stage.dimensions.y)
|
||||
);
|
||||
this.stageRatio = Math.min(maxRatio, Math.max(minRatio, this.stageRatio));
|
||||
|
||||
// apply
|
||||
IDE_Morph.uber.setExtent.call(this, ext);
|
||||
this.fixLayout();
|
||||
};
|
||||
|
@ -1746,6 +1774,9 @@ IDE_Morph.prototype.stopAllScripts = function () {
|
|||
};
|
||||
|
||||
IDE_Morph.prototype.selectSprite = function (sprite) {
|
||||
if (this.currentSprite && this.currentSprite.scripts.focus) {
|
||||
this.currentSprite.scripts.focus.stopEditing();
|
||||
}
|
||||
this.currentSprite = sprite;
|
||||
this.createPalette();
|
||||
this.createSpriteBar();
|
||||
|
@ -1800,7 +1831,8 @@ IDE_Morph.prototype.applySavedSettings = function () {
|
|||
click = this.getSetting('click'),
|
||||
longform = this.getSetting('longform'),
|
||||
longurls = this.getSetting('longurls'),
|
||||
plainprototype = this.getSetting('plainprototype');
|
||||
plainprototype = this.getSetting('plainprototype'),
|
||||
keyboard = this.getSetting('keyboard');
|
||||
|
||||
// design
|
||||
if (design === 'flat') {
|
||||
|
@ -1840,6 +1872,13 @@ IDE_Morph.prototype.applySavedSettings = function () {
|
|||
this.projectsInURLs = false;
|
||||
}
|
||||
|
||||
// keyboard editing
|
||||
if (keyboard) {
|
||||
ScriptsMorph.prototype.enableKeyboard = true;
|
||||
} else {
|
||||
ScriptsMorph.prototype.enableKeyboard = false;
|
||||
}
|
||||
|
||||
// plain prototype labels
|
||||
if (plainprototype) {
|
||||
BlockLabelPlaceHolderMorph.prototype.plainLabel = true;
|
||||
|
@ -2346,6 +2385,22 @@ IDE_Morph.prototype.settingsMenu = function () {
|
|||
'check to enable\nsprite composition',
|
||||
true
|
||||
);
|
||||
addPreference(
|
||||
'Keyboard Editing',
|
||||
function () {
|
||||
ScriptsMorph.prototype.enableKeyboard =
|
||||
!ScriptsMorph.prototype.enableKeyboard;
|
||||
if (ScriptsMorph.prototype.enableKeyboard) {
|
||||
myself.saveSetting('keyboard', true);
|
||||
} else {
|
||||
myself.removeSetting('keyboard');
|
||||
}
|
||||
},
|
||||
ScriptsMorph.prototype.enableKeyboard,
|
||||
'uncheck to disable\nkeyboard editing support',
|
||||
'check to enable\nkeyboard editing support',
|
||||
false
|
||||
);
|
||||
menu.addLine(); // everything below this line is stored in the project
|
||||
addPreference(
|
||||
'Thread safe scripts',
|
||||
|
@ -2385,6 +2440,20 @@ IDE_Morph.prototype.settingsMenu = function () {
|
|||
'check for block\nto text mapping features',
|
||||
false
|
||||
);
|
||||
addPreference(
|
||||
'Inheritance support',
|
||||
function () {
|
||||
StageMorph.prototype.enableInheritance =
|
||||
!StageMorph.prototype.enableInheritance;
|
||||
myself.currentSprite.blocksCache.variables = null;
|
||||
myself.currentSprite.paletteCache.variables = null;
|
||||
myself.refreshPalette();
|
||||
},
|
||||
StageMorph.prototype.enableInheritance,
|
||||
'uncheck to disable\nsprite inheritance features',
|
||||
'check for sprite\ninheritance features',
|
||||
false
|
||||
);
|
||||
menu.popup(world, pos);
|
||||
};
|
||||
|
||||
|
@ -2497,10 +2566,10 @@ IDE_Morph.prototype.projectMenu = function () {
|
|||
function () {
|
||||
// read a list of libraries from an external file,
|
||||
var libMenu = new MenuMorph(this, 'Import library'),
|
||||
libUrl = baseUrl + 'libraries/' + 'LIBRARIES';
|
||||
libUrl = baseURL + 'libraries/' + 'LIBRARIES';
|
||||
|
||||
function loadLib(name) {
|
||||
var url = baseUrl + 'libraries/' + name + '.xml';
|
||||
var url = baseURL + 'libraries/' + name + '.xml';
|
||||
myself.droppedText(myself.getURL(url), name);
|
||||
}
|
||||
|
||||
|
@ -2617,7 +2686,7 @@ IDE_Morph.prototype.aboutSnap = function () {
|
|||
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
|
||||
world = this.world();
|
||||
|
||||
aboutTxt = 'Snap! 4.0.1\nBuild Your Own Blocks\n\n'
|
||||
aboutTxt = 'Snap! 4.0.2\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'
|
||||
|
@ -2834,6 +2903,7 @@ IDE_Morph.prototype.newProject = function () {
|
|||
StageMorph.prototype.codeMappings = {};
|
||||
StageMorph.prototype.codeHeaders = {};
|
||||
StageMorph.prototype.enableCodeMapping = false;
|
||||
StageMorph.prototype.enableInheritance = false;
|
||||
SpriteMorph.prototype.useFlatLineEnds = false;
|
||||
this.setProjectName('');
|
||||
this.projectNotes = '';
|
||||
|
@ -3053,6 +3123,7 @@ IDE_Morph.prototype.rawOpenProjectString = function (str) {
|
|||
StageMorph.prototype.codeMappings = {};
|
||||
StageMorph.prototype.codeHeaders = {};
|
||||
StageMorph.prototype.enableCodeMapping = false;
|
||||
StageMorph.prototype.enableInheritance = false;
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
this.serializer.openProject(
|
||||
|
@ -3094,6 +3165,7 @@ IDE_Morph.prototype.rawOpenCloudDataString = function (str) {
|
|||
StageMorph.prototype.codeMappings = {};
|
||||
StageMorph.prototype.codeHeaders = {};
|
||||
StageMorph.prototype.enableCodeMapping = false;
|
||||
StageMorph.prototype.enableInheritance = false;
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
model = this.serializer.parse(str);
|
||||
|
@ -3417,6 +3489,7 @@ IDE_Morph.prototype.toggleAppMode = function (appMode) {
|
|||
this.controlBar.projectButton,
|
||||
this.controlBar.settingsButton,
|
||||
this.controlBar.stageSizeButton,
|
||||
this.stageHandle,
|
||||
this.corral,
|
||||
this.corralBar,
|
||||
this.spriteEditor,
|
||||
|
@ -3440,6 +3513,9 @@ IDE_Morph.prototype.toggleAppMode = function (appMode) {
|
|||
morph.hide();
|
||||
}
|
||||
});
|
||||
if (world.keyboardReceiver instanceof ScriptFocusMorph) {
|
||||
world.keyboardReceiver.stopEditing();
|
||||
}
|
||||
} else {
|
||||
this.setColor(this.backgroundColor);
|
||||
this.controlBar.setColor(this.frameColor);
|
||||
|
@ -3476,36 +3552,32 @@ IDE_Morph.prototype.toggleStageSize = function (isSmall) {
|
|||
var myself = this,
|
||||
smallRatio = 0.5,
|
||||
world = this.world(),
|
||||
shiftClicked = (world.currentKey === 16);
|
||||
shiftClicked = (world.currentKey === 16),
|
||||
altClicked = (world.currentKey === 18);
|
||||
|
||||
function toggle() {
|
||||
myself.isSmallStage = isNil(isSmall) ? !myself.isSmallStage : isSmall;
|
||||
}
|
||||
|
||||
function zoomIn() {
|
||||
myself.step = function () {
|
||||
myself.stageRatio -= (myself.stageRatio - smallRatio) / 2;
|
||||
myself.setExtent(world.extent());
|
||||
if (myself.stageRatio < (smallRatio + 0.1)) {
|
||||
myself.stageRatio = smallRatio;
|
||||
myself.setExtent(world.extent());
|
||||
delete myself.step;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function zoomOut() {
|
||||
function zoomTo(targetRatio) {
|
||||
var count = 1,
|
||||
steps = 5;
|
||||
myself.fps = 30;
|
||||
myself.isSmallStage = true;
|
||||
myself.step = function () {
|
||||
myself.stageRatio += (1 - myself.stageRatio) / 2;
|
||||
myself.setExtent(world.extent());
|
||||
if (myself.stageRatio > 0.9) {
|
||||
myself.stageRatio = 1;
|
||||
myself.isSmallStage = false;
|
||||
myself.setExtent(world.extent());
|
||||
myself.controlBar.stageSizeButton.refresh();
|
||||
var diff;
|
||||
if (count >= steps) {
|
||||
myself.stageRatio = targetRatio;
|
||||
delete myself.step;
|
||||
myself.fps = 0;
|
||||
myself.isSmallStage = !(targetRatio === 1);
|
||||
myself.controlBar.stageSizeButton.refresh();
|
||||
} else {
|
||||
count += 1;
|
||||
diff = (targetRatio - myself.stageRatio) / 2;
|
||||
myself.stageRatio += diff;
|
||||
}
|
||||
myself.setExtent(world.extent());
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3515,14 +3587,20 @@ IDE_Morph.prototype.toggleStageSize = function (isSmall) {
|
|||
if (!this.isSmallStage || (smallRatio === this.stageRatio)) {
|
||||
toggle();
|
||||
}
|
||||
} else if (altClicked) {
|
||||
smallRatio = this.width() / 2 /
|
||||
this.stage.dimensions.x;
|
||||
if (!this.isSmallStage || (smallRatio === this.stageRatio)) {
|
||||
toggle();
|
||||
}
|
||||
} else {
|
||||
toggle();
|
||||
}
|
||||
if (this.isAnimating) {
|
||||
if (this.isSmallStage) {
|
||||
zoomIn();
|
||||
zoomTo(smallRatio);
|
||||
} else {
|
||||
zoomOut();
|
||||
zoomTo(1);
|
||||
}
|
||||
} else {
|
||||
if (this.isSmallStage) {this.stageRatio = smallRatio; }
|
||||
|
@ -4219,7 +4297,7 @@ IDE_Morph.prototype.getURLsbeOrRelative = function (url) {
|
|||
var request = new XMLHttpRequest(),
|
||||
myself = this;
|
||||
try {
|
||||
request.open('GET', baseUrl + url, false);
|
||||
request.open('GET', baseURL + url, false);
|
||||
request.send();
|
||||
if (request.status === 200) {
|
||||
return request.responseText;
|
||||
|
@ -4660,7 +4738,7 @@ ProjectDialogMorph.prototype.setSource = function (source) {
|
|||
myself.nameField.setContents(item.name || '');
|
||||
}
|
||||
src = myself.ide.getURL(
|
||||
baseUrl + 'Examples/' + item.name + '.xml'
|
||||
baseURL + 'Examples/' + item.name + '.xml'
|
||||
);
|
||||
|
||||
xml = myself.ide.serializer.parse(src);
|
||||
|
@ -4714,9 +4792,9 @@ ProjectDialogMorph.prototype.getLocalProjectList = function () {
|
|||
ProjectDialogMorph.prototype.getExamplesProjectList = function () {
|
||||
var dir,
|
||||
projects = [];
|
||||
//alert(baseUrl);
|
||||
//alert(baseURL);
|
||||
|
||||
dir = this.ide.getURL(baseUrl + 'Examples/');
|
||||
dir = this.ide.getURL(baseURL + 'Examples/');
|
||||
dir.split('\n').forEach(
|
||||
function (line) {
|
||||
var startIdx = line.search(new RegExp('href=".*xml"')),
|
||||
|
@ -4835,7 +4913,7 @@ 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');
|
||||
src = this.ide.getURL(baseURL + 'Examples/' + proj.name + '.xml');
|
||||
this.ide.openProjectString(src);
|
||||
this.destroy();
|
||||
} else { // 'local'
|
||||
|
@ -5042,7 +5120,7 @@ ProjectDialogMorph.prototype.shareProject = function () {
|
|||
projectId = 'Username=' +
|
||||
encodeURIComponent(usr.toLowerCase()) +
|
||||
'&ProjectName=' +
|
||||
encodeURIComponent(proj.projectName);
|
||||
encodeURIComponent(proj.ProjectName);
|
||||
location.hash = projectId;
|
||||
}
|
||||
},
|
||||
|
@ -5214,7 +5292,7 @@ function SpriteIconMorph(aSprite, aTemplate) {
|
|||
}
|
||||
|
||||
SpriteIconMorph.prototype.init = function (aSprite, aTemplate) {
|
||||
var colors, action, query, myself = this;
|
||||
var colors, action, query, hover, myself = this;
|
||||
|
||||
if (!aTemplate) {
|
||||
colors = [
|
||||
|
@ -5244,6 +5322,11 @@ SpriteIconMorph.prototype.init = function (aSprite, aTemplate) {
|
|||
return false;
|
||||
};
|
||||
|
||||
hover = function () {
|
||||
if (!aSprite.exemplar) {return null; }
|
||||
return (localize('parent' + ':\n' + aSprite.exemplar.name));
|
||||
};
|
||||
|
||||
// additional properties:
|
||||
this.object = aSprite || new SpriteMorph(); // mandatory, actually
|
||||
this.version = this.object.version;
|
||||
|
@ -5259,7 +5342,7 @@ SpriteIconMorph.prototype.init = function (aSprite, aTemplate) {
|
|||
this.object.name, // label string
|
||||
query, // predicate/selector
|
||||
null, // environment
|
||||
null, // hint
|
||||
hover, // hint
|
||||
aTemplate // optional, for cached background images
|
||||
);
|
||||
|
||||
|
@ -5430,6 +5513,9 @@ SpriteIconMorph.prototype.userMenu = function () {
|
|||
menu.addItem("duplicate", 'duplicateSprite');
|
||||
menu.addItem("delete", 'removeSprite');
|
||||
menu.addLine();
|
||||
if (StageMorph.prototype.enableInheritance) {
|
||||
menu.addItem("parent...", 'chooseExemplar');
|
||||
}
|
||||
if (this.object.anchor) {
|
||||
menu.addItem(
|
||||
localize('detach from') + ' ' + this.object.anchor.name,
|
||||
|
@ -5464,6 +5550,10 @@ SpriteIconMorph.prototype.exportSprite = function () {
|
|||
this.object.exportSprite();
|
||||
};
|
||||
|
||||
SpriteIconMorph.prototype.chooseExemplar = function () {
|
||||
this.object.chooseExemplar();
|
||||
};
|
||||
|
||||
SpriteIconMorph.prototype.showSpriteOnStage = function () {
|
||||
this.object.showOnStage();
|
||||
};
|
||||
|
@ -6483,3 +6573,148 @@ JukeboxMorph.prototype.reactToDropOf = function (icon) {
|
|||
this.sprite.sounds.add(costume, idx);
|
||||
this.updateList();
|
||||
};
|
||||
|
||||
// StageHandleMorph ////////////////////////////////////////////////////////
|
||||
|
||||
// I am a horizontal resizing handle for a StageMorph
|
||||
|
||||
// StageHandleMorph inherits from Morph:
|
||||
|
||||
StageHandleMorph.prototype = new Morph();
|
||||
StageHandleMorph.prototype.constructor = StageHandleMorph;
|
||||
StageHandleMorph.uber = Morph.prototype;
|
||||
|
||||
// StageHandleMorph instance creation:
|
||||
|
||||
function StageHandleMorph(target) {
|
||||
this.init(target);
|
||||
}
|
||||
|
||||
StageHandleMorph.prototype.init = function (target) {
|
||||
this.target = target || null;
|
||||
HandleMorph.uber.init.call(this);
|
||||
this.color = MorphicPreferences.isFlat ?
|
||||
IDE_Morph.prototype.groupColor : new Color(190, 190, 190);
|
||||
this.isDraggable = false;
|
||||
this.noticesTransparentClick = true;
|
||||
this.setExtent(new Point(12, 50));
|
||||
};
|
||||
|
||||
// StageHandleMorph drawing:
|
||||
|
||||
StageHandleMorph.prototype.drawNew = function () {
|
||||
this.normalImage = newCanvas(this.extent());
|
||||
this.highlightImage = newCanvas(this.extent());
|
||||
this.drawOnCanvas(
|
||||
this.normalImage,
|
||||
this.color
|
||||
);
|
||||
this.drawOnCanvas(
|
||||
this.highlightImage,
|
||||
MorphicPreferences.isFlat ?
|
||||
new Color(245, 245, 255) : new Color(100, 100, 255),
|
||||
this.color
|
||||
);
|
||||
this.image = this.normalImage;
|
||||
this.fixLayout();
|
||||
};
|
||||
|
||||
StageHandleMorph.prototype.drawOnCanvas = function (
|
||||
aCanvas,
|
||||
color,
|
||||
shadowColor
|
||||
) {
|
||||
var context = aCanvas.getContext('2d'),
|
||||
l = aCanvas.height / 8,
|
||||
w = aCanvas.width / 6,
|
||||
r = w / 2,
|
||||
x,
|
||||
y,
|
||||
i;
|
||||
|
||||
context.lineWidth = w;
|
||||
context.lineCap = 'round';
|
||||
y = aCanvas.height / 2;
|
||||
|
||||
context.strokeStyle = color.toString();
|
||||
x = aCanvas.width / 12;
|
||||
for (i = 0; i < 3; i += 1) {
|
||||
if (i > 0) {
|
||||
context.beginPath();
|
||||
context.moveTo(x, y - (l - r));
|
||||
context.lineTo(x, y + (l - r));
|
||||
context.stroke();
|
||||
}
|
||||
x += (w * 2);
|
||||
l *= 2;
|
||||
}
|
||||
if (shadowColor) {
|
||||
context.strokeStyle = shadowColor.toString();
|
||||
x = aCanvas.width / 12 + w;
|
||||
l = aCanvas.height / 8;
|
||||
for (i = 0; i < 3; i += 1) {
|
||||
if (i > 0) {
|
||||
context.beginPath();
|
||||
context.moveTo(x, y - (l - r));
|
||||
context.lineTo(x, y + (l - r));
|
||||
context.stroke();
|
||||
}
|
||||
x += (w * 2);
|
||||
l *= 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// StageHandleMorph layout:
|
||||
|
||||
StageHandleMorph.prototype.fixLayout = function () {
|
||||
if (!this.target) {return; }
|
||||
var ide = this.target.parentThatIsA(IDE_Morph);
|
||||
this.setTop(this.target.top() + 10);
|
||||
this.setRight(this.target.left());
|
||||
if (ide) {ide.add(this); } // come to front
|
||||
};
|
||||
|
||||
// StageHandleMorph stepping:
|
||||
|
||||
StageHandleMorph.prototype.step = null;
|
||||
|
||||
StageHandleMorph.prototype.mouseDownLeft = function (pos) {
|
||||
var world = this.world(),
|
||||
offset = this.right() - pos.x,
|
||||
myself = this,
|
||||
ide = this.target.parentThatIsA(IDE_Morph);
|
||||
|
||||
if (!this.target) {
|
||||
return null;
|
||||
}
|
||||
ide.isSmallStage = true;
|
||||
ide.controlBar.stageSizeButton.refresh();
|
||||
this.step = function () {
|
||||
var newPos, newWidth;
|
||||
if (world.hand.mouseButton) {
|
||||
newPos = world.hand.bounds.origin.x + offset;
|
||||
newWidth = myself.target.right() - newPos;
|
||||
ide.stageRatio = newWidth / myself.target.dimensions.x;
|
||||
ide.setExtent(world.extent());
|
||||
|
||||
} else {
|
||||
this.step = null;
|
||||
ide.isSmallStage = !(ide.stageRatio === 1);
|
||||
ide.controlBar.stageSizeButton.refresh();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// StageHandleMorph events:
|
||||
|
||||
StageHandleMorph.prototype.mouseEnter = function () {
|
||||
this.image = this.highlightImage;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
StageHandleMorph.prototype.mouseLeave = function () {
|
||||
this.image = this.normalImage;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
|
|
Plik binarny nie jest wyświetlany.
29
history.txt
29
history.txt
|
@ -2522,8 +2522,35 @@ ______
|
|||
* Morphic, Objects, Blocks, XML: Optimizations and dramatic speed-up. Thanks, Nathan!!
|
||||
* Objects: push maximum clone count up to 1000, tweak Note::play
|
||||
|
||||
=== Start with v4.0.1 ===
|
||||
=== v4.0.1 (unreleased) ===
|
||||
|
||||
150626
|
||||
------
|
||||
* Morphic: Fix Inspector duplication, update documentation
|
||||
|
||||
150727
|
||||
------
|
||||
* Polish translation update, thanks, Bartosz Leper!
|
||||
* Turkish translation. Yay!! Thanks, Hakan Ataş!
|
||||
* Hungarian translation. Yay!! Thanks, Makány György!
|
||||
* GUI: relative-url fixes, Thanks, Michael!
|
||||
* Morphic: enable exporting a screenshot of the World
|
||||
* Morphic: enable more fine-grained control over dragging position correction
|
||||
* Morphic: enable all Morphs to “scrollIntoView()”
|
||||
* Morpic: keyboard accessibility for menus
|
||||
* Objects: fixes and enhancements for nested sprites
|
||||
* Blocks, Objects, BYOB, GUI: keyboard editing support
|
||||
* Objects, Blocks, Threads, GUI, Store, Widgets: Prototypal inheritance for sprite-local variables
|
||||
* Objects, Blocks: enable monitoring closurized non-locals and thread-temporaries (script vars of running processes)
|
||||
* GUI: stage resizing handle
|
||||
|
||||
150728
|
||||
------
|
||||
* GUI: fixed relative urls, thanks, Michael!
|
||||
* Morphic: escalate origin with “accept” and “cancel” events from text cursors
|
||||
* BYOB: keep BlockEditors open when <enter> or <esc> keys are pressed
|
||||
* GUI: stop keyboard editing of blocks when selecting another sprite
|
||||
|
||||
150730
|
||||
------
|
||||
* Blocks: improve keyboard editing for embedded rings
|
||||
|
|
Plik diff jest za duży
Load Diff
120
lang-pl.js
120
lang-pl.js
|
@ -248,8 +248,8 @@ SnapTranslator.dict.pl = {
|
|||
'tylko lewo/prawo',
|
||||
|
||||
// new sprite button:
|
||||
'add a new sprite':
|
||||
'dodaj nowego duszka',
|
||||
'add a new Turtle sprite':
|
||||
'dodaj nowego duszka-żółwia',
|
||||
|
||||
// tab help
|
||||
'costumes tab help':
|
||||
|
@ -343,7 +343,7 @@ SnapTranslator.dict.pl = {
|
|||
'think %s':
|
||||
'pomy\u015Bl %s',
|
||||
'Hello!':
|
||||
'Hallo!',
|
||||
'Cześć!',
|
||||
'Hmm...':
|
||||
'Hmm...',
|
||||
'change %eff effect by %n':
|
||||
|
@ -545,9 +545,9 @@ SnapTranslator.dict.pl = {
|
|||
'join %words':
|
||||
'po\u0142\u0105cz %words',
|
||||
'hello':
|
||||
'Hallo',
|
||||
'witaj',
|
||||
'world':
|
||||
's\u0142owo',
|
||||
'świecie',
|
||||
'letter %n of %s':
|
||||
'litera %n z %s',
|
||||
'length of %s':
|
||||
|
@ -673,6 +673,8 @@ SnapTranslator.dict.pl = {
|
|||
'Logowanie...',
|
||||
'Signup...':
|
||||
'Rejestracja...',
|
||||
'Reset Password...':
|
||||
'Zresetuj hasło...',
|
||||
|
||||
// settings menu
|
||||
'Language...':
|
||||
|
@ -857,7 +859,7 @@ SnapTranslator.dict.pl = {
|
|||
'Ok':
|
||||
'Ok',
|
||||
'Cancel':
|
||||
'Poniechaj',
|
||||
'Anuluj',
|
||||
'Yes':
|
||||
'Tak',
|
||||
'No':
|
||||
|
@ -903,9 +905,53 @@ SnapTranslator.dict.pl = {
|
|||
'Delete Project':
|
||||
'Usu\u0144 projekt',
|
||||
'Are you sure you want to delete':
|
||||
'Czy napewno chcesz usun\u0105\u0107?',
|
||||
'Czy napewno chcesz usun\u0105\u0107',
|
||||
'rename...':
|
||||
'przemianuj',
|
||||
'Cloud':
|
||||
'Chmura',
|
||||
'Browser':
|
||||
'Przeglądarka',
|
||||
'Examples':
|
||||
'Przykłady',
|
||||
'You are not logged in':
|
||||
'Nie jesteś zalogowany',
|
||||
'Updating\nproject list...':
|
||||
'Aktualizowanie\nlisty projektów...',
|
||||
'last changed':
|
||||
'ostatnio zmieniony',
|
||||
'Open':
|
||||
'Otwórz',
|
||||
'Share':
|
||||
'Udostępnij',
|
||||
'Unshare':
|
||||
'Wyłącz udostępnianie',
|
||||
'Share Project':
|
||||
'Udostępnij projekt',
|
||||
'Unshare Project':
|
||||
'Wyłącz udostępnianie projektu',
|
||||
'Are you sure you want to publish':
|
||||
'Czy na pewno chcesz opublikować projekt',
|
||||
'Are you sure you want to unpublish':
|
||||
'Czy na pewno chcesz wyłączyć publikowanie projektu',
|
||||
'sharing\nproject...':
|
||||
'Udostępnianie\nprojektu...',
|
||||
'shared.':
|
||||
'Projekt udostępniony.',
|
||||
'unsharing\nproject...':
|
||||
'Wyłączanie\nudostępniania projektu...',
|
||||
'unshared.':
|
||||
'Udostępnianie wyłączone.',
|
||||
'Fetching project\nfrom the cloud...':
|
||||
'Wczytywanie projektu\nz chmury...',
|
||||
'Opening project...':
|
||||
'Otwieranie projektu...',
|
||||
'Save Project':
|
||||
'Zapisz projekt',
|
||||
'Saving project\nto the cloud...':
|
||||
'Zapisywanie projektu\ndo chmury...',
|
||||
'saved.':
|
||||
'Projekt zapisany.',
|
||||
|
||||
// costume editor
|
||||
'Costume Editor':
|
||||
|
@ -1081,7 +1127,7 @@ SnapTranslator.dict.pl = {
|
|||
|
||||
// costumes
|
||||
'Turtle':
|
||||
'Duszek',
|
||||
'Żółw',
|
||||
'Empty':
|
||||
'Pusty',
|
||||
|
||||
|
@ -1221,5 +1267,61 @@ SnapTranslator.dict.pl = {
|
|||
'last':
|
||||
'ostatni',
|
||||
'any':
|
||||
'dowolny'
|
||||
'dowolny',
|
||||
|
||||
// Sign up dialog
|
||||
'Sign up':
|
||||
'Rejestracja',
|
||||
'User name:':
|
||||
'Nazwa użytkownika:',
|
||||
'Birth date:':
|
||||
'Data urodzenia:',
|
||||
'year:':
|
||||
'rok:',
|
||||
'E-mail address:':
|
||||
'Adres e-mail:',
|
||||
'E-mail address of parent or guardian:':
|
||||
'Adres e-mail rodzica lub opiekuna:',
|
||||
'Terms of Service...':
|
||||
'Regulamin...',
|
||||
'Privacy...':
|
||||
'Polityka prywatności...',
|
||||
'I have read and agree\nto the Terms of Service':
|
||||
'Przeczytałem i zgadzam się\nz Regulaminem',
|
||||
'January':
|
||||
'styczeń',
|
||||
'February':
|
||||
'luty',
|
||||
'March':
|
||||
'marzec',
|
||||
'April':
|
||||
'kwiecień',
|
||||
'May':
|
||||
'maj',
|
||||
'June':
|
||||
'czerwiec',
|
||||
'July':
|
||||
'lipiec',
|
||||
'August':
|
||||
'sierpień',
|
||||
'September':
|
||||
'wrzesień',
|
||||
'October':
|
||||
'październik',
|
||||
'November':
|
||||
'listopad',
|
||||
'December':
|
||||
'grudzień',
|
||||
'please fill out\nthis field':
|
||||
'Proszę wypełnić\nto pole',
|
||||
'please agree to\nthe TOS':
|
||||
'Proszę zaakceptować\nRegulamin',
|
||||
'Sign in':
|
||||
'Zaloguj się',
|
||||
'Password:':
|
||||
'Hasło:',
|
||||
'stay signed in on this computer\nuntil logging out':
|
||||
'Zapamiętaj mnie na tym komputerze\naż do wylogowania',
|
||||
'Reset password':
|
||||
'Zresetuj hasło'
|
||||
};
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -3,3 +3,5 @@ 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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<blocks app="Snap! 4.0, http://snap.berkeley.edu" version="1"><block-definition s="cases: if %'test' then %'result' %'more'" type="command" category="control"><header></header><code></code><inputs><input type="%b"></input><input type="%cs"></input><input type="%mult%boolUE"></input></inputs><script><block s="doIfElse"><block var="test"/><script><block s="doRun"><block var="result"/><list></list></block></script><script><custom-block s="catch %upvar %cs"><l>tag</l><script><custom-block s="for each %upvar of %l %cs"><l>item</l><block var="more"/><script><block s="doIf"><block s="evaluate"><block var="item"/><list></list></block><script><custom-block s="throw %s"><block var="tag"/></custom-block></script></block></script></custom-block></script></custom-block></script></block></script></block-definition><block-definition s="catch %'tag' %'action'" type="command" category="control"><header></header><code></code><inputs><input type="%upvar"></input><input type="%cs"></input></inputs><script><block s="doCallCC"><block s="reifyScript"><script><block s="doSetVar"><l>tag</l><block var="cont"/></block><block s="doRun"><block var="action"/><list></list></block></script><list><l>cont</l></list></block></block></script></block-definition><block-definition s="throw %'cont'" type="command" category="control"><header></header><code></code><inputs><input type="%s">catchtag</input></inputs><script><block s="doRun"><block var="cont"/><list></list></block></script></block-definition><block-definition s="for each %'item' of %'data' %'action'" type="command" category="lists"><header></header><code></code><inputs><input type="%upvar"></input><input type="%l"></input><input type="%cs"></input></inputs><script><block s="doUntil"><custom-block s="empty? %l"><block var="data"/></custom-block><script><block s="doSetVar"><l>item</l><block s="reportListItem"><l>1</l><block var="data"/></block></block><block s="doRun"><block var="action"/><list><block s="reportListItem"><l>1</l><block var="data"/></block></list></block><block s="doSetVar"><l>data</l><block s="reportCDR"><block var="data"/></block></block></script></block></script></block-definition><block-definition s="else if %'test' then %'action'" type="predicate" category="control"><header></header><code></code><inputs><input type="%b"></input><input type="%cs"></input></inputs><script><block s="doIfElse"><block var="test"/><script><block s="doRun"><block var="action"/><list></list></block><block s="doReport"><block s="reportTrue"></block></block></script><script><block s="doReport"><block s="reportFalse"></block></block></script></block></script></block-definition><block-definition s="else %'action'" type="predicate" category="control"><header></header><code></code><inputs><input type="%cs"></input></inputs><script><block s="doRun"><block var="action"/><list></list></block><block s="doReport"><block s="reportTrue"></block></block></script></block-definition></blocks>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
lists.js
7
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-June-25';
|
||||
modules.lists = '2015-July-27';
|
||||
|
||||
var List;
|
||||
var ListWatcherMorph;
|
||||
|
@ -158,9 +158,8 @@ List.prototype.add = function (element, index) {
|
|||
if no index is specifed, append the element
|
||||
*/
|
||||
var idx = index || this.length() + 1,
|
||||
obj = element === 0 ? 0
|
||||
: element === false ? false
|
||||
: element || null;
|
||||
obj = isNil(element) ? null : element;
|
||||
|
||||
this.becomeArray();
|
||||
this.contents.splice(idx - 1, 0, obj);
|
||||
this.changed();
|
||||
|
|
27
locale.js
27
locale.js
|
@ -42,7 +42,7 @@
|
|||
|
||||
/*global modules, contains*/
|
||||
|
||||
modules.locale = '2015-June-25';
|
||||
modules.locale = '2015-July-27';
|
||||
|
||||
// Global stuff
|
||||
|
||||
|
@ -475,3 +475,28 @@ SnapTranslator.dict.te = {
|
|||
'last_changed':
|
||||
'2015-02-20'
|
||||
};
|
||||
|
||||
SnapTranslator.dict.tr = {
|
||||
// translations meta information
|
||||
'language_name':
|
||||
'Türkçe',
|
||||
'language_translator':
|
||||
'Hakan Atas',
|
||||
'translator_e-mail':
|
||||
'hakanatas@gmail.com',
|
||||
'last_changed':
|
||||
'2015-7-27'
|
||||
};
|
||||
|
||||
SnapTranslator.dict.hu = {
|
||||
// translations meta information
|
||||
'language_name':
|
||||
'Magyar',
|
||||
'language_translator':
|
||||
'Makány György',
|
||||
'translator_e-mail':
|
||||
'makany.gyorgy@gmail.com',
|
||||
'last_changed':
|
||||
'2015-07-27'
|
||||
};
|
||||
|
||||
|
|
211
morphic.js
211
morphic.js
|
@ -1048,7 +1048,7 @@
|
|||
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
|
||||
FileList, getBlurredShadowSupport*/
|
||||
|
||||
var morphicVersion = '2015-June-26';
|
||||
var morphicVersion = '2015-July-28';
|
||||
var modules = {}; // keep track of additional loaded modules
|
||||
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
||||
|
||||
|
@ -2501,6 +2501,32 @@ Morph.prototype.keepWithin = function (aMorph) {
|
|||
}
|
||||
};
|
||||
|
||||
Morph.prototype.scrollIntoView = function () {
|
||||
var leftOff, rightOff, topOff, bottomOff,
|
||||
sf = this.parentThatIsA(ScrollFrameMorph);
|
||||
if (!sf) {return; }
|
||||
rightOff = Math.min(
|
||||
this.fullBounds().right() - sf.right(),
|
||||
sf.contents.right() - sf.right()
|
||||
);
|
||||
if (rightOff > 0) {
|
||||
sf.contents.moveBy(new Point(-rightOff, 0));
|
||||
}
|
||||
leftOff = this.fullBounds().left() - sf.left();
|
||||
if (leftOff < 0) {
|
||||
sf.contents.moveBy(new Point(-leftOff, 0));
|
||||
}
|
||||
topOff = this.fullBounds().top() - sf.top();
|
||||
if (topOff < 0) {
|
||||
sf.contents.moveBy(new Point(0, -topOff));
|
||||
}
|
||||
bottomOff = this.fullBounds().bottom() - sf.bottom();
|
||||
if (bottomOff > 0) {
|
||||
sf.contents.moveBy(new Point(0, -bottomOff));
|
||||
}
|
||||
sf.adjustScrollBars();
|
||||
};
|
||||
|
||||
// Morph accessing - dimensional changes requiring a complete redraw
|
||||
|
||||
Morph.prototype.setExtent = function (aPoint) {
|
||||
|
@ -3092,6 +3118,13 @@ Morph.prototype.rootForGrab = function () {
|
|||
return this.parent.rootForGrab();
|
||||
};
|
||||
|
||||
Morph.prototype.isCorrectingOutsideDrag = function () {
|
||||
// make sure I don't "trail behind" the hand when dragged
|
||||
// override for morphs that you want to be dragged outside
|
||||
// their full bounds
|
||||
return true;
|
||||
};
|
||||
|
||||
Morph.prototype.wantsDropOf = function (aMorph) {
|
||||
// default is to answer the general flag - change for my heirs
|
||||
if ((aMorph instanceof HandleMorph) ||
|
||||
|
@ -3174,6 +3207,17 @@ Morph.prototype.move = function () {
|
|||
);
|
||||
};
|
||||
|
||||
Morph.prototype.moveCenter = function () {
|
||||
this.world().activeHandle = new HandleMorph(
|
||||
this,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'moveCenter'
|
||||
);
|
||||
};
|
||||
|
||||
Morph.prototype.hint = function (msg) {
|
||||
var m, text;
|
||||
text = msg;
|
||||
|
@ -3722,7 +3766,7 @@ HandleMorph.prototype.init = function (
|
|||
this.target = target || null;
|
||||
this.minExtent = new Point(minX || 0, minY || 0);
|
||||
this.inset = new Point(insetX || 0, insetY || insetX || 0);
|
||||
this.type = type || 'resize'; // can also be 'move'
|
||||
this.type = type || 'resize'; // can also be 'move', 'moveCenter'
|
||||
HandleMorph.uber.init.call(this);
|
||||
this.color = new Color(255, 255, 255);
|
||||
this.isDraggable = false;
|
||||
|
@ -3747,11 +3791,15 @@ HandleMorph.prototype.drawNew = function () {
|
|||
);
|
||||
this.image = this.normalImage;
|
||||
if (this.target) {
|
||||
this.setPosition(
|
||||
this.target.bottomRight().subtract(
|
||||
this.extent().add(this.inset)
|
||||
)
|
||||
);
|
||||
if (this.type === 'moveCenter') {
|
||||
this.setCenter(this.target.center());
|
||||
} else { // 'resize', 'move'
|
||||
this.setPosition(
|
||||
this.target.bottomRight().subtract(
|
||||
this.extent().add(this.inset)
|
||||
)
|
||||
);
|
||||
}
|
||||
this.target.add(this);
|
||||
this.target.changed();
|
||||
}
|
||||
|
@ -3763,6 +3811,7 @@ HandleMorph.prototype.drawOnCanvas = function (
|
|||
shadowColor
|
||||
) {
|
||||
var context = aCanvas.getContext('2d'),
|
||||
isSquare = (this.type.indexOf('move') === 0),
|
||||
p1,
|
||||
p11,
|
||||
p2,
|
||||
|
@ -3774,7 +3823,7 @@ HandleMorph.prototype.drawOnCanvas = function (
|
|||
|
||||
context.strokeStyle = color.toString();
|
||||
|
||||
if (this.type === 'move') {
|
||||
if (isSquare) {
|
||||
|
||||
p1 = this.bottomLeft().subtract(this.position());
|
||||
p11 = p1.copy();
|
||||
|
@ -3811,7 +3860,7 @@ HandleMorph.prototype.drawOnCanvas = function (
|
|||
|
||||
context.strokeStyle = shadowColor.toString();
|
||||
|
||||
if (this.type === 'move') {
|
||||
if (isSquare) {
|
||||
|
||||
p1 = this.bottomLeft().subtract(this.position());
|
||||
p11 = p1.copy();
|
||||
|
@ -3853,12 +3902,17 @@ HandleMorph.prototype.step = null;
|
|||
|
||||
HandleMorph.prototype.mouseDownLeft = function (pos) {
|
||||
var world = this.root(),
|
||||
offset = pos.subtract(this.bounds.origin),
|
||||
offset,
|
||||
myself = this;
|
||||
|
||||
if (!this.target) {
|
||||
return null;
|
||||
}
|
||||
if (this.type === 'moveCenter') {
|
||||
offset = pos.subtract(this.center());
|
||||
} else {
|
||||
offset = pos.subtract(this.bounds.origin);
|
||||
}
|
||||
this.step = function () {
|
||||
var newPos, newExt;
|
||||
if (world.hand.mouseButton) {
|
||||
|
@ -3875,6 +3929,8 @@ HandleMorph.prototype.mouseDownLeft = function (pos) {
|
|||
myself.extent().add(myself.inset)
|
||||
)
|
||||
);
|
||||
} else if (this.type === 'moveCenter') {
|
||||
myself.target.setCenter(newPos);
|
||||
} else { // type === 'move'
|
||||
myself.target.setPosition(
|
||||
newPos.subtract(this.target.extent())
|
||||
|
@ -4680,7 +4736,7 @@ CursorMorph.prototype.accept = function () {
|
|||
if (world) {
|
||||
world.stopEditing();
|
||||
}
|
||||
this.escalateEvent('accept', null);
|
||||
this.escalateEvent('accept', this);
|
||||
};
|
||||
|
||||
CursorMorph.prototype.cancel = function () {
|
||||
|
@ -4689,7 +4745,7 @@ CursorMorph.prototype.cancel = function () {
|
|||
if (world) {
|
||||
world.stopEditing();
|
||||
}
|
||||
this.escalateEvent('cancel', null);
|
||||
this.escalateEvent('cancel', this);
|
||||
};
|
||||
|
||||
CursorMorph.prototype.undo = function () {
|
||||
|
@ -6652,6 +6708,8 @@ MenuMorph.prototype.init = function (target, title, environment, fontSize) {
|
|||
this.label = null;
|
||||
this.world = null;
|
||||
this.isListContents = false;
|
||||
this.hasFocus = false;
|
||||
this.selection = null;
|
||||
|
||||
// initialize inherited properties:
|
||||
MenuMorph.uber.init.call(this);
|
||||
|
@ -6871,6 +6929,7 @@ MenuMorph.prototype.popup = function (world, pos) {
|
|||
}
|
||||
world.add(this);
|
||||
world.activeMenu = this;
|
||||
this.world = world; // optionally enable keyboard support
|
||||
this.fullChanged();
|
||||
};
|
||||
|
||||
|
@ -6901,6 +6960,105 @@ MenuMorph.prototype.popUpCenteredInWorld = function (world) {
|
|||
);
|
||||
};
|
||||
|
||||
// MenuMorph keyboard accessibility
|
||||
|
||||
MenuMorph.prototype.getFocus = function () {
|
||||
this.world.keyboardReceiver = this;
|
||||
this.selection = null;
|
||||
this.selectFirst();
|
||||
this.hasFocus = true;
|
||||
};
|
||||
|
||||
MenuMorph.prototype.processKeyDown = function (event) {
|
||||
//console.log(event.keyCode);
|
||||
switch (event.keyCode) {
|
||||
case 13: // 'enter'
|
||||
case 32: // 'space'
|
||||
if (this.selection) {
|
||||
this.selection.mouseClickLeft();
|
||||
}
|
||||
return;
|
||||
case 27: // 'esc'
|
||||
return this.destroy();
|
||||
case 38: // 'up arrow'
|
||||
return this.selectUp();
|
||||
case 40: // 'down arrow'
|
||||
return this.selectDown();
|
||||
default:
|
||||
nop();
|
||||
}
|
||||
};
|
||||
|
||||
MenuMorph.prototype.processKeyUp = function (event) {
|
||||
nop(event);
|
||||
};
|
||||
|
||||
MenuMorph.prototype.processKeyPress = function (event) {
|
||||
nop(event);
|
||||
};
|
||||
|
||||
MenuMorph.prototype.selectFirst = function () {
|
||||
var i;
|
||||
for (i = 0; i < this.children.length; i += 1) {
|
||||
if (this.children[i] instanceof MenuItemMorph) {
|
||||
this.select(this.children[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MenuMorph.prototype.selectUp = function () {
|
||||
var triggers, idx;
|
||||
|
||||
triggers = this.children.filter(function (each) {
|
||||
return each instanceof MenuItemMorph;
|
||||
});
|
||||
if (!this.selection) {
|
||||
if (triggers.length) {
|
||||
this.select(triggers[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
idx = triggers.indexOf(this.selection) - 1;
|
||||
if (idx < 0) {
|
||||
idx = triggers.length - 1;
|
||||
}
|
||||
this.select(triggers[idx]);
|
||||
};
|
||||
|
||||
MenuMorph.prototype.selectDown = function () {
|
||||
var triggers, idx;
|
||||
|
||||
triggers = this.children.filter(function (each) {
|
||||
return each instanceof MenuItemMorph;
|
||||
});
|
||||
if (!this.selection) {
|
||||
if (triggers.length) {
|
||||
this.select(triggers[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
idx = triggers.indexOf(this.selection) + 1;
|
||||
if (idx >= triggers.length) {
|
||||
idx = 0;
|
||||
}
|
||||
this.select(triggers[idx]);
|
||||
};
|
||||
|
||||
MenuMorph.prototype.select = function (aMenuItem) {
|
||||
this.unselectAllItems();
|
||||
aMenuItem.image = aMenuItem.highlightImage;
|
||||
aMenuItem.changed();
|
||||
this.selection = aMenuItem;
|
||||
};
|
||||
|
||||
MenuMorph.prototype.destroy = function () {
|
||||
if (this.hasFocus) {
|
||||
this.world.keyboardReceiver = null;
|
||||
}
|
||||
MenuMorph.uber.destroy.call(this);
|
||||
};
|
||||
|
||||
// StringMorph /////////////////////////////////////////////////////////
|
||||
|
||||
// I am a single line of text
|
||||
|
@ -9586,32 +9744,16 @@ HandMorph.prototype.processMouseMove = function (event) {
|
|||
this.grabOrigin = this.morphToGrab.situation();
|
||||
}
|
||||
if (morph) {
|
||||
// if the mouse has left its fullBounds, center it
|
||||
// if the mouse has left its fullBounds, allow to center it
|
||||
fb = morph.fullBounds();
|
||||
if (!fb.containsPoint(pos)) {
|
||||
if (!fb.containsPoint(pos) &&
|
||||
morph.isCorrectingOutsideDrag()) {
|
||||
this.bounds.origin = fb.center();
|
||||
this.grab(morph);
|
||||
this.setPosition(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
original, more cautious code for grabbing Morphs,
|
||||
retained in case of needing to fall back:
|
||||
|
||||
if (morph === this.morphToGrab) {
|
||||
if (morph.isDraggable) {
|
||||
this.grab(morph);
|
||||
} else if (morph.isTemplate) {
|
||||
morph = morph.fullCopy();
|
||||
morph.isTemplate = false;
|
||||
morph.isDraggable = true;
|
||||
this.grab(morph);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
this.mouseOverList.forEach(function (old) {
|
||||
|
@ -10399,6 +10541,13 @@ WorldMorph.prototype.contextMenu = function () {
|
|||
'inspect',
|
||||
'open a window on\nall properties'
|
||||
);
|
||||
menu.addItem(
|
||||
"screenshot...",
|
||||
function () {
|
||||
window.open(this.fullImageClassic().toDataURL());
|
||||
},
|
||||
'open a new window\nwith a picture of this morph'
|
||||
);
|
||||
menu.addLine();
|
||||
menu.addItem(
|
||||
"restore display",
|
||||
|
|
538
objects.js
538
objects.js
|
@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.objects = '2015-June-25';
|
||||
modules.objects = '2015-July-27';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -583,7 +583,7 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
},
|
||||
|
||||
/* migrated to a newer block version:
|
||||
|
||||
|
||||
receiveClick: {
|
||||
type: 'hat',
|
||||
category: 'control',
|
||||
|
@ -900,17 +900,20 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
reifyScript: {
|
||||
type: 'ring',
|
||||
category: 'other',
|
||||
spec: '%rc %ringparms'
|
||||
spec: '%rc %ringparms',
|
||||
alias: 'command ring lambda'
|
||||
},
|
||||
reifyReporter: {
|
||||
type: 'ring',
|
||||
category: 'other',
|
||||
spec: '%rr %ringparms'
|
||||
spec: '%rr %ringparms',
|
||||
alias: 'reporter ring lambda'
|
||||
},
|
||||
reifyPredicate: {
|
||||
type: 'ring',
|
||||
category: 'other',
|
||||
spec: '%rp %ringparms'
|
||||
spec: '%rp %ringparms',
|
||||
alias: 'predicate ring lambda'
|
||||
},
|
||||
reportSum: {
|
||||
type: 'reporter',
|
||||
|
@ -920,12 +923,14 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
reportDifference: {
|
||||
type: 'reporter',
|
||||
category: 'operators',
|
||||
spec: '%n \u2212 %n'
|
||||
spec: '%n \u2212 %n',
|
||||
alias: '-'
|
||||
},
|
||||
reportProduct: {
|
||||
type: 'reporter',
|
||||
category: 'operators',
|
||||
spec: '%n \u00D7 %n'
|
||||
spec: '%n \u00D7 %n',
|
||||
alias: '*'
|
||||
},
|
||||
reportQuotient: {
|
||||
type: 'reporter',
|
||||
|
@ -1103,6 +1108,13 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
spec: 'script variables %scriptVars'
|
||||
},
|
||||
|
||||
// inheritance - experimental
|
||||
doDeleteAttr: {
|
||||
type: 'command',
|
||||
category: 'variables',
|
||||
spec: 'delete %shd'
|
||||
},
|
||||
|
||||
// Lists
|
||||
reportNewList: {
|
||||
type: 'reporter',
|
||||
|
@ -1348,11 +1360,13 @@ SpriteMorph.prototype.init = function (globals) {
|
|||
'confetti': 0
|
||||
};
|
||||
|
||||
// sprite inheritance
|
||||
this.exemplar = null;
|
||||
|
||||
SpriteMorph.uber.init.call(this);
|
||||
|
||||
this.isDraggable = true;
|
||||
this.isDown = false;
|
||||
|
||||
this.heading = 90;
|
||||
this.changed();
|
||||
this.drawNew();
|
||||
|
@ -1642,7 +1656,8 @@ SpriteMorph.prototype.variableBlock = function (varName) {
|
|||
|
||||
SpriteMorph.prototype.blockTemplates = function (category) {
|
||||
var blocks = [], myself = this, varNames, button,
|
||||
cat = category || 'motion', txt;
|
||||
cat = category || 'motion', txt,
|
||||
inheritedVars = this.inheritedVariableNames();
|
||||
|
||||
function block(selector) {
|
||||
if (StageMorph.prototype.hiddenPrimitives[selector]) {
|
||||
|
@ -1657,6 +1672,9 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
var newBlock = SpriteMorph.prototype.variableBlock(varName);
|
||||
newBlock.isDraggable = false;
|
||||
newBlock.isTemplate = true;
|
||||
if (contains(inheritedVars, varName)) {
|
||||
newBlock.ghost();
|
||||
}
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
|
@ -1705,15 +1723,18 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
}
|
||||
|
||||
function addVar(pair) {
|
||||
var ide;
|
||||
if (pair) {
|
||||
if (myself.variables.silentFind(pair[0])) {
|
||||
if (myself.isVariableNameInUse(pair[0], pair[1])) {
|
||||
myself.inform('that name is already in use');
|
||||
} else {
|
||||
ide = myself.parentThatIsA(IDE_Morph);
|
||||
myself.addVariable(pair[0], pair[1]);
|
||||
myself.toggleVariableWatcher(pair[0], pair[1]);
|
||||
myself.blocksCache[cat] = null;
|
||||
myself.paletteCache[cat] = null;
|
||||
myself.parentThatIsA(IDE_Morph).refreshPalette();
|
||||
if (!myself.showingVariableWatcher(pair[0])) {
|
||||
myself.toggleVariableWatcher(pair[0], pair[1]);
|
||||
}
|
||||
ide.flushBlocksCache('variables'); // b/c of inheritance
|
||||
ide.refreshPalette();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2028,7 +2049,7 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
button.showHelp = BlockMorph.prototype.showHelp;
|
||||
blocks.push(button);
|
||||
|
||||
if (this.variables.allNames().length > 0) {
|
||||
if (this.deletableVariableNames().length > 0) {
|
||||
button = new PushButtonMorph(
|
||||
null,
|
||||
function () {
|
||||
|
@ -2037,7 +2058,7 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
null,
|
||||
myself
|
||||
);
|
||||
myself.variables.allNames().forEach(function (name) {
|
||||
myself.deletableVariableNames().forEach(function (name) {
|
||||
menu.addItem(name, name);
|
||||
});
|
||||
menu.popUpAtHand(myself.world());
|
||||
|
@ -2067,6 +2088,15 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push(block('doHideVar'));
|
||||
blocks.push(block('doDeclareVariables'));
|
||||
|
||||
// inheritance:
|
||||
|
||||
if (StageMorph.prototype.enableInheritance) {
|
||||
blocks.push('-');
|
||||
blocks.push(block('doDeleteAttr'));
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
blocks.push('=');
|
||||
|
||||
blocks.push(block('reportNewList'));
|
||||
|
@ -2357,15 +2387,30 @@ SpriteMorph.prototype.freshPalette = function (category) {
|
|||
|
||||
// SpriteMorph blocks searching
|
||||
|
||||
SpriteMorph.prototype.blocksMatching = function (searchString, strictly) {
|
||||
SpriteMorph.prototype.blocksMatching = function (
|
||||
searchString,
|
||||
strictly,
|
||||
types, // optional, ['hat', 'command', 'reporter', 'predicate']
|
||||
varNames // optional, list of reachable unique variable names
|
||||
) {
|
||||
// answer an array of block templates whose spec contains
|
||||
// the given search string, ordered by descending relevance
|
||||
// types is an optional array containing block types the search
|
||||
// is limited to, e.g. "command", "hat", "reporter", "predicate".
|
||||
// Note that "predicate" is not subsumed by "reporter" and has
|
||||
// to be specified explicitly.
|
||||
// if no types are specified all blocks are searched
|
||||
var blocks = [],
|
||||
blocksDict,
|
||||
myself = this,
|
||||
search = searchString.toLowerCase(),
|
||||
stage = this.parentThatIsA(StageMorph);
|
||||
|
||||
if (!types || !types.length) {
|
||||
types = ['hat', 'command', 'reporter', 'predicate', 'ring'];
|
||||
}
|
||||
if (!varNames) {varNames = []; }
|
||||
|
||||
function labelOf(aBlockSpec) {
|
||||
var words = (BlockMorph.prototype.parseSpec(aBlockSpec)),
|
||||
filtered = words.filter(
|
||||
|
@ -2396,29 +2441,39 @@ SpriteMorph.prototype.blocksMatching = function (searchString, strictly) {
|
|||
return newBlock;
|
||||
}
|
||||
|
||||
// variable getters
|
||||
varNames.forEach(function (vName) {
|
||||
var rel = relevance(labelOf(vName), search);
|
||||
if (rel !== -1) {
|
||||
blocks.push([myself.variableBlock(vName), rel + '1']);
|
||||
}
|
||||
});
|
||||
// custom blocks
|
||||
[this.customBlocks, stage.globalBlocks].forEach(function (blocksList) {
|
||||
blocksList.forEach(function (definition) {
|
||||
var spec = localize(definition.blockSpec()).toLowerCase(),
|
||||
rel = relevance(labelOf(spec), search);
|
||||
if (rel !== -1) {
|
||||
blocks.push([definition.templateInstance(), rel + '1']);
|
||||
if (contains(types, definition.type)) {
|
||||
var spec = localize(definition.blockSpec()).toLowerCase(),
|
||||
rel = relevance(labelOf(spec), search);
|
||||
if (rel !== -1) {
|
||||
blocks.push([definition.templateInstance(), rel + '2']);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
// primitives
|
||||
blocksDict = SpriteMorph.prototype.blocks;
|
||||
Object.keys(blocksDict).forEach(function (selector) {
|
||||
if (!StageMorph.prototype.hiddenPrimitives[selector]) {
|
||||
if (!StageMorph.prototype.hiddenPrimitives[selector] &&
|
||||
contains(types, blocksDict[selector].type)) {
|
||||
var block = blocksDict[selector],
|
||||
spec = localize(block.spec).toLowerCase(),
|
||||
spec = localize(block.alias || block.spec).toLowerCase(),
|
||||
rel = relevance(labelOf(spec), search);
|
||||
if (
|
||||
(rel !== -1) &&
|
||||
(!block.dev) &&
|
||||
(!block.only || (block.only === myself.constructor))
|
||||
) {
|
||||
blocks.push([primitive(selector), rel + '2']);
|
||||
blocks.push([primitive(selector), rel + '3']);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2426,18 +2481,43 @@ SpriteMorph.prototype.blocksMatching = function (searchString, strictly) {
|
|||
return blocks.map(function (each) {return each[0]; });
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.searchBlocks = function () {
|
||||
SpriteMorph.prototype.searchBlocks = function (
|
||||
searchString,
|
||||
types,
|
||||
varNames,
|
||||
scriptFocus
|
||||
) {
|
||||
var myself = this,
|
||||
unit = SyntaxElementMorph.prototype.fontSize,
|
||||
ide = this.parentThatIsA(IDE_Morph),
|
||||
oldSearch = '',
|
||||
searchBar = new InputFieldMorph(''),
|
||||
searchPane = ide.createPalette('forSearch');
|
||||
searchBar = new InputFieldMorph(searchString || ''),
|
||||
searchPane = ide.createPalette('forSearch'),
|
||||
blocksList = [],
|
||||
selection,
|
||||
focus;
|
||||
|
||||
function showSelection() {
|
||||
if (focus) {focus.destroy(); }
|
||||
if (!selection || !scriptFocus) {return; }
|
||||
focus = selection.outline(
|
||||
MorphicPreferences.isFlat ? new Color(150, 200, 255)
|
||||
: new Color(255, 255, 255),
|
||||
2
|
||||
);
|
||||
searchPane.contents.add(focus);
|
||||
focus.scrollIntoView();
|
||||
}
|
||||
|
||||
function show(blocks) {
|
||||
var oldFlag = Morph.prototype.trackChanges,
|
||||
x = searchPane.contents.left() + 5,
|
||||
y = (searchBar.bottom() + unit);
|
||||
blocksList = blocks;
|
||||
selection = null;
|
||||
if (blocks.length && scriptFocus) {
|
||||
selection = blocks[0];
|
||||
}
|
||||
Morph.prototype.trackChanges = false;
|
||||
searchPane.contents.children = [searchPane.contents.children[0]];
|
||||
blocks.forEach(function (block) {
|
||||
|
@ -2447,6 +2527,7 @@ SpriteMorph.prototype.searchBlocks = function () {
|
|||
y += unit * 0.3;
|
||||
});
|
||||
Morph.prototype.trackChanges = oldFlag;
|
||||
showSelection();
|
||||
searchPane.changed();
|
||||
}
|
||||
|
||||
|
@ -2463,17 +2544,52 @@ SpriteMorph.prototype.searchBlocks = function () {
|
|||
searchBar.drawNew();
|
||||
|
||||
searchPane.accept = function () {
|
||||
var search = searchBar.getValue();
|
||||
if (search.length > 0) {
|
||||
show(myself.blocksMatching(search));
|
||||
var search;
|
||||
if (scriptFocus) {
|
||||
searchBar.cancel();
|
||||
if (selection) {
|
||||
scriptFocus.insertBlock(selection);
|
||||
}
|
||||
} else {
|
||||
search = searchBar.getValue();
|
||||
if (search.length > 0) {
|
||||
show(myself.blocksMatching(search));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
searchPane.reactToKeystroke = function () {
|
||||
var search = searchBar.getValue();
|
||||
if (search !== oldSearch) {
|
||||
oldSearch = search;
|
||||
show(myself.blocksMatching(search, search.length < 2));
|
||||
searchPane.reactToKeystroke = function (evt) {
|
||||
var search, idx, code = evt ? evt.keyCode : 0;
|
||||
switch (code) {
|
||||
case 38: // up arrow
|
||||
if (!scriptFocus || !selection) {return; }
|
||||
idx = blocksList.indexOf(selection) - 1;
|
||||
if (idx < 0) {
|
||||
idx = blocksList.length - 1;
|
||||
}
|
||||
selection = blocksList[idx];
|
||||
showSelection();
|
||||
return;
|
||||
case 40: // down arrow
|
||||
if (!scriptFocus || !selection) {return; }
|
||||
idx = blocksList.indexOf(selection) + 1;
|
||||
if (idx >= blocksList.length) {
|
||||
idx = 0;
|
||||
}
|
||||
selection = blocksList[idx];
|
||||
showSelection();
|
||||
return;
|
||||
default:
|
||||
search = searchBar.getValue();
|
||||
if (search !== oldSearch) {
|
||||
oldSearch = search;
|
||||
show(myself.blocksMatching(
|
||||
search,
|
||||
search.length < 2,
|
||||
types,
|
||||
varNames
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2484,6 +2600,7 @@ SpriteMorph.prototype.searchBlocks = function () {
|
|||
|
||||
ide.fixLayout('refreshPalette');
|
||||
searchBar.edit();
|
||||
if (searchString) {searchPane.reactToKeystroke(); }
|
||||
};
|
||||
|
||||
// SpriteMorph variable management
|
||||
|
@ -2491,7 +2608,7 @@ SpriteMorph.prototype.searchBlocks = function () {
|
|||
SpriteMorph.prototype.addVariable = function (name, isGlobal) {
|
||||
var ide = this.parentThatIsA(IDE_Morph);
|
||||
if (isGlobal) {
|
||||
this.variables.parentFrame.addVar(name);
|
||||
this.globalVariables().addVar(name);
|
||||
if (ide) {
|
||||
ide.flushBlocksCache('variables');
|
||||
}
|
||||
|
@ -2503,7 +2620,10 @@ SpriteMorph.prototype.addVariable = function (name, isGlobal) {
|
|||
|
||||
SpriteMorph.prototype.deleteVariable = function (varName) {
|
||||
var ide = this.parentThatIsA(IDE_Morph);
|
||||
this.deleteVariableWatcher(varName);
|
||||
if (!contains(this.inheritedVariableNames(true), varName)) {
|
||||
// check only shadowed variables
|
||||
this.deleteVariableWatcher(varName);
|
||||
}
|
||||
this.variables.deleteVar(varName);
|
||||
if (ide) {
|
||||
ide.flushBlocksCache('variables'); // b/c the var could be global
|
||||
|
@ -2658,7 +2778,7 @@ SpriteMorph.prototype.userMenu = function () {
|
|||
}
|
||||
menu.addItem("duplicate", 'duplicate');
|
||||
menu.addItem("delete", 'remove');
|
||||
menu.addItem("move", 'move');
|
||||
menu.addItem("move", 'moveCenter');
|
||||
if (!this.isClone) {
|
||||
menu.addItem("edit", 'edit');
|
||||
}
|
||||
|
@ -3176,12 +3296,20 @@ SpriteMorph.prototype.positionTalkBubble = function () {
|
|||
SpriteMorph.prototype.prepareToBeGrabbed = function (hand) {
|
||||
this.removeShadow();
|
||||
this.recordLayers();
|
||||
if (!this.bounds.containsPoint(hand.position())) {
|
||||
if (!this.bounds.containsPoint(hand.position()) &&
|
||||
this.isCorrectingOutsideDrag()) {
|
||||
this.setCenter(hand.position());
|
||||
}
|
||||
this.addShadow();
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.isCorrectingOutsideDrag = function () {
|
||||
// make sure I don't "trail behind" the hand when dragged
|
||||
// override for morphs that you want to be dragged outside
|
||||
// their full bounds
|
||||
return !this.parts.length;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.justDropped = function () {
|
||||
this.restoreLayers();
|
||||
this.positionTalkBubble();
|
||||
|
@ -3240,6 +3368,22 @@ SpriteMorph.prototype.moveBy = function (delta, justMe) {
|
|||
}
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.silentMoveBy = function (delta, justMe) {
|
||||
SpriteMorph.uber.silentMoveBy.call(this, delta);
|
||||
if (!justMe && this.parent instanceof HandMorph) {
|
||||
this.parts.forEach(function (part) {
|
||||
part.moveBy(delta);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.rootForGrab = function () {
|
||||
if (this.anchor) {
|
||||
return this.anchor.rootForGrab();
|
||||
}
|
||||
return SpriteMorph.uber.rootForGrab.call(this);
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.slideBackTo = function (situation, inSteps) {
|
||||
// override the inherited default to make sure my parts follow
|
||||
var steps = inSteps || 5,
|
||||
|
@ -3646,6 +3790,7 @@ SpriteMorph.prototype.reportThreadCount = function () {
|
|||
|
||||
SpriteMorph.prototype.findVariableWatcher = function (varName) {
|
||||
var stage = this.parentThatIsA(StageMorph),
|
||||
globals = this.globalVariables(),
|
||||
myself = this;
|
||||
if (stage === null) {
|
||||
return null;
|
||||
|
@ -3655,7 +3800,7 @@ SpriteMorph.prototype.findVariableWatcher = function (varName) {
|
|||
function (morph) {
|
||||
return morph instanceof WatcherMorph
|
||||
&& (morph.target === myself.variables
|
||||
|| morph.target === myself.variables.parentFrame)
|
||||
|| morph.target === globals)
|
||||
&& morph.getter === varName;
|
||||
}
|
||||
);
|
||||
|
@ -3663,6 +3808,7 @@ SpriteMorph.prototype.findVariableWatcher = function (varName) {
|
|||
|
||||
SpriteMorph.prototype.toggleVariableWatcher = function (varName, isGlobal) {
|
||||
var stage = this.parentThatIsA(StageMorph),
|
||||
globals = this.globalVariables(),
|
||||
watcher,
|
||||
others;
|
||||
if (stage === null) {
|
||||
|
@ -3682,12 +3828,12 @@ SpriteMorph.prototype.toggleVariableWatcher = function (varName, isGlobal) {
|
|||
|
||||
// if no watcher exists, create a new one
|
||||
if (isNil(isGlobal)) {
|
||||
isGlobal = contains(this.variables.parentFrame.names(), varName);
|
||||
isGlobal = contains(globals.names(), varName);
|
||||
}
|
||||
watcher = new WatcherMorph(
|
||||
varName,
|
||||
this.blockColor.variables,
|
||||
isGlobal ? this.variables.parentFrame : this.variables,
|
||||
isGlobal ? globals : this.variables,
|
||||
varName
|
||||
);
|
||||
watcher.setPosition(stage.position().add(10));
|
||||
|
@ -3954,6 +4100,176 @@ SpriteMorph.prototype.replaceDoubleDefinitionsFor = function (definition) {
|
|||
}
|
||||
};
|
||||
|
||||
// SpriteMorph inheritance - general
|
||||
|
||||
SpriteMorph.prototype.chooseExemplar = function () {
|
||||
var stage = this.parentThatIsA(StageMorph),
|
||||
myself = this,
|
||||
other = stage.children.filter(function (m) {
|
||||
return m instanceof SpriteMorph &&
|
||||
(!contains(m.allExemplars(), myself));
|
||||
}),
|
||||
menu;
|
||||
menu = new MenuMorph(
|
||||
function (aSprite) {myself.setExemplar(aSprite); },
|
||||
localize('current parent') +
|
||||
':\n' +
|
||||
(this.exemplar ? this.exemplar.name : localize('none'))
|
||||
);
|
||||
other.forEach(function (eachSprite) {
|
||||
menu.addItem(eachSprite.name, eachSprite);
|
||||
});
|
||||
menu.addLine();
|
||||
menu.addItem(localize('none'), null);
|
||||
menu.popUpAtHand(this.world());
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.setExemplar = function (another) {
|
||||
var ide = this.parentThatIsA(IDE_Morph);
|
||||
this.exemplar = another;
|
||||
if (isNil(another)) {
|
||||
this.variables.parentFrame = (this.globalVariables());
|
||||
} else {
|
||||
this.variables.parentFrame = (another.variables);
|
||||
}
|
||||
if (ide) {
|
||||
ide.flushBlocksCache('variables');
|
||||
ide.refreshPalette();
|
||||
}
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.allExemplars = function () {
|
||||
// including myself
|
||||
var all = [],
|
||||
current = this;
|
||||
while (!isNil(current)) {
|
||||
all.push(current);
|
||||
current = current.exemplar;
|
||||
}
|
||||
return all;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.specimens = function () {
|
||||
// without myself
|
||||
var myself = this;
|
||||
return this.siblings().filter(function (m) {
|
||||
return m instanceof SpriteMorph && (m.exemplar === myself);
|
||||
});
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.allSpecimens = function () {
|
||||
// without myself
|
||||
var myself = this;
|
||||
return this.siblings().filter(function (m) {
|
||||
return m instanceof SpriteMorph && contains(m.allExemplars(), myself);
|
||||
});
|
||||
};
|
||||
|
||||
// SpriteMorph inheritance - variables
|
||||
|
||||
SpriteMorph.prototype.isVariableNameInUse = function (vName, isGlobal) {
|
||||
if (isGlobal) {
|
||||
return contains(this.variables.allNames(), vName);
|
||||
}
|
||||
if (contains(this.variables.names(), vName)) {return true; }
|
||||
return contains(this.globalVariables().names(), vName);
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.globalVariables = function () {
|
||||
var current = this.variables.parentFrame;
|
||||
while (current.owner) {
|
||||
current = current.parentFrame;
|
||||
}
|
||||
return current;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.shadowVar = function (name, value) {
|
||||
var ide = this.parentThatIsA(IDE_Morph);
|
||||
this.variables.addVar(name, value);
|
||||
if (ide) {
|
||||
ide.flushBlocksCache('variables');
|
||||
ide.refreshPalette();
|
||||
}
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.inheritedVariableNames = function (shadowedOnly) {
|
||||
var names = [],
|
||||
own = this.variables.names(),
|
||||
current = this.variables.parentFrame;
|
||||
|
||||
function test(each) {
|
||||
return shadowedOnly ? contains(own, each) : !contains(own, each);
|
||||
}
|
||||
|
||||
while (current.owner instanceof SpriteMorph) {
|
||||
names.push.apply(
|
||||
names,
|
||||
current.names().filter(test)
|
||||
);
|
||||
current = current.parentFrame;
|
||||
}
|
||||
return names;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.deletableVariableNames = function () {
|
||||
var locals = this.variables.names(),
|
||||
inherited = this.inheritedVariableNames();
|
||||
return locals.concat(
|
||||
this.globalVariables().names().filter(
|
||||
function (each) {
|
||||
return !contains(locals, each) && !contains(inherited, each);
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
// SpriteMorph inheritance - custom blocks
|
||||
|
||||
/*
|
||||
// under construction, commented out for now
|
||||
|
||||
SpriteMorph.prototype.ownBlocks = function () {
|
||||
var dict = {};
|
||||
this.customBlocks.forEach(function (def) {
|
||||
dict[def.blockSpec()] = def;
|
||||
});
|
||||
return dict;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.allBlocks = function (valuesOnly) {
|
||||
var dict = {};
|
||||
this.allExemplars().reverse().forEach(function (sprite) {
|
||||
sprite.customBlocks.forEach(function (def) {
|
||||
dict[def.blockSpec()] = def;
|
||||
});
|
||||
});
|
||||
if (valuesOnly) {
|
||||
return Object.keys(dict).map(function (key) {return dict[key]; });
|
||||
}
|
||||
return dict;
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.inheritedBlocks = function (valuesOnly) {
|
||||
var dict = {},
|
||||
own = Object.keys(this.ownBlocks()),
|
||||
others = this.allExemplars().reverse();
|
||||
others.pop();
|
||||
others.forEach(function (sprite) {
|
||||
sprite.customBlocks.forEach(function (def) {
|
||||
var spec = def.blockSpec();
|
||||
if (!contains(own, spec)) {
|
||||
dict[spec] = def;
|
||||
}
|
||||
});
|
||||
});
|
||||
if (valuesOnly) {
|
||||
return Object.keys(dict).map(function (key) {return dict[key]; });
|
||||
}
|
||||
return dict;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
// SpriteMorph thumbnail
|
||||
|
||||
SpriteMorph.prototype.thumbnail = function (extentPoint) {
|
||||
|
@ -4334,6 +4650,8 @@ StageMorph.prototype.codeMappings = {};
|
|||
StageMorph.prototype.codeHeaders = {};
|
||||
StageMorph.prototype.enableCodeMapping = false;
|
||||
|
||||
StageMorph.prototype.enableInheritance = false;
|
||||
|
||||
// StageMorph instance creation
|
||||
|
||||
function StageMorph(globals) {
|
||||
|
@ -4767,6 +5085,8 @@ StageMorph.prototype.processKeyEvent = function (event, action) {
|
|||
keyName = 'enter';
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
keyName = 'ctrl enter';
|
||||
} else if (event.shiftKey) {
|
||||
keyName = 'shift enter';
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
|
@ -4807,6 +5127,9 @@ StageMorph.prototype.fireKeyEvent = function (key) {
|
|||
if (evt === 'ctrl enter') {
|
||||
return this.fireGreenFlagEvent();
|
||||
}
|
||||
if (evt === 'shift enter') {
|
||||
return this.editScripts();
|
||||
}
|
||||
if (evt === 'ctrl f') {
|
||||
if (!ide.isAppMode) {ide.currentSprite.searchBlocks(); }
|
||||
return;
|
||||
|
@ -4907,6 +5230,25 @@ StageMorph.prototype.removeAllClones = function () {
|
|||
this.cloneCount = 0;
|
||||
};
|
||||
|
||||
StageMorph.prototype.editScripts = function () {
|
||||
var ide = this.parentThatIsA(IDE_Morph),
|
||||
scripts,
|
||||
sorted;
|
||||
if (ide.isAppMode || !ScriptsMorph.prototype.enableKeyboard) {return; }
|
||||
scripts = this.parentThatIsA(IDE_Morph).currentSprite.scripts;
|
||||
scripts.edit(scripts.position());
|
||||
sorted = scripts.focus.sortedScripts();
|
||||
if (sorted.length) {
|
||||
scripts.focus.element = sorted[0];
|
||||
if (scripts.focus.element instanceof HatBlockMorph) {
|
||||
scripts.focus.nextCommand();
|
||||
}
|
||||
} else {
|
||||
scripts.focus.moveBy(new Point(50, 50));
|
||||
}
|
||||
scripts.focus.fixLayout();
|
||||
};
|
||||
|
||||
// StageMorph block templates
|
||||
|
||||
StageMorph.prototype.blockTemplates = function (category) {
|
||||
|
@ -4969,7 +5311,7 @@ StageMorph.prototype.blockTemplates = function (category) {
|
|||
|
||||
function addVar(pair) {
|
||||
if (pair) {
|
||||
if (myself.variables.silentFind(pair[0])) {
|
||||
if (myself.isVariableNameInUse(pair[0])) {
|
||||
myself.inform('that name is already in use');
|
||||
} else {
|
||||
myself.addVariable(pair[0], pair[1]);
|
||||
|
@ -5271,9 +5613,7 @@ StageMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push(block('doShowVar'));
|
||||
blocks.push(block('doHideVar'));
|
||||
blocks.push(block('doDeclareVariables'));
|
||||
|
||||
blocks.push('=');
|
||||
|
||||
blocks.push(block('reportNewList'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('reportCONS'));
|
||||
|
@ -5472,7 +5812,7 @@ StageMorph.prototype.show = function () {
|
|||
this.changed();
|
||||
};
|
||||
|
||||
// StageMorph cloning overrice
|
||||
// StageMorph cloning override
|
||||
|
||||
StageMorph.prototype.createClone = nop;
|
||||
|
||||
|
@ -5663,6 +6003,18 @@ StageMorph.prototype.doubleDefinitionsFor
|
|||
StageMorph.prototype.replaceDoubleDefinitionsFor
|
||||
= SpriteMorph.prototype.replaceDoubleDefinitionsFor;
|
||||
|
||||
// StageMorph inheritance support - variables
|
||||
|
||||
StageMorph.prototype.isVariableNameInUse
|
||||
= SpriteMorph.prototype.isVariableNameInUse;
|
||||
|
||||
StageMorph.prototype.globalVariables
|
||||
= SpriteMorph.prototype.globalVariables;
|
||||
|
||||
StageMorph.prototype.inheritedVariableNames = function () {
|
||||
return [];
|
||||
};
|
||||
|
||||
// SpriteBubbleMorph ////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
|
@ -6876,32 +7228,51 @@ WatcherMorph.prototype.isGlobal = function (selector) {
|
|||
|
||||
// WatcherMorph slider accessing:
|
||||
|
||||
WatcherMorph.prototype.setSliderMin = function (num) {
|
||||
WatcherMorph.prototype.setSliderMin = function (num, noUpdate) {
|
||||
if (this.target instanceof VariableFrame) {
|
||||
this.sliderMorph.setSize(1);
|
||||
this.sliderMorph.setStart(num);
|
||||
this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5);
|
||||
this.sliderMorph.setSize(1, noUpdate);
|
||||
this.sliderMorph.setStart(num, noUpdate);
|
||||
this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5, noUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
WatcherMorph.prototype.setSliderMax = function (num) {
|
||||
WatcherMorph.prototype.setSliderMax = function (num, noUpdate) {
|
||||
if (this.target instanceof VariableFrame) {
|
||||
this.sliderMorph.setSize(1);
|
||||
this.sliderMorph.setStop(num);
|
||||
this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5);
|
||||
this.sliderMorph.setSize(1, noUpdate);
|
||||
this.sliderMorph.setStop(num, noUpdate);
|
||||
this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5, noUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
// WatcherMorph updating:
|
||||
|
||||
WatcherMorph.prototype.update = function () {
|
||||
var newValue,
|
||||
num;
|
||||
var newValue, sprite, num;
|
||||
|
||||
if (this.target && this.getter) {
|
||||
this.updateLabel();
|
||||
if (this.target instanceof VariableFrame) {
|
||||
newValue = this.target.vars[this.getter] ?
|
||||
this.target.vars[this.getter].value : undefined;
|
||||
if (newValue === undefined && this.target.owner) {
|
||||
sprite = this.target.owner;
|
||||
if (contains(sprite.inheritedVariableNames(), this.getter)) {
|
||||
newValue = this.target.getVar(this.getter);
|
||||
// ghost cell color
|
||||
this.cellMorph.setColor(
|
||||
SpriteMorph.prototype.blockColor.variables
|
||||
.lighter(35)
|
||||
);
|
||||
} else {
|
||||
this.destroy();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// un-ghost the cell color
|
||||
this.cellMorph.setColor(
|
||||
SpriteMorph.prototype.blockColor.variables
|
||||
);
|
||||
}
|
||||
} else {
|
||||
newValue = this.target[this.getter]();
|
||||
}
|
||||
|
@ -6986,7 +7357,11 @@ WatcherMorph.prototype.fixLayout = function () {
|
|||
this.sliderMorph.button.pressColor.b += 100;
|
||||
this.sliderMorph.setHeight(fontSize);
|
||||
this.sliderMorph.action = function (num) {
|
||||
myself.target.vars[myself.getter].value = Math.round(num);
|
||||
myself.target.setVar(
|
||||
myself.getter,
|
||||
Math.round(num),
|
||||
myself.target.owner
|
||||
);
|
||||
};
|
||||
this.add(this.sliderMorph);
|
||||
}
|
||||
|
@ -7083,7 +7458,46 @@ WatcherMorph.prototype.userMenu = function () {
|
|||
var myself = this,
|
||||
menu = new MenuMorph(this),
|
||||
on = '\u25CF',
|
||||
off = '\u25CB';
|
||||
off = '\u25CB',
|
||||
vNames;
|
||||
|
||||
function monitor(vName) {
|
||||
var stage = myself.parentThatIsA(StageMorph),
|
||||
varFrame = myself.currentValue.outerContext.variables;
|
||||
menu.addItem(
|
||||
vName + '...',
|
||||
function () {
|
||||
var watcher = detect(
|
||||
stage.children,
|
||||
function (morph) {
|
||||
return morph instanceof WatcherMorph
|
||||
&& morph.target === varFrame
|
||||
&& morph.getter === vName;
|
||||
}
|
||||
),
|
||||
others;
|
||||
if (watcher !== null) {
|
||||
watcher.show();
|
||||
watcher.fixLayout(); // re-hide hidden parts
|
||||
return;
|
||||
}
|
||||
watcher = new WatcherMorph(
|
||||
vName + ' ' + localize('(temporary)'),
|
||||
SpriteMorph.prototype.blockColor.variables,
|
||||
varFrame,
|
||||
vName
|
||||
);
|
||||
watcher.setPosition(stage.position().add(10));
|
||||
others = stage.watchers(watcher.left());
|
||||
if (others.length > 0) {
|
||||
watcher.setTop(others[others.length - 1].bottom());
|
||||
}
|
||||
stage.add(watcher);
|
||||
watcher.fixLayout();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
menu.addItem(
|
||||
(this.style === 'normal' ? on : off) + ' ' + localize('normal'),
|
||||
'styleNormal'
|
||||
|
@ -7182,6 +7596,14 @@ WatcherMorph.prototype.userMenu = function () {
|
|||
);
|
||||
}
|
||||
);
|
||||
} else if (this.currentValue instanceof Context) {
|
||||
vNames = this.currentValue.outerContext.variables.names();
|
||||
if (vNames.length) {
|
||||
menu.addLine();
|
||||
vNames.forEach(function (vName) {
|
||||
monitor(vName);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return menu;
|
||||
|
|
124
store.js
124
store.js
|
@ -61,7 +61,7 @@ SyntaxElementMorph, Variable*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.store = '2015-June-25';
|
||||
modules.store = '2015-July-27';
|
||||
|
||||
|
||||
// XML_Serializer ///////////////////////////////////////////////////////
|
||||
|
@ -413,6 +413,8 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
|
|||
model.stage.attributes.threadsafe === 'true';
|
||||
StageMorph.prototype.enableCodeMapping =
|
||||
model.stage.attributes.codify === 'true';
|
||||
StageMorph.prototype.enableInheritance =
|
||||
model.stage.attributes.inheritance === 'true';
|
||||
|
||||
model.hiddenPrimitives = model.project.childNamed('hidden');
|
||||
if (model.hiddenPrimitives) {
|
||||
|
@ -459,9 +461,17 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
|
|||
myself.loadValue(model);
|
||||
});
|
||||
|
||||
// restore nesting associations
|
||||
// restore inheritance and nesting associations
|
||||
myself.project.stage.children.forEach(function (sprite) {
|
||||
var anchor;
|
||||
var exemplar, anchor;
|
||||
if (sprite.inheritanceInfo) { // only sprites can inherit
|
||||
exemplar = myself.project.sprites[
|
||||
sprite.inheritanceInfo.exemplar
|
||||
];
|
||||
if (exemplar) {
|
||||
sprite.setExemplar(exemplar);
|
||||
}
|
||||
}
|
||||
if (sprite.nestingInfo) { // only sprites may have nesting info
|
||||
anchor = myself.project.sprites[sprite.nestingInfo.anchor];
|
||||
if (anchor) {
|
||||
|
@ -471,6 +481,7 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
|
|||
}
|
||||
});
|
||||
myself.project.stage.children.forEach(function (sprite) {
|
||||
delete sprite.inheritanceInfo;
|
||||
if (sprite.nestingInfo) { // only sprites may have nesting info
|
||||
sprite.nestingScale = +(sprite.nestingInfo.scale || sprite.scale);
|
||||
delete sprite.nestingInfo;
|
||||
|
@ -491,7 +502,7 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
|
|||
/* Watchers */
|
||||
|
||||
model.sprites.childrenNamed('watcher').forEach(function (model) {
|
||||
var watcher, color, target, hidden, extX, extY, vFrame;
|
||||
var watcher, color, target, hidden, extX, extY;
|
||||
|
||||
color = myself.loadColor(model.attributes.color);
|
||||
target = Object.prototype.hasOwnProperty.call(
|
||||
|
@ -512,20 +523,14 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
|
|||
model.attributes,
|
||||
'var'
|
||||
)) {
|
||||
vFrame = isNil(target) ? project.globalVariables
|
||||
: target.variables;
|
||||
if (Object.prototype.hasOwnProperty.call(
|
||||
vFrame.vars,
|
||||
model.attributes['var']
|
||||
)) {
|
||||
watcher = new WatcherMorph(
|
||||
model.attributes['var'],
|
||||
color,
|
||||
vFrame,
|
||||
model.attributes['var'],
|
||||
hidden
|
||||
);
|
||||
}
|
||||
watcher = new WatcherMorph(
|
||||
model.attributes['var'],
|
||||
color,
|
||||
isNil(target) ? project.globalVariables
|
||||
: target.variables,
|
||||
model.attributes['var'],
|
||||
hidden
|
||||
);
|
||||
} else {
|
||||
watcher = new WatcherMorph(
|
||||
localize(myself.watcherLabels[model.attributes.s]),
|
||||
|
@ -535,35 +540,33 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
|
|||
hidden
|
||||
);
|
||||
}
|
||||
if (watcher) {
|
||||
watcher.setStyle(model.attributes.style || 'normal');
|
||||
if (watcher.style === 'slider') {
|
||||
watcher.setSliderMin(model.attributes.min || '1');
|
||||
watcher.setSliderMax(model.attributes.max || '100');
|
||||
}
|
||||
watcher.setPosition(
|
||||
project.stage.topLeft().add(new Point(
|
||||
+model.attributes.x || 0,
|
||||
+model.attributes.y || 0
|
||||
))
|
||||
);
|
||||
project.stage.add(watcher);
|
||||
watcher.onNextStep = function () {this.currentValue = null; };
|
||||
watcher.setStyle(model.attributes.style || 'normal');
|
||||
if (watcher.style === 'slider') {
|
||||
watcher.setSliderMin(model.attributes.min || '1', true);
|
||||
watcher.setSliderMax(model.attributes.max || '100', true);
|
||||
}
|
||||
watcher.setPosition(
|
||||
project.stage.topLeft().add(new Point(
|
||||
+model.attributes.x || 0,
|
||||
+model.attributes.y || 0
|
||||
))
|
||||
);
|
||||
project.stage.add(watcher);
|
||||
watcher.onNextStep = function () {this.currentValue = null; };
|
||||
|
||||
// set watcher's contentsMorph's extent if it is showing a list
|
||||
// and if its monitor dimensions are given
|
||||
if (watcher.currentValue instanceof List) {
|
||||
extX = model.attributes.extX;
|
||||
if (extX) {
|
||||
watcher.cellMorph.contentsMorph.setWidth(+extX);
|
||||
}
|
||||
extY = model.attributes.extY;
|
||||
if (extY) {
|
||||
watcher.cellMorph.contentsMorph.setHeight(+extY);
|
||||
}
|
||||
// adjust my contentsMorph's handle position
|
||||
watcher.cellMorph.contentsMorph.handle.drawNew();
|
||||
// set watcher's contentsMorph's extent if it is showing a list and
|
||||
// its monitor dimensions are given
|
||||
if (watcher.currentValue instanceof List) {
|
||||
extX = model.attributes.extX;
|
||||
if (extX) {
|
||||
watcher.cellMorph.contentsMorph.setWidth(+extX);
|
||||
}
|
||||
extY = model.attributes.extY;
|
||||
if (extY) {
|
||||
watcher.cellMorph.contentsMorph.setHeight(+extY);
|
||||
}
|
||||
// adjust my contentsMorph's handle position
|
||||
watcher.cellMorph.contentsMorph.handle.drawNew();
|
||||
}
|
||||
});
|
||||
this.objects = {};
|
||||
|
@ -647,9 +650,17 @@ SnapSerializer.prototype.loadSprites = function (xmlString, ide) {
|
|||
myself.loadObject(sprite, model);
|
||||
});
|
||||
|
||||
// restore nesting associations
|
||||
// restore inheritance and nesting associations
|
||||
project.stage.children.forEach(function (sprite) {
|
||||
var anchor;
|
||||
var exemplar, anchor;
|
||||
if (sprite.inheritanceInfo) { // only sprites can inherit
|
||||
exemplar = project.sprites[
|
||||
sprite.inheritanceInfo.exemplar
|
||||
];
|
||||
if (exemplar) {
|
||||
sprite.setExemplar(exemplar);
|
||||
}
|
||||
}
|
||||
if (sprite.nestingInfo) { // only sprites may have nesting info
|
||||
anchor = project.sprites[sprite.nestingInfo.anchor];
|
||||
if (anchor) {
|
||||
|
@ -659,6 +670,7 @@ SnapSerializer.prototype.loadSprites = function (xmlString, ide) {
|
|||
}
|
||||
});
|
||||
project.stage.children.forEach(function (sprite) {
|
||||
delete sprite.inheritanceInfo;
|
||||
if (sprite.nestingInfo) { // only sprites may have nesting info
|
||||
sprite.nestingScale = +(sprite.nestingInfo.scale || sprite.scale);
|
||||
delete sprite.nestingInfo;
|
||||
|
@ -707,6 +719,14 @@ SnapSerializer.prototype.loadObject = function (object, model) {
|
|||
this.loadScripts(object.scripts, model.require('scripts'));
|
||||
};
|
||||
|
||||
SnapSerializer.prototype.loadInheritanceInfo = function (object, model) {
|
||||
// private
|
||||
var info = model.childNamed('inherit');
|
||||
if (info) {
|
||||
object.inheritanceInfo = info.attributes;
|
||||
}
|
||||
};
|
||||
|
||||
SnapSerializer.prototype.loadNestingInfo = function (object, model) {
|
||||
// private
|
||||
var info = model.childNamed('nest');
|
||||
|
@ -1416,6 +1436,7 @@ StageMorph.prototype.toXML = function (serializer) {
|
|||
'costume="@" tempo="@" threadsafe="@" ' +
|
||||
'lines="@" ' +
|
||||
'codify="@" ' +
|
||||
'inheritance="@" ' +
|
||||
'scheduled="@" ~>' +
|
||||
'<pentrails>$</pentrails>' +
|
||||
'<costumes>%</costumes>' +
|
||||
|
@ -1443,6 +1464,7 @@ StageMorph.prototype.toXML = function (serializer) {
|
|||
this.isThreadSafe,
|
||||
SpriteMorph.prototype.useFlatLineEnds ? 'flat' : 'round',
|
||||
this.enableCodeMapping,
|
||||
this.enableInheritance,
|
||||
StageMorph.prototype.frameRate !== 0,
|
||||
this.trailsCanvas.toDataURL('image/png'),
|
||||
serializer.store(this.costumes, this.name + '_cst'),
|
||||
|
@ -1475,6 +1497,7 @@ SpriteMorph.prototype.toXML = function (serializer) {
|
|||
' draggable="@"' +
|
||||
'%' +
|
||||
' costume="@" color="@,@,@" pen="@" ~>' +
|
||||
'%' + // inheritance info
|
||||
'%' + // nesting info
|
||||
'<costumes>%</costumes>' +
|
||||
'<sounds>%</sounds>' +
|
||||
|
@ -1497,6 +1520,13 @@ SpriteMorph.prototype.toXML = function (serializer) {
|
|||
this.color.b,
|
||||
this.penPoint,
|
||||
|
||||
// inheritance info
|
||||
this.exemplar
|
||||
? '<inherit exemplar="' +
|
||||
this.exemplar.name
|
||||
+ '"/>'
|
||||
: '',
|
||||
|
||||
// nesting info
|
||||
this.anchor
|
||||
? '<nest anchor="' +
|
||||
|
|
83
threads.js
83
threads.js
|
@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.threads = '2015-June-25';
|
||||
modules.threads = '2015-July-27';
|
||||
|
||||
var ThreadManager;
|
||||
var Process;
|
||||
|
@ -1157,7 +1157,8 @@ Process.prototype.doSetVar = function (varName, value) {
|
|||
if (name.expression.selector === 'reportGetVar') {
|
||||
name.variables.setVar(
|
||||
name.expression.blockSpec,
|
||||
value
|
||||
value,
|
||||
this.blockReceiver()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -1173,7 +1174,8 @@ Process.prototype.doChangeVar = function (varName, value) {
|
|||
if (name.expression.selector === 'reportGetVar') {
|
||||
name.variables.changeVar(
|
||||
name.expression.blockSpec,
|
||||
value
|
||||
value,
|
||||
this.blockReceiver()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -1206,7 +1208,8 @@ Process.prototype.doShowVar = function (varName) {
|
|||
if (this.homeContext.receiver) {
|
||||
stage = this.homeContext.receiver.parentThatIsA(StageMorph);
|
||||
if (stage) {
|
||||
target = varFrame.find(name);
|
||||
target = varFrame.silentFind(name);
|
||||
if (!target) {return; }
|
||||
// first try to find an existing (hidden) watcher
|
||||
watcher = detect(
|
||||
stage.children,
|
||||
|
@ -1223,7 +1226,7 @@ Process.prototype.doShowVar = function (varName) {
|
|||
}
|
||||
// if no watcher exists, create a new one
|
||||
isGlobal = contains(
|
||||
this.homeContext.receiver.variables.parentFrame.names(),
|
||||
this.homeContext.receiver.globalVariables().names(),
|
||||
varName
|
||||
);
|
||||
if (isGlobal || target.owner) {
|
||||
|
@ -1302,6 +1305,23 @@ Process.prototype.doRemoveTemporaries = function () {
|
|||
}
|
||||
};
|
||||
|
||||
// Process sprite inheritance primitives
|
||||
|
||||
Process.prototype.doDeleteAttr = function (attrName) {
|
||||
// currently only variables are deletable
|
||||
var name = attrName,
|
||||
rcvr = this.blockReceiver();
|
||||
|
||||
if (name instanceof Context) {
|
||||
if (name.expression.selector === 'reportGetVar') {
|
||||
name = name.expression.blockSpec;
|
||||
}
|
||||
}
|
||||
if (contains(rcvr.inheritedVariableNames(true), name)) {
|
||||
rcvr.deleteVariable(name);
|
||||
}
|
||||
};
|
||||
|
||||
// Process lists primitives
|
||||
|
||||
Process.prototype.reportNewList = function (elements) {
|
||||
|
@ -3115,35 +3135,50 @@ VariableFrame.prototype.silentFind = function (name) {
|
|||
return null;
|
||||
};
|
||||
|
||||
VariableFrame.prototype.setVar = function (name, value) {
|
||||
/*
|
||||
change the specified variable if it exists
|
||||
else throw an error, because variables need to be
|
||||
declared explicitly (e.g. through a "script variables" block),
|
||||
before they can be accessed.
|
||||
*/
|
||||
VariableFrame.prototype.setVar = function (name, value, sender) {
|
||||
// change the specified variable if it exists
|
||||
// else throw an error, because variables need to be
|
||||
// declared explicitly (e.g. through a "script variables" block),
|
||||
// before they can be accessed.
|
||||
// if the found frame is inherited by the sender sprite
|
||||
// shadow it (create an explicit one for the sender)
|
||||
// before setting the value ("create-on-write")
|
||||
|
||||
var frame = this.find(name);
|
||||
if (frame) {
|
||||
frame.vars[name].value = value;
|
||||
if (sender instanceof SpriteMorph &&
|
||||
(frame.owner instanceof SpriteMorph) &&
|
||||
(sender !== frame.owner)) {
|
||||
sender.shadowVar(name, value);
|
||||
} else {
|
||||
frame.vars[name].value = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VariableFrame.prototype.changeVar = function (name, delta) {
|
||||
/*
|
||||
change the specified variable if it exists
|
||||
else throw an error, because variables need to be
|
||||
declared explicitly (e.g. through a "script variables" block,
|
||||
before they can be accessed.
|
||||
*/
|
||||
VariableFrame.prototype.changeVar = function (name, delta, sender) {
|
||||
// change the specified variable if it exists
|
||||
// else throw an error, because variables need to be
|
||||
// declared explicitly (e.g. through a "script variables" block,
|
||||
// before they can be accessed.
|
||||
// if the found frame is inherited by the sender sprite
|
||||
// shadow it (create an explicit one for the sender)
|
||||
// before changing the value ("create-on-write")
|
||||
|
||||
var frame = this.find(name),
|
||||
value;
|
||||
value,
|
||||
newValue;
|
||||
if (frame) {
|
||||
value = parseFloat(frame.vars[name].value);
|
||||
if (isNaN(value)) {
|
||||
frame.vars[name].value = delta;
|
||||
newValue = isNaN(value) ? delta : value + parseFloat(delta);
|
||||
if (sender instanceof SpriteMorph &&
|
||||
(frame.owner instanceof SpriteMorph) &&
|
||||
(sender !== frame.owner)) {
|
||||
sender.shadowVar(name, newValue);
|
||||
} else {
|
||||
frame.vars[name].value = value + parseFloat(delta);
|
||||
frame.vars[name].value = newValue;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -74,7 +74,7 @@ HTMLCanvasElement, fontHeight, SymbolMorph, localize, SpeechBubbleMorph,
|
|||
ArrowMorph, MenuMorph, isString, isNil, SliderMorph, MorphicPreferences,
|
||||
ScrollFrameMorph*/
|
||||
|
||||
modules.widgets = '2015-June-25';
|
||||
modules.widgets = '2015-July-27';
|
||||
|
||||
var PushButtonMorph;
|
||||
var ToggleButtonMorph;
|
||||
|
@ -560,12 +560,13 @@ ToggleButtonMorph.prototype.init = function (
|
|||
// ToggleButtonMorph events
|
||||
|
||||
ToggleButtonMorph.prototype.mouseEnter = function () {
|
||||
var contents = this.hint instanceof Function ? this.hint() : this.hint;
|
||||
if (!this.state) {
|
||||
this.image = this.highlightImage;
|
||||
this.changed();
|
||||
}
|
||||
if (this.hint) {
|
||||
this.bubbleHelp(this.hint);
|
||||
if (contents) {
|
||||
this.bubbleHelp(contents);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue