Michael Aschauer 2015-08-19 16:33:00 +02:00
commit 6305eaac9f
68 zmienionych plików z 13104 dodań i 782 usunięć

1156
blocks.js

Plik diff jest za duży Load Diff

45
byob.js
Wyświetl plik

@ -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-January-21';
modules.byob = '2015-July-28';
// Declarations
@ -429,6 +429,7 @@ CustomCommandBlockMorph.prototype.refresh = function () {
// find unnahmed upvars and label them
// to their internal definition (default)
this.cachedInputs = null;
this.inputs().forEach(function (inp, idx) {
if (inp instanceof TemplateSlotMorph && inp.contents() === '\u2191') {
inp.setContents(def.inputNames()[idx]);
@ -443,6 +444,7 @@ CustomCommandBlockMorph.prototype.restoreInputs = function (oldInputs) {
myself = this;
if (this.isPrototype) {return; }
this.cachedInputs = null;
this.inputs().forEach(function (inp) {
old = oldInputs[i];
if (old instanceof ReporterBlockMorph &&
@ -460,6 +462,7 @@ CustomCommandBlockMorph.prototype.restoreInputs = function (oldInputs) {
}
i += 1;
});
this.cachedInputs = null;
};
CustomCommandBlockMorph.prototype.refreshDefaults = function () {
@ -472,6 +475,7 @@ CustomCommandBlockMorph.prototype.refreshDefaults = function () {
}
idx += 1;
});
this.cachedInputs = null;
};
CustomCommandBlockMorph.prototype.refreshPrototype = function () {
@ -924,6 +928,9 @@ CustomReporterBlockMorph.prototype.refresh = function () {
if (!this.isPrototype) {
this.isPredicate = (this.definition.type === 'predicate');
}
if (this.parent instanceof SyntaxElementMorph) {
this.parent.cachedInputs = null;
}
this.drawNew();
};
@ -1720,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') {
@ -1740,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();
};
@ -1865,6 +1874,9 @@ BlockEditorMorph.prototype.context = function (prototypeHat) {
if (topBlock === null) {
return null;
}
topBlock.allChildren().forEach(function (c) {
if (c instanceof BlockMorph) {c.cachedInputs = null; }
});
stackFrame = Process.prototype.reify.call(
null,
topBlock,
@ -1956,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();
};
@ -2039,7 +2056,13 @@ BlockLabelFragment.prototype.defTemplateSpecFragment = function () {
)) {
suff = ' \u03BB';
} else if (this.defaultValue) {
suff = ' = ' + this.defaultValue.toString();
if (this.type === '%n') {
suff = ' # = ' + this.defaultValue.toString();
} else { // 'any' or 'text'
suff = ' = ' + this.defaultValue.toString();
}
} else if (this.type === '%n') {
suff = ' #';
}
return this.labelString + suff;
};
@ -2974,7 +2997,7 @@ InputSlotDialogMorph.prototype.editSlotOptions = function () {
new DialogBoxMorph(
myself,
function (options) {
myself.fragment.options = options;
myself.fragment.options = options.trim();
},
myself
).promptCode(
@ -3281,15 +3304,17 @@ BlockExportDialogMorph.prototype.selectNone = function () {
// BlockExportDialogMorph ops
BlockExportDialogMorph.prototype.exportBlocks = function () {
var str = this.serializer.serialize(this.blocks);
var str = encodeURIComponent(
this.serializer.serialize(this.blocks)
);
if (this.blocks.length > 0) {
window.open(encodeURI('data:text/xml,<blocks app="'
window.open('data:text/xml,<blocks app="'
+ this.serializer.app
+ '" version="'
+ this.serializer.version
+ '">'
+ str
+ '</blocks>'));
+ '</blocks>');
} else {
new DialogBoxMorph().inform(
'Export blocks',

452
gui.js
Wyświetl plik

@ -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-February-06';
modules.gui = '2015-July-28';
// Declarations
@ -81,6 +82,18 @@ var TurtleIconMorph;
var WardrobeMorph;
var SoundIconMorph;
var JukeboxMorph;
var StageHandleMorph;
// Get the full url without "snap.html"
var baseURL = (function getPath(location) {
var origin, path, slash;
path = location.pathname; // starts with a /
origin = location.origin; // has no trailing /
slash = path.lastIndexOf('/');
path = path.slice(0, slash + 1); // keep a trailing /
return origin + path;
}(window.location));
// IDE_Morph ///////////////////////////////////////////////////////////
@ -202,6 +215,7 @@ IDE_Morph.prototype.init = function (isAutoFill) {
// restore saved user preferences
this.userLanguage = null; // user language preference for startup
this.projectsInURLs = false;
this.applySavedSettings();
// additional properties:
@ -224,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;
@ -316,7 +331,8 @@ IDE_Morph.prototype.openIn = function (world) {
}
throw new Error('unable to retrieve ' + url);
} catch (err) {
return;
myself.showMessage('unable to retrieve project');
return '';
}
}
@ -396,8 +412,21 @@ IDE_Morph.prototype.openIn = function (world) {
myself.shield.destroy();
myself.shield = null;
msg.destroy();
myself.toggleAppMode(true);
myself.runScripts();
if (dict.editMode) {
myself.toggleAppMode(false);
} else {
myself.toggleAppMode(true);
}
if (!dict.noRun) {
myself.runScripts();
}
if (dict.hideControls) {
myself.controlBar.hide();
window.onbeforeunload = function () {nop(); };
}
}
]);
},
@ -971,9 +1000,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
@ -988,6 +1015,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 = [],
@ -1351,6 +1385,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();
}
@ -1482,10 +1517,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
@ -1534,7 +1569,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) {
@ -1542,21 +1582,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();
};
@ -1742,6 +1790,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();
@ -1795,7 +1846,9 @@ IDE_Morph.prototype.applySavedSettings = function () {
language = this.getSetting('language'),
click = this.getSetting('click'),
longform = this.getSetting('longform'),
plainprototype = this.getSetting('plainprototype');
longurls = this.getSetting('longurls'),
plainprototype = this.getSetting('plainprototype'),
keyboard = this.getSetting('keyboard');
// design
if (design === 'flat') {
@ -1828,6 +1881,20 @@ IDE_Morph.prototype.applySavedSettings = function () {
InputSlotDialogMorph.prototype.isLaunchingExpanded = true;
}
// project data in URLs
if (longurls) {
this.projectsInURLs = true;
} else {
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;
@ -2277,6 +2344,17 @@ IDE_Morph.prototype.settingsMenu = function () {
'uncheck to run scripts\nat normal speed',
'check to prioritize\nscript execution'
);
addPreference(
'Cache Inputs',
function () {
BlockMorph.prototype.isCachingInputs =
!BlockMorph.prototype.isCachingInputs;
},
BlockMorph.prototype.isCachingInputs,
'uncheck to stop caching\ninputs (for debugging the evaluator)',
'check to cache inputs\nboosts recursion',
true
);
addPreference(
'Rasterize SVGs',
function () {
@ -2301,6 +2379,21 @@ IDE_Morph.prototype.settingsMenu = function () {
'check for alternative\nGUI design',
false
);
addPreference(
'Project URLs',
function () {
myself.projectsInURLs = !myself.projectsInURLs;
if (myself.projectsInURLs) {
myself.saveSetting('longurls', true);
} else {
myself.removeSetting('longurls');
}
},
myself.projectsInURLs,
'uncheck to disable\nproject data in URLs',
'check to enable\nproject data in URLs',
true
);
addPreference(
'Sprite Nesting',
function () {
@ -2312,6 +2405,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',
@ -2351,6 +2460,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);
};
@ -2373,7 +2496,8 @@ IDE_Morph.prototype.projectMenu = function () {
menu.addItem(
'Save to disk',
'saveProjectToDisk',
'experimental - store this project\nin your downloads folder',
'store this project\nin the downloads folder\n'
+ '(in supporting browsers)',
new Color(100, 0, 0)
);
}
@ -2462,13 +2586,10 @@ IDE_Morph.prototype.projectMenu = function () {
function () {
// read a list of libraries from an external file,
var libMenu = new MenuMorph(this, 'Import library'),
libUrl = 'http://snap.berkeley.edu/snapsource/libraries/' +
'LIBRARIES';
libUrl = baseURL + 'libraries/' + 'LIBRARIES';
function loadLib(name) {
var url = 'http://snap.berkeley.edu/snapsource/libraries/'
+ name
+ '.xml';
var url = baseURL + 'libraries/' + name + '.xml';
myself.droppedText(myself.getURL(url), name);
}
@ -2585,7 +2706,7 @@ IDE_Morph.prototype.aboutSnap = function () {
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
world = this.world();
aboutTxt = 'Snap! 4.0\nBuild Your Own Blocks\n\n--- beta ---\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'
@ -2619,7 +2740,7 @@ IDE_Morph.prototype.aboutSnap = function () {
creditsTxt = localize('Contributors')
+ '\n\nNathan Dinsmore: Saving/Loading, Snap-Logo Design, '
+ 'countless bugfixes'
+ '\ncountless bugfixes and optimizations'
+ '\nKartik Chandra: Paint Editor'
+ '\nMichael Ball: Time/Date UI, many bugfixes'
+ '\n"Ava" Yuan Yuan: Graphic Effects'
@ -2802,6 +2923,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 = '';
@ -2848,7 +2970,7 @@ IDE_Morph.prototype.rawSaveProject = function (name) {
try {
localStorage['-snap-project-' + name]
= str = this.serializer.serialize(this.stage);
location.hash = '#open:' + str;
this.setURL('#open:' + str);
this.showMessage('Saved!', 1);
} catch (err) {
this.showMessage('Save failed: ' + err);
@ -2856,7 +2978,7 @@ IDE_Morph.prototype.rawSaveProject = function (name) {
} else {
localStorage['-snap-project-' + name]
= str = this.serializer.serialize(this.stage);
location.hash = '#open:' + str;
this.setURL('#open:' + str);
this.showMessage('Saved!', 1);
}
}
@ -2897,7 +3019,7 @@ IDE_Morph.prototype.exportProject = function (name, plain) {
str = encodeURIComponent(
this.serializer.serialize(this.stage)
);
location.hash = '#open:' + str;
this.setURL('#open:' + str);
window.open('data:text/'
+ (plain ? 'plain,' + str : 'xml,' + str));
menu.destroy();
@ -2910,7 +3032,7 @@ IDE_Morph.prototype.exportProject = function (name, plain) {
str = encodeURIComponent(
this.serializer.serialize(this.stage)
);
location.hash = '#open:' + str;
this.setURL('#open:' + str);
window.open('data:text/'
+ (plain ? 'plain,' + str : 'xml,' + str));
menu.destroy();
@ -2935,7 +3057,9 @@ IDE_Morph.prototype.exportGlobalBlocks = function () {
};
IDE_Morph.prototype.exportSprite = function (sprite) {
var str = this.serializer.serialize(sprite.allParts());
var str = encodeURIComponent(
this.serializer.serialize(sprite.allParts())
);
window.open('data:text/xml,<sprites app="'
+ this.serializer.app
+ '" version="'
@ -3019,6 +3143,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(
@ -3060,6 +3185,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);
@ -3184,7 +3310,13 @@ IDE_Morph.prototype.openProject = function (name) {
this.setProjectName(name);
str = localStorage['-snap-project-' + name];
this.openProjectString(str);
location.hash = '#open:' + str;
this.setURL('#open:' + str);
}
};
IDE_Morph.prototype.setURL = function (str) {
if (this.projectsInURLs) {
location.hash = str;
}
};
@ -3377,6 +3509,7 @@ IDE_Morph.prototype.toggleAppMode = function (appMode) {
this.controlBar.projectButton,
this.controlBar.settingsButton,
this.controlBar.stageSizeButton,
this.stageHandle,
this.corral,
this.corralBar,
this.spriteEditor,
@ -3400,6 +3533,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);
@ -3436,36 +3572,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());
};
}
@ -3475,14 +3607,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; }
@ -4186,8 +4324,7 @@ IDE_Morph.prototype.getURLsbeOrRelative = function (url) {
var request = new XMLHttpRequest(),
myself = this;
try {
request.open('GET', 'http://snap.berkeley.edu/snapsource/' +
url, false);
request.open('GET', baseURL + url, false);
request.send();
if (request.status === 200) {
return request.responseText;
@ -4632,8 +4769,7 @@ ProjectDialogMorph.prototype.setSource = function (source) {
myself.nameField.setContents(item.name || '');
}
src = myself.ide.getURL(
'http://snap.berkeley.edu/snapsource/Examples/' +
item.name + '.xml'
baseURL + 'Examples/' + item.name + '.xml'
);
xml = myself.ide.serializer.parse(src);
@ -4687,8 +4823,9 @@ ProjectDialogMorph.prototype.getLocalProjectList = function () {
ProjectDialogMorph.prototype.getExamplesProjectList = function () {
var dir,
projects = [];
//alert(baseURL);
dir = this.ide.getURL('http://snap.berkeley.edu/snapsource/Examples/');
dir = this.ide.getURL(baseURL + 'Examples/');
dir.split('\n').forEach(
function (line) {
var startIdx = line.search(new RegExp('href=".*xml"')),
@ -4707,8 +4844,8 @@ ProjectDialogMorph.prototype.getExamplesProjectList = function () {
}
}
);
projects.sort(function (x, y) {
return x.name < y.name ? -1 : 1;
projects = projects.sort(function (x, y) {
return x.name.toLowerCase() < y.name.toLowerCase() ? -1 : 1;
});
return projects;
};
@ -4807,10 +4944,7 @@ ProjectDialogMorph.prototype.openProject = function () {
if (this.source === 'cloud') {
this.openCloudProject(proj);
} else if (this.source === 'examples') {
src = this.ide.getURL(
'http://snap.berkeley.edu/snapsource/Examples/' +
proj.name + '.xml'
);
src = this.ide.getURL(baseURL + 'Examples/' + proj.name + '.xml');
this.ide.openProjectString(src);
this.destroy();
} else { // 'local'
@ -4980,6 +5114,7 @@ ProjectDialogMorph.prototype.deleteProject = function () {
ProjectDialogMorph.prototype.shareProject = function () {
var myself = this,
ide = this.ide,
proj = this.listField.selected,
entry = this.listField.active;
@ -5010,6 +5145,15 @@ ProjectDialogMorph.prototype.shareProject = function () {
myself.ide.cloudError(),
[proj.ProjectName]
);
// Set the Shared URL if the project is currently open
if (proj.ProjectName === ide.projectName) {
var usr = SnapCloud.username,
projectId = 'Username=' +
encodeURIComponent(usr.toLowerCase()) +
'&ProjectName=' +
encodeURIComponent(proj.ProjectName);
location.hash = projectId;
}
},
myself.ide.cloudError()
);
@ -5020,6 +5164,7 @@ ProjectDialogMorph.prototype.shareProject = function () {
ProjectDialogMorph.prototype.unshareProject = function () {
var myself = this,
ide = this.ide,
proj = this.listField.selected,
entry = this.listField.active;
@ -5051,6 +5196,10 @@ ProjectDialogMorph.prototype.unshareProject = function () {
myself.ide.cloudError(),
[proj.ProjectName]
);
// Remove the shared URL if the project is open.
if (proj.ProjectName === ide.projectName) {
location.hash = '';
}
},
myself.ide.cloudError()
);
@ -5174,7 +5323,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 = [
@ -5204,6 +5353,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;
@ -5219,7 +5373,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
);
@ -5390,6 +5544,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,
@ -5424,6 +5581,10 @@ SpriteIconMorph.prototype.exportSprite = function () {
this.object.exportSprite();
};
SpriteIconMorph.prototype.chooseExemplar = function () {
this.object.chooseExemplar();
};
SpriteIconMorph.prototype.showSpriteOnStage = function () {
this.object.showOnStage();
};
@ -6443,3 +6604,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.

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 183 KiB

BIN
help/doCallCC.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 127 KiB

BIN
help/doPauseAll.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 139 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 176 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 138 KiB

BIN
help/doStopThis.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 167 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 82 KiB

7
help/manual/.gitignore vendored 100644
Wyświetl plik

@ -0,0 +1,7 @@
*.aux
*.log
*.out
*.toc
en/snap-manual.pdf
pl/snap-podrecznik.pdf
*.synctex.gz

Wyświetl plik

@ -0,0 +1,39 @@
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{baskervald} % Default font
\usepackage{setspace} \onehalfspacing
\usepackage{graphicx}
\usepackage{color}
\usepackage{textcomp}
\usepackage{hyperref}
% This macro produces a "Snap!" logo.
%
% Note that in Polish (and other languages), nouns are inflected. The form "Snap!" with suffix looks plain stupid, so the macro takes a suffix as argument. If the suffix is non-empty, no exclamation mark is generated, and the suffix is used instead.
\newcommand{\Snap}[1]{%
\textsf{%
Snap%
\ifx\\#1\\\textit{!\@}%
\else #1%
\fi%
}%
}
\newcommand{\code}[1]{\textsf{#1}}
\newcommand{\defaultGraphicsScale}{0.6}
\renewcommand{\thechapter}{\Roman{chapter}}
\renewcommand{\thesection}{\Alph{section}}
\renewcommand{\thesubsection}{}
\newcommand{\inlinepic}[1]{%
\raisebox{-4pt}{%
\includegraphics[scale=\defaultGraphicsScale]{#1}%
}%
}
\newcommand{\bigpic}[1]{
\begin{center}
\includegraphics[scale=\defaultGraphicsScale]{#1}
\end{center}
}

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.5 KiB

Wyświetl plik

@ -0,0 +1,159 @@
\documentclass{report}
\input{../common/defs.tex}
\begin{document}
\title{\Snap{} Reference Manual}
\author{Brian Harvey \and Jens M\"{o}nig}
\date{}
\maketitle
\tableofcontents
\chapter*{}
\section*{Acknowledgements}
We have been extremely lucky in our mentors. Jens cut his teeth in the company of the Smalltalk pioneers: Alan Kay, Dan Ingalls, and the rest of the gang who invented personal computing and object oriented programming in the great days of Xerox PARC. He worked with John Maloney, of the MIT Scratch Team, who developed the Morphic graphics framework that's still at the heart of \Snap{}. The brilliant design of Scratch, from the Lifelong Kindergarten Group at the MIT Media Lab, is crucial to \Snap{}.
\textbf{\emph{Our earlier version, BYOB, was a direct modification of the Scratch source code. \Snap{} is a complete rewrite, but its code structure and its user interface remain deeply indebted to Scratch. And the Scratch Team, who could have seen us as rivals, have been entirely supportive and welcoming to us.}}
Brian grew up at the MIT and Stanford Artificial Intelligence Labs, learning from Lisp inventor John McCarthy, Scheme inventors Gerald~J. Sussman and Guy Steele, and the authors of the world's best computer science book, \textit{Structure and Interpretation of Computer Programs}, Hal Abelson and Gerald~J. Sussman with Julie Sussman, among many other heroes of computer science.
\textbf{\emph{In the glory days of the MIT Logo Lab, we used to say, ``Logo is Lisp disguised as BASIC.'' Now, with its first class procedures, lexical scope, and first class continuations, \Snap{} is Scheme disguised as Scratch.}}
We have been fortunate to get to know an amazing group of brilliant middle school (!\@) and high school students through the Scratch Advanced Topics forum, several of whom have contributed code to \Snap{}: Kartik Chandra, Nathan Dinsmore, Connor Hudson, and Ian Reynolds. Many more have contributed ideas and alpha-testing bug reports. UC Berkeley students who've contributed code include Michael Ball, Achal Dave, Kyle Hotchkiss, Ivan Motyashov, and Yuan Yuan. Contributors of translations are too numerous to list here, but they're in the ``About...'' box in \Snap{} itself. This work was supported in part by the National Science Foundation grant 1143566, and in part by MioSoft.
\clearpage
\begin{center}
\bf \Huge \Snap{} Reference Manual \\
\huge Version 4.0
\vspace{40pt}
\end{center}
\Snap{} (formerly BYOB) is an extended reimplementation of Scratch (\url{http://scratch.mit.edu}) that allows you to Build Your Own Blocks. It also features first class lists, first class procedures, and continuations. These added capabilities make it suitable for a serious introduction to computer science for high school or college students. To run \Snap{}, open a browser window and connect to either \url{http://snap.berkeley.edu/run} to start with a minimal set of blocks or \url{http://snap.berkeley.edu/init} to load a small set of additional blocks (a little slower startup, but recommended for convenience and assumed in this manual).
\clearpage
\chapter{Blocks, Scripts, and Sprites}
This chapter describes the \Snap{} features inherited from Scratch; experienced Scratch users can skip to section~\ref{sec:nesting-sprites}.
\Snap{} is a programming language---a notation in which you can tell a computer what you want it to do. Unlike most programming languages, though, \Snap{} is a visual language; instead of writing a program using the keyboard, the \Snap{} programmer uses the same drag-and-drop interface familiar to computer users.
Start \Snap{}. You should see the following arrangement of regions in the window:
\begin{center}
\includegraphics[width=\textwidth]{window-regions}
\end{center}
(The proportions of these areas may be different, depending on the size and shape of your browser window.)
A \Snap{} program consists of one or more \emph{scripts}, each of which is made of \emph{blocks}. Here's a typical script:
\label{fig:typical-script}
\bigpic{typical-script}
The five blocks that make up this script have three different colors, corresponding to three of the eight \emph{palettes} in which blocks can be found. The palette area at the left edge of the window shows one palette at a time, chosen with the eight buttons just above the palette area. In this script, the gold blocks are from the Control palette; the green block is from the Pen palette; and the blue blocks are from the Motion palette. A script is assembled by dragging blocks from a palette into the \emph{scripting area} in the middle part of the window. Blocks snap together (hence the name \Snap{} for the language) when you drag a block so that its indentation is near the tab of the one above it:
\bigpic{snapping-blocks}
The white horizontal line is a signal that if you let go of the green block it will snap into the tab of the gold one.
\subsection{Hat Blocks and Command Blocks}
At the top of the script is a \emph{hat} block, which indicates when the script should be carried out. Hat block names typically start with the word ``\code{when}''; in this example, the script should be run when the green flag near the right end of the \Snap{} tool bar is clicked. (The \Snap{} tool bar is part of the \Snap{} window, not the same as the browser's or operating system's menu bar.) A script isn't required to have a hat block, but if not, then the script will be run only if the user clicks on the script itself. A script can't have more than one hat block, and the hat block can be used only at the top of the script; its distinctive shape is meant to remind you of that.
The other blocks in this script are \emph{command} blocks. Each command block corresponds to an action that \Snap{} already knows how to carry out. For example, the block \inlinepic{move-10-steps} tells the sprite (the arrowhead shape on the \emph{stage} at the right end of the window) to move ten steps (a step is a very small unit of distance) in the direction in which the arrowhead is pointing. We'll see shortly that there can be more than one sprite, and that each sprite has its own scripts. Also, a sprite doesn't have to look like an arrowhead, but can have any picture as a costume. The shape of the \code{move} block is meant to remind you of a Lego\texttrademark{} brick; a script is a stack of blocks. (The word ``block'' denotes both the graphical shape on the screen and the procedure, the action, that the block carries out.)
The number~10 in the \code{move} block above is called an \emph{input} to the block. By clicking on the white oval, you can type any number in place of the 10. The sample script on page~\pageref{fig:typical-script} uses 100 as the input value. We'll see later that inputs can have non-oval shapes that accept values other than numbers. We'll also see that you can compute input values, instead of typing a particular value into the oval. A block can have more than one input slot. For example, the \code{glide} block located about halfway down the Motion palette has three inputs.
Most command blocks have that brick shape, but some, like the \code{repeat} block in the sample script, are \emph{C-shaped}. Most C-shaped blocks are found in the Control palette. The slot inside the C shape is a special kind of input slot that accepts a \emph{script} as the input. In the sample script, the \code{repeat} block has two inputs: the number 4 and the script
\bigpic{typical-script-inner}
\section{Sprites and Parallelism}
\subsection{Costumes and Sounds}
\subsection{Inter-Sprite Communication with Broadcast}
\section{Nesting Sprites: Anchors and Parts}
\label{sec:nesting-sprites}
\section{Reporter Blocks and Expressions}
\section{Predicates and Conditional Evaluation}
\section{Variables}
\subsection{Global Variables}
\subsection{Script Variables}
\section{Etcetera}
\chapter{Saving and Loading Projects and Media}
\section{Local Storage}
\subsection{Localstore}
\subsection{XML Export}
\section{Cloud Storage}
\section{Loading Saved Projects}
\chapter{Building a Block}
\section{Simple Blocks}
\subsection{Custom Blocks with Inputs}
\section{Recursion}
\section{Block Libraries}
\chapter{First Class Lists}
\section{The list Block}
\section{Lists of Lists}
\section{Functional and Imperative List Programming}
\section{Higher Order List Operations and Rings}
\chapter{Typed Inputs}
\section{Scratch's Type Notation}
\section{The \Snap{} Input Type Dialog}
\subsection{Procedure Types}
\subsection{Pulldown inputs}
\subsection{Input variants}
\subsection{Prototype Hints}
\subsection{Title Text and Symbols}
\chapter{Procedures as Data}
\section{Call and Run}
\subsection{Call/Run with inputs}
\subsection{Variables in Ring Slots}
\section{Writing Higher Order Procedures}
\subsection{Recursive Calls to Multiple-Input Blocks}
\section{Formal Parameters}
\section{Procedures as Data}
\section{Special Forms}
\subsection{Special Forms in Scratch}
\chapter{Object Oriented Programming}
\section{Local State with Script Variables}
\section{Messages and Dispatch Procedures}
\section{Inheritance via Delegation}
\section{An Implementation of Prototyping OOP}
\chapter{The Outside World}
\section{The World Wide Web}
\section{Hardware Devices}
\section{Date and Time}
\chapter{Continuations}
\section{Continuation Passing Style}
\section{Call/Run w/Continuation}
\subsection{Nonlocal exit}
\chapter{User Interface Elements}
\section{Tool Bar Features}
\subsection{The \Snap{} Logo Menu}
\subsection{The File Menu}
\subsection{The Cloud Menu}
\subsection{The Settings Menu}
\subsection{Stage Resizing Buttons}
\subsection{Project Control Buttons}
\section{The Palette Area}
\subsection{Context Menus for Palette Blocks}
\subsection{Context Menu for the Palette Background}
\section{The Scripting Area}
\subsection{Sprite Appearance and Behavior Controls}
\subsection{Scripting Area Tabs}
\subsection{Scripts and Blocks Within Scripts}
\subsection{Scripting Area Background Context Menu}
\subsection{Controls in the Costumes Tab}
\subsection{The Paint Editor}
\subsection{Controls in the Sounds Tab}
\section{Controls on the Stage}
\section{The Sprite Corral and Sprite Creation Buttons}
\end{document}

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 12 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.5 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 11 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 139 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.9 KiB

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,59 @@
%% Creator: Inkscape inkscape 0.48.4, www.inkscape.org
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
%% Accompanies image file 'obszary-okna.pdf' (pdf, eps, ps)
%%
%% To include the image in your LaTeX document, write
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics{<filename>.pdf}
%% To scale the image, write
%% \def\svgwidth{<desired width>}
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics[width=<desired width>]{<filename>.pdf}
%%
%% Images with a different path to the parent latex file can
%% be accessed with the `import' package (which may need to be
%% installed) using
%% \usepackage{import}
%% in the preamble, and then including the image with
%% \import{<path to file>}{<filename>.pdf_tex}
%% Alternatively, one can specify
%% \graphicspath{{<path to file>/}}
%%
%% For more information, please see info/svg-inkscape on CTAN:
%% http://tug.ctan.org/tex-archive/info/svg-inkscape
%%
\begingroup%
\makeatletter%
\providecommand\color[2][]{%
\errmessage{(Inkscape) Color is used for the text in Inkscape, but the package 'color.sty' is not loaded}%
\renewcommand\color[2][]{}%
}%
\providecommand\transparent[1]{%
\errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package 'transparent.sty' is not loaded}%
\renewcommand\transparent[1]{}%
}%
\providecommand\rotatebox[2]{#2}%
\ifx\svgwidth\undefined%
\setlength{\unitlength}{855.2bp}%
\ifx\svgscale\undefined%
\relax%
\else%
\setlength{\unitlength}{\unitlength * \real{\svgscale}}%
\fi%
\else%
\setlength{\unitlength}{\svgwidth}%
\fi%
\global\let\svgwidth\undefined%
\global\let\svgscale\undefined%
\makeatother%
\begin{picture}(1,0.60243218)%
\put(0,0){\includegraphics[width=\unitlength]{obszary-okna.pdf}}%
\put(0.37031041,0.03597468){\color[rgb]{1,0,0}\makebox(0,0)[b]{\smash{\emph{\Large Obszar skryptów}}}}%
\put(0.42733084,0.57941921){\color[rgb]{1,0,0}\makebox(0,0)[b]{\smash{\emph{\small Pasek narzędzi}}}}%
\put(0.77489765,0.03597473){\color[rgb]{1,0,0}\makebox(0,0)[b]{\smash{\emph{\Large Zagroda duszków}}}}%
\put(0.09676227,0.03597473){\color[rgb]{1,0,0}\makebox(0,0)[b]{\smash{\emph{\Large Paleta}}}}%
\put(0.77708296,0.27919271){\color[rgb]{1,0,0}\makebox(0,0)[b]{\smash{\emph{\Large Scena}}}}%
\end{picture}%
\endgroup%

Plik diff jest za duży Load Diff

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 98 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 3.1 KiB

Wyświetl plik

@ -0,0 +1,167 @@
% !TeX spellcheck = pl
\documentclass{report}
\input{../common/defs.tex}
\usepackage[polish]{babel}
\usepackage{polski}
\frenchspacing
\usepackage{indentfirst}
\begin{document}
\title{\Snap{} \\ Podręcznik użytkownika}
\author{Brian Harvey \and Jens M\"{o}nig}
\date{}
\maketitle
\tableofcontents
\chapter*{}
\section*{Podziękowania}
Mieliśmy ogromne szczęście do mentorów. Jens zdobył dużo doświadczenia pracując wśród pionierów Smalltalka: Alana Kaya, Dana Ingallsa i~reszty ekipy, która wynalazła komputery osobiste i~programowanie obiektowe w~najlepszych dniach firmy Xerox PARC. Pracował z~Johnem Maloneyem z~zespołu Scratcha w~MIT\footnote{Massachusetts Institute of Technology, amerykańska uczelnia techniczna --- przyp. tłum.}, autorem platformy graficznej Morphic, wciąż stanowiącej fundament \Snap{a}. Znakomity projekt języka Scratch, autorstwa Lifelong Kindergarten Group z~MIT Media Lab, odgrywa w~\Snap{ie} kluczową rolę.
\textbf{\emph{Nasza poprzednia wersja, BYOB, była bezpośrednią modyfikacją kodu źródłowego Scratcha. \Snap{} został napisany od zera, lecz struktura jego kodu oraz interfejs użytkownika pozostają mocno zakorzenione w~Scratchu. Z~kolei zespół Scratcha, który mógłby widzieć w~nas rywali, przyjął nas ciepło i~okazał nam całkowite wsparcie.}}
Brian zdobywał szlify w~MIT oraz Stanford Artificial Intelligence Labs\footnote{Laboratorium sztucznej inteligencji na Uniwersytecie Stanforda --- przyp. tłum.}, gdzie uczył się pod okiem Johna McCarthy'ego, twórcy Lispa, oraz Geralda~J. Suss\-mana i~Guya Steele'a, twórców języka Scheme. Zdobywał również wiedzę od wielu innych wybitnych informatyków, w~tym autorów najlepszej książki z zakresu informatyki --- \emph{Struktury i~interpretacji programów komputerowych}: Hala Abelsona, Geralda~J. Suss\-mana i~Julie Suss\-man.
\textbf{\emph{Za starych dobrych czasów mawialiśmy w~MIT Logo Lab: ,,Język Logo to Lisp w przebraniu BASIC-a''. Dziś, ze swoimi pierwszoklasowymi procedurami, zasięgami leksykalnymi~i pierwszoklasowymi kontynuacjami, \Snap{} jest jak Scheme w~przebraniu Scratcha.}}
Szczęśliwym zrządzeniem losu, poprzez forum Scratch Advanced Topics, poznaliśmy wspaniałą grupę błyskotliwych uczniów gimnazjów~(!\@) i liceów. Kilku z nich wniosło swój wkład w~kod \Snap{a}: Kartik Chandra, Nathan Dinsmore, Connor Hudson i~Ian Reynolds. Ponadto wielu zgłosiło pomysły i~raporty błędów podczas testowania wersji alfa. Wśród studentów Uniwersytetu Kalifornijskiego w~Berkeley, którzy przyczynili się do rozwoju kodu, znajdują się Michael Ball, Achal Dave, Kyle Hotchkiss, Ivan Motyashov i~Yuan Yuan. Wymienianie wszystkich tłumaczy zajęłoby zbyt wiele miejsca, ale można ich odnaleźć w~okienku ,,O Snap!...'' dostępnym w~programie. Niniejsze dzieło powstało częściowo w~ramach grantu nr~1143566 udzielonego przez National Science Foundation, a częściowo przy wsparciu firmy MioSoft.
\clearpage
\begin{center}
\bf \Huge \Snap{} \\
Podręcznik użytkownika \\
\huge Wersja 4.0 \vspace{40pt}
\end{center}
\Snap{} to rozszerzona reimplementacja języka Scratch (\url{http://scratch.mit.edu}), która pozwala na tworzenie własnych bloków (ang.\ \textit{Build Your Own Blocks}; stąd dawna nazwa \Snap{a} --- BYOB). Opisywany tu język obsługuje pierwszoklasowe listy, procedury i~kontynuacje. Te dodatkowe możliwości sprawiają, że nadaje się on do przeprowadzenia poważnego wstępu do informatyki dla uczniów liceów i szkół wyższych. Aby uruchomić środowisko \Snap{}, wystarczy otworzyć przeglądarkę internetową i~wpisać adres \url{http://snap.berkeley.edu/run}, aby zacząć pracę z~minimalnym zestawem bloków. Można też użyć adresu \url{http://snap.berkeley.edu/init}, aby załadować niewielki zestaw dodatkowych bloków. Wiąże się to z~nieco wolniejszym ładowaniem, ale jest zalecane dla wygody użytkowników (w~dalszej części podręcznika będziemy zakładali korzystanie z~tej właśnie metody).
\clearpage
\chapter{Bloki, skrypty i duszki}
W~tym rozdziale poznamy kilka cech języka \Snap{} odziedziczonych po Scratchu; doświadczeni użytkownicy Scratcha mogą przejść od razu do sekcji~\ref{sec:zagnieżdżanie-duszków}.
\Snap{} jest językiem programowania --- notacją, przy pomocy której możemy powiedzieć komputerowi, co ma zrobić. Jednak w~odróżnieniu od większości innych, \Snap{} jest językiem wizualnym; programując w~nim, zamiast posługiwać się klawiaturą, używamy metody ,,przeciągnij i~upuść'', dobrze znanej użytkownikom komputerów.
Uruchom teraz środowisko \Snap{}. Powinieneś zobaczyć ekran podzielony na kilka obszarów:
\begin{center}
\def\svgwidth{\textwidth}
\input{obszary-okna.pdf_tex}
\end{center}
(Proporcje tych stref mogą się różnić, w~zależności od rozmiaru i~kształtu okna przeglądarki.)
Program w~języku \Snap{} składa się z~jednego lub więcej \emph{skryptów}, te zaś z~kolei --- z~\emph{bloków}. Oto przykładowy skrypt:
\label{fig:typowy-skrypt}
\bigpic{typowy-skrypt}
Na powyższy skrypt składa się pięć bloków w~trzech różnych kolorach, odpowiadających trzem z~ośmiu \emph{palet} z~blokami. Obszar palet, znajdujący się po lewej stronie okna, pokazuje jedną paletę na raz. Do zmiany widocznej palety służy osiem przycisków znajdujących się tuż nad tym obszarem. Bloki ciemnożółte, widoczne w~naszym skrypcie, pochodzą z~palety ,,Kontrola''; zielone z~palety ,,Pisak'', a~niebieskie --- z~palety ,,Ruch''. Aby złożyć taki skrypt, należy poprzeciągać odpowiednie bloki z~palet do \emph{obszaru skryptów}, umiejscowionego na środku okna. Kiedy układamy jeden blok pod drugim w~taki sposób, aby wcięcie dolnego bloku znalazło się w~pobliżu wypustki tego powyżej, bloki łączą się ze sobą (ang. \textit{snap together}; stąd nazwa języka \Snap{}):
\bigpic{laczenie-blokow}
Pozioma biała linia sygnalizuje, że jeśli puścimy zielony blok, połączy się on z~wypustką ciemnożółtego.
\subsection{Bloki-czapki i bloki poleceń}
Na górze skryptu znajduje się \emph{blok-czapka}, który określa, kiedy skrypt ma zostać wykonany. Nazwy bloków-czapek zazwyczaj zaczynają się słowem ,,\code{kiedy}''; nasz przykładowy skrypt powinien zostać uruchomiony w~momencie kliknięcia zielonej flagi, znajdującej się w pobliżu prawej strony paska narzędzi \Snap{a}. (Pasek ten jest częścią okna programu \Snap{}; nie chodzi tutaj o pasek menu przeglądarki lub systemu operacyjnego.) Skrypt nie musi posiadać czapki, jednak w~takim przypadku zostanie wykonany tylko wtedy, gdy użytkownik sam go kliknie. Skrypt nie może mieć więcej niż jednej czapki; jej charakterystyczny kształt służy łatwiejszemu zapamiętaniu tej szczególnej własności.
Pozostałe bloki w naszym skrypcie to \emph{bloki poleceń}. Każdy z~nich oznacza jakąś akcję, którą \Snap{} potrafi wykonać. Na przykład blok \inlinepic{przesun-o-10-krokow} nakazuje duszkowi\footnote{W grafice komputerowej słowem ,,duszek'' (ang. \textit{sprite}) nazywa się ruchomy obiekt na ekranie --- przyp. tłum.}, czyli strzałce na \emph{scenie} po prawej stronie okna, aby przesunął się o~dziesięć kroków do przodu w~kierunku, w~którym jest zwrócony. Każdy krok to niewielka odległość na ekranie. Wkrótce przekonamy się, że na scenie może być więcej duszków, a~każdy z nich może mieć własne skrypty. Ponadto duszki nie muszą wyglądać jak strzałki; ich kostiumy mogą być dowolnymi obrazkami. Kształt bloku \code{przesuń} ma za zadanie przypominać klocek, skrypt zaś jest jak wieża z klocków. Słowa ,,blok'' będziemy używać dla oznaczenia zarówno graficznego symbolu na ekranie, jak i~procedury (akcji) jaką ten blok wykonuje.
Liczbę 10 w powyższym bloku \code{przesuń} nazywamy jego \emph{parametrem}. Kliknąwszy na białym, zaokrąglonym polu, możemy wpisać w~jej miejsce dowolną inną. W przykładowym skrypcie ze strony \pageref{fig:typowy-skrypt} parametrem jest liczba 100. Jak się później okaże, pola parametrów mogą mieć kształty inne od zaokrąglonych; oznacza to wtedy, że akceptują one wartości inne niż liczby. Zobaczymy również, że zamiast wpisywać konkretne wartości w~pola, możemy nakazać komputerowi je obliczać. Ponadto blok może mieć więcej niż jeden parametr. Na przykład blok \code{leć}, znajdujący się mniej więcej w~połowie palety ,,Ruch'', przyjmuje trzy parametry.
Większość bloków poleceń ma kształt klocków, lecz niektóre, jak \code{powtórz} z~tego samego przykładu, wyglądają jak \emph{klamry}. Większość bloków klamrowych można znaleźć na palecie ,,Kontrola'. Wnętrze klamry jest szczególnym rodzajem pola parametru, który przyjmuje \emph{skrypt} jako parametr. W~przykładowym skrypcie blok \code{powtórz} ma dwa parametry: liczbę 4 oraz skrypt
\bigpic{typowy-skrypt-wnetrze}
\section{Sprites and Parallelism}
\subsection{Costumes and Sounds}
\subsection{Inter-Sprite Communication with Broadcast}
\section{Zagnieżdżanie duszków: kotwice i części}
\label{sec:zagnieżdżanie-duszków}
\section{Reporter Blocks and Expressions}
\section{Predicates and Conditional Evaluation}
\section{Variables}
\subsection{Global Variables}
\subsection{Script Variables}
\section{Etcetera}
\chapter{Saving and Loading Projects and Media}
\section{Local Storage}
\subsection{Localstore}
\subsection{XML Export}
\section{Cloud Storage}
\section{Loading Saved Projects}
\chapter{Building a Block}
\section{Simple Blocks}
\subsection{Custom Blocks with Inputs}
\section{Recursion}
\section{Block Libraries}
\chapter{First Class Lists}
\section{The list Block}
\section{Lists of Lists}
\section{Functional and Imperative List Programming}
\section{Higher Order List Operations and Rings}
\chapter{Typed Inputs}
\section{Scratch's Type Notation}
\section{The \Snap{} Input Type Dialog}
\subsection{Procedure Types}
\subsection{Pulldown inputs}
\subsection{Input variants}
\subsection{Prototype Hints}
\subsection{Title Text and Symbols}
\chapter{Procedures as Data}
\section{Call and Run}
\subsection{Call/Run with inputs}
\subsection{Variables in Ring Slots}
\section{Writing Higher Order Procedures}
\subsection{Recursive Calls to Multiple-Input Blocks}
\section{Formal Parameters}
\section{Procedures as Data}
\section{Special Forms}
\subsection{Special Forms in Scratch}
\chapter{Object Oriented Programming}
\section{Local State with Script Variables}
\section{Messages and Dispatch Procedures}
\section{Inheritance via Delegation}
\section{An Implementation of Prototyping OOP}
\chapter{The Outside World}
\section{The World Wide Web}
\section{Hardware Devices}
\section{Date and Time}
\chapter{Continuations}
\section{Continuation Passing Style}
\section{Call/Run w/Continuation}
\subsection{Nonlocal exit}
\chapter{User Interface Elements}
\section{Tool Bar Features}
\subsection{The \Snap{} Logo Menu}
\subsection{The File Menu}
\subsection{The Cloud Menu}
\subsection{The Settings Menu}
\subsection{Stage Resizing Buttons}
\subsection{Project Control Buttons}
\section{The Palette Area}
\subsection{Context Menus for Palette Blocks}
\subsection{Context Menu for the Palette Background}
\section{The Scripting Area}
\subsection{Sprite Appearance and Behavior Controls}
\subsection{Scripting Area Tabs}
\subsection{Scripts and Blocks Within Scripts}
\subsection{Scripting Area Background Context Menu}
\subsection{Controls in the Costumes Tab}
\subsection{The Paint Editor}
\subsection{Controls in the Sounds Tab}
\section{Controls on the Stage}
\section{The Sprite Corral and Sprite Creation Buttons}
\end{document}

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 5.1 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 12 KiB

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 48 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 111 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 145 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 149 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 148 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 125 KiB

BIN
help/reportDate.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 388 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 176 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 132 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 206 KiB

BIN
help/reportURL.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 151 KiB

Wyświetl plik

@ -2435,3 +2435,136 @@ ______
------
* GUI: Added url switch #cloud: to open a shared project in edit mode
150220
------
* Malayam, Tamil and Telagu translations, thanks, Vinay Kumar!!
* Un-hide “Save to disk” feature (currently supported by both Chrome and Firefox, but not by Safari)
* Update German translation
* GUI: Make “project data in URLs” a hidden dev option (prevent long urls per default)
150223
------
* Blocks, Objects: Add user-interaction choices to the “When I am ...” hat block
* Update German translation
* Store: Avoid incompatibility warning for very old (pre-earmarked) projects
150224
------
* Store: fixed #725
150228
------
* Blocks, Store, GUI: Cache inputs, accelerates evaluating recursive reporters and warped / turbo recursive commands by up to 40%
* Objects: slightly optimize warped / turbo execution
* Threads: fixed #715
* BYOB: fixed #716
150302
------
* BYOB: fixed #730
150306
------
* Blocks: fixed #736
150309
------
* Blocks: fixed #738
* GUI, Blocks: Only enable input caching for blocks
150315
------
* Store: fixed #743
* GUI, html: switch from beta to release candidate
150325
------
* Threads: fixed #752
150415
------
* Threads: flush Stage>>keysPressed when prompting the user
* Objects: fixed #770
150426
------
* Store: fixed #784
150501
------
* Morphic, Blocks: select all text when first clicking an input slot
* BYOB: indicate numeric inputs in the block prototype with the # sign
* Threads: return empty string when querying first letter of a list
* GUI: hide “save to disk” option behind shift-click again (has issues in Chrome)
* GUI: parameters for embedding projects in iFrames, thanks, Bernat!
=== Release v4.0 ===
150518
------
* Objects, GUI: Fix encoding for exported sprites (esp. comments)
* Portuguese translation update, thanks, Manuel!!
150521
------
* BYOB: Fix encoding for exported libraries of global blocks
150523
------
* BYOB: Fix encoding glitch
150608
------
* Blocks: Fixed #820
150625
------
* Morphic, Objects, Blocks, XML: Optimizations and dramatic speed-up. Thanks, Nathan!!
* Objects: push maximum clone count up to 1000, tweak Note::play
=== 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
150806
------
* Polish & German translation updates
=== Release v4.0.2 ===
150809
------
* Interlingua support, yay!! thanks, Ken Dickey!
150814
------
* Blocks: fixed #907

Wyświetl plik

@ -20,8 +20,8 @@
<script type="text/javascript" src="sha512.js"></script>
<script type="text/javascript" src="stitchcode/jquery.js"></script>
<script type="text/javascript" src="stitchcode/byob.js"></script>
<script type="text/javascript" src="stitchcode/blocks.js"></script>
<!--<script type="text/javascript" src="stitchcode/byob.js"></script>-->
<!--<script type="text/javascript" src="stitchcode/blocks.js"></script>-->
<script type="text/javascript" src="stitchcode/Filesaver.js"></script>
<script type="text/javascript" src="stitchcode/stitchcodeGUI.js"></script>
<script type="text/javascript" src="stitchcode/stitchcodeChangeSet.js"></script>

Wyświetl plik

@ -185,7 +185,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org', // optional
'last_changed':
'2014-07-29', // this, too, will appear in the Translators tab
'2015-08-06', // this, too, will appear in the Translators tab
// GUI
// control bar:
@ -417,8 +417,18 @@ SnapTranslator.dict.de = {
'Wenn %greenflag angeklickt',
'when %keyHat key pressed':
'Wenn Taste %keyHat gedr\u00fcckt',
'when I am clicked':
'Wenn ich angeklickt werde',
'when I am %interaction':
'Wenn ich %interaction werde',
'clicked':
'angeklickt',
'pressed':
'gedr\u00fcckt',
'dropped':
'abgestellt',
'mouse-entered':
'vom Mauszeiger betreten',
'mouse-departed':
'vom Mauszeiger verlassen',
'when I receive %msgHat':
'Wenn ich %msgHat empfange',
'broadcast %msg':
@ -647,6 +657,11 @@ SnapTranslator.dict.de = {
'\u00d6ffnen...',
'Save':
'Sichern',
'Save to disk':
'Abpeichern',
'store this project\nin the downloads folder\n(in supporting browsers)':
'dieses Projekt herunterladen\nund lokal speichern\n'
+ '(nicht von allen Browsern unters\u00fctzt)',
'Save As...':
'Sichern als...',
'Import...':
@ -765,6 +780,10 @@ SnapTranslator.dict.de = {
'ausschalten, um Skripte\nnormal auszuf\u00fchren',
'check to enable\nIDE animations':
'einschalten um IDE-\nAnimationen zu erlauben',
'Flat design':
'Helles Design',
'Keyboard Editing':
'Tastaturunterstützung',
'Thread safe scripts':
'Threadsicherheit',
'uncheck to allow\nscript reentrance':
@ -783,6 +802,8 @@ SnapTranslator.dict.de = {
'einschalten f\u00fcr flache\nPinselstrichenden',
'uncheck for round ends of lines':
'auschalten f\u00fcr runde\nPinselstrichenden',
'Inheritance support':
'Prototypische Vererbung',
// inputs
'with inputs':

Wyświetl plik

@ -185,7 +185,7 @@ SnapTranslator.dict.fr = {
'translator_e-mail':
'i.scool@mac.com', // optional
'last_changed':
'2014-02-04', // this, too, will appear in the Translators tab
'2015-06-25', // this, too, will appear in the Translators tab
// GUI
// control bar:
@ -392,7 +392,7 @@ SnapTranslator.dict.fr = {
'clear':
'effacer tout',
'pen down':
'stylo en position d\u0027\u00EAcriture',
'stylo en position d\u0027\u00E9criture',
'pen up':
'relever le stylo',
'set pen color to %clr':
@ -419,6 +419,8 @@ SnapTranslator.dict.fr = {
'Quand %keyHat est press\u00E9',
'when I am clicked':
'Quand je suis press\u00E9 ',
'when I am %interaction':
'Quand je suis %interaction',
'when I receive %msgHat':
'Quand je re\u00E7ois %msgHat',
'broadcast %msg':
@ -447,6 +449,10 @@ SnapTranslator.dict.fr = {
'arr\u00EAter le bloc',
'stop script':
'arr\u00EAter le script',
'stop %stopOthersChoices':
'arr\u00EAter %stopOthersChoices',
'stop %stopChoices':
'arr\u00EAter %stopChoices',
'stop all %stop':
'arr\u00EAter tout %stop',
'run %cmdRing %inputs':
@ -469,8 +475,16 @@ SnapTranslator.dict.fr = {
'moi-m\u00EAme',
'delete this clone':
'supprime ce clone',
'pause all':
'mettre en pause',
'pause all %pause':
'mettre en pause %pause',
'all but this script':
'tout sauf ce lutin',
'other scripts in sprite':
'les autres scripts de ce lutin',
'this script':
'ce script',
'this block':
'ce bloc',
// sensing:
'touching %col ?':
@ -958,6 +972,8 @@ SnapTranslator.dict.fr = {
'tabulations',
'cr':
'retours de ligne',
'letter':
'lettres',
// About Snap
'About Snap':
@ -1162,5 +1178,133 @@ SnapTranslator.dict.fr = {
'last':
'dernier',
'any':
'n\u0027importe quel'
'n\u0027importe quel',
// miscellaneous
'find blocks...':
'chercher des blocs...',
'hide primitives':
'cacher les primitives',
'show primitives':
'montrer les primitives',
'Login...':
'Connexion...',
'Signup...':
'S\u0027enregistrer...',
'Reset Password...':
'Remise \u00E0 z\u00E9ro du mot de passe',
'show all':
'tout montrer',
'pic...':
'image...',
'open a new window\nwith a picture of the stage':
'ouvre une nouvelle fen\u00EAtre\navec une image de la sc\u00E8ne',
'scripts pic...':
'image des scripts...',
'open a new window\nwith a picture of all scripts':
'ouvre une nouvelle fen\u00EAtre\navec une image de tous les scripts',
'Stage size...':
'Taille de la sc\u00E8ne...',
'Zoom blocks...':
'Agrandir les blocs...',
'Plain prototype labels':
'\u00C9tiquettes simples de d\u00E9finition',
'uncheck to always show (+) symbols\nin block prototype labels':
'd\u00E9cocher pour montrer en permance le symbole (+)\ndans les \u00e9tiquettes de d\u00E9finition de bloc',
'check to hide (+) symbols\nin block prototype labels':
'cocher pour cacher le symbole (+)\ndans les \u00e9tiquettes de d\u00E9finition de bloc',
'check for flat ends of lines':
'cocher pour dessiner des fins de ligne plates',
'uncheck for round ends of lines':
'd\u00E9cocher pour dessiner des fins de lignes arrondies',
'Flat line ends':
'Fins de ligne plates',
'Codification support':
'Support de la \u00AB codification \u00BB',
'uncheck to disable\nblock to text mapping features':
'd\u00E9cocher pour d\u00E9activer\nla fonction de transformation :\nbloc vers texte',
'check for block\nto text mapping features':
'cocher pour activer\nla fonction de transformation :\nbloc vers texte',
'current %dates':
'date courante %dates',
'year':'ann\u00E9e',
'month':'mois',
'date':'jour',
'hour':'heure',
'minute':'minute',
'second':'seconde',
'time in milliseconds':
'heure en millisecondes',
'day of week':
'jour de la semaine',
'brightness':
'luminosit\u00E9',
'transparence':
'transparence',
'negative':
'n\u00E9gatif',
'comic':
'bande dessin\u00E9e',
'clicked':
'cliqu\u00E9',
'pressed':
'press\u00E9',
'dropped':
'd\u00E9pos\u00E9',
'mouse-entered':
'survol\u00E9',
'mouse-departed':
'quitt\u00E9',
'JavaScript function ( %mult%s ) { %code }':
'fonction JavaScript ( %mult%s ) { %code }',
// Copy / Paste
'Press CTRL+C one more time to effectively copy to clipboard.':
'Taper une nouvelle fois sur CTRL+C pour copier effectivement vers le presse-papier.',
'Press CTRL+V one more time to effectively paste from clipboard.':
'Taper une nouvelle fois sur CTRL+V pour coller effectivement depuis le presse-papier.',
'Press CTRL+X one more time to effectively cut to clipboard.':
'Taper une nouvelle fois sur CTRL+X pour couper effectivement vers le presse-papier.',
// Paint.js
'undo':'d\u00E9faire',
'Paintbrush tool\n(free draw)':
'Pinceau\n(dessin \u00E0 main lev\u00E9)',
'Stroked Rectangle\n(shift: square)':
'Rectangle\n(Maj: carr\u00E9)',
'Stroked Ellipse\n(shift: circle)':
'Ellipse\n(Maj: cercle)',
'Eraser tool':
'Gomme',
'Set the rotation center':
'Fixe le centre de rotation',
'Line tool\n(shift: vertical/horizontal)':
'Ligne\n(Maj: verticale/horizontale)',
'Filled Rectangle\n(shift: square)':
'Rectangle plein\n(Maj: carr\u00E9)',
'Filled Ellipse\n(shift: circle)':
'Ellipse pleine\n(Maj: cercle)',
'Fill a region':
'Remplir une r\u00E9gion',
'Pipette tool\n(pick a color anywhere)':
'Pipette\n(s\u00E9lectionnez une couleur n\u0027importe o\u00F9',
'grow':'agrandir',
'shrink':'r\u00E9duire',
'flip \u2194':
'miroir \u2194',
'flip \u2195':
'miroir \u2195',
'Brush size':
'Taille de pinceau',
'Constrain proportions of shapes?\n(you can also hold shift)':
'Contrainte sur les proportions de la forme ?\n(vous pouvez aussi maintenir appuy\u00E9 Maj)'
};

1695
lang-hu.js 100644

Plik diff jest za duży Load Diff

1337
lang-ia.js 100644

Plik diff jest za duży Load Diff

1282
lang-ml.js 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -190,7 +190,7 @@ SnapTranslator.dict.pl = {
'translator_e-mail':
'witek@oeiizk.waw.pl', // optional
'last_changed':
'2013-08-05', // this, too, will appear in the Translators tab
'2015-08-06', // this, too, will appear in the Translators tab
// GUI
// control bar:
@ -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':
@ -331,7 +331,7 @@ SnapTranslator.dict.pl = {
'switch to costume %cst':
'zmie\u0144 kostium na %cst',
'next costume':
'nast\u0118pny kostium',
'następny kostium',
'costume #':
'kostium nr ',
'say %s for %n secs':
@ -343,7 +343,7 @@ SnapTranslator.dict.pl = {
'think %s':
'pomy\u015Bl %s',
'Hello!':
'Hallo!',
'Cześć!',
'Hmm...':
'Hmm...',
'change %eff effect by %n':
@ -421,8 +421,18 @@ SnapTranslator.dict.pl = {
'kiedy klikni\u0119to %greenflag',
'when %keyHat key pressed':
'kiedy klawisz %keyHat naci\u015Bni\u0119ty',
'when I am clicked':
'kiedy duszek klikni\u0119ty',
'when I am %interaction':
'kiedy zostanę %interaction',
'clicked':
'kliknięty',
'pressed':
'naciśnięty',
'dropped':
'upuszczony',
'mouse-entered':
'najechany przez kursor myszy',
'mouse-departed':
'opuszczony przez kursor myszy',
'when I receive %msgHat':
'kiedy otrzymam %msgHat',
'broadcast %msg':
@ -545,9 +555,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 +683,8 @@ SnapTranslator.dict.pl = {
'Logowanie...',
'Signup...':
'Rejestracja...',
'Reset Password...':
'Zresetuj hasło...',
// settings menu
'Language...':
@ -857,7 +869,7 @@ SnapTranslator.dict.pl = {
'Ok':
'Ok',
'Cancel':
'Poniechaj',
'Anuluj',
'Yes':
'Tak',
'No':
@ -903,9 +915,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 +1137,7 @@ SnapTranslator.dict.pl = {
// costumes
'Turtle':
'Duszek',
'Żółw',
'Empty':
'Pusty',
@ -1221,5 +1277,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'
};

Wyświetl plik

@ -185,7 +185,7 @@ SnapTranslator.dict.pt = {
'translator_e-mail':
'mmsequeira@gmail.com',
'last_changed':
'2014-10-01',
'2015-08-02',
// GUI
// control bar:
@ -417,8 +417,18 @@ SnapTranslator.dict.pt = {
'Quando alguém clicar em %greenflag',
'when %keyHat key pressed':
'Quando alguém pressionar a tecla %keyHat',
'when I am clicked':
'Quando alguém clicar em ti',
'when I am %interaction':
'Quando o rato %interaction',
'clicked':
'clicar em ti',
'pressed':
'pressionar em ti',
'dropped':
'te largar',
'mouse-entered':
'entrar em ti',
'mouse-departed':
'sair de ti',
'when I receive %msgHat':
'Quando receberes a mensagem %msgHat',
'broadcast %msg':
@ -647,13 +657,17 @@ SnapTranslator.dict.pt = {
'Abrir um projecto…',
'Save':
'Guardar este projecto',
'Save to disk':
'Guardar no disco',
'store this project\nin the downloads folder\n(in supporting browsers)':
'Guardar este projecto\nna sua pasta de descargas\n'
+ '(em navegadores que o suportem).',
'Save As...':
'Guardar este projecto como…',
'Import...':
'Importar…',
'file menu import hint':
'Abrir um projecto exportado,\n'
+ 'substitundo o projecto corrente, ou\n'
'Abrir um projecto exportado,\nsubstitundo o projecto corrente, ou\n'
+ 'importar uma biblioteca de blocos, um\n'
+ 'traje ou um som para o projecto corrente.',
'Export project as plain text...':
@ -1443,10 +1457,6 @@ SnapTranslator.dict.pt = {
'Suportar produção de código',
'check for block\nto text mapping features':
'Assinalar para funcionalidades\nde mapeamento entre blocos e texto.',
'Save to disk':
'Guardar no disco',
'experimental - store this project\nin your downloads folder':
'Experimental - Guardar este projecto\nna sua pasta de descargas.',
'saved.':
'guardado.',
'options...':
@ -1692,5 +1702,17 @@ SnapTranslator.dict.pt = {
+ 'nomes para os parâmetros (ignorando os nomes mostrados).',
'Enter code that corresponds to the block\'s operation (usually a single\nfunction invocation). Use <#n> to reference actual arguments as shown.':
'Introduza o código que corresponda à operação do bloco (normalmente uma simples\n'
+ 'invocação de rotina). Use <#n> para referenciar os argumentos tal como mostrado'
+ 'invocação de rotina). Use <#n> para referenciar os argumentos tal como mostrado',
'Keyboard Editing':
'Edição usando o teclado',
'uncheck to disable\nkeyboard editing support':
'Desassinalar para desactivar\na edição usando o teclado.',
'check to enable\nkeyboard editing support':
'Assinalar para activar\na edição usando o teclado.',
'Inheritance support':
'Suporte para herança',
'uncheck to disable\nsprite inheritance features':
'Desassinalar para desactivar\nfuncionalidades de herança de actores.',
'check for sprite\ninheritance features':
'Assinalar para activar\nfuncionalidades de herança de actores.'
};

1283
lang-ta.js 100644

Plik diff jest za duży Load Diff

1283
lang-te.js 100644

Plik diff jest za duży Load Diff

1275
lang-tr.js 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1 @@
<blocks app="Snap! 4.0, http://snap.berkeley.edu" version="1"><block-definition s="cases: if %&apos;test&apos; then %&apos;result&apos; %&apos;more&apos;" 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 %&apos;tag&apos; %&apos;action&apos;" 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 %&apos;cont&apos;" 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 %&apos;item&apos; of %&apos;data&apos; %&apos;action&apos;" 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 %&apos;test&apos; then %&apos;action&apos;" 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 %&apos;action&apos;" 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

Wyświetl plik

@ -7,7 +7,7 @@
written by Jens Mönig and Brian Harvey
jens@moenig.org, bh@cs.berkeley.edu
Copyright (C) 2014 by Jens Mönig and Brian Harvey
Copyright (C) 2015 by Jens Mönig and Brian Harvey
This file is part of Snap!.
@ -61,7 +61,7 @@ PushButtonMorph, SyntaxElementMorph, Color, Point, WatcherMorph,
StringMorph, SpriteMorph, ScrollFrameMorph, CellMorph, ArrowMorph,
MenuMorph, snapEquals, Morph, isNil, localize, MorphicPreferences*/
modules.lists = '2014-November-20';
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();
@ -634,6 +633,7 @@ ListWatcherMorph.prototype.setStartIndex = function (index) {
};
ListWatcherMorph.prototype.fixLayout = function () {
if (!this.label) {return; }
Morph.prototype.trackChanges = false;
if (this.frame) {
this.arrangeCells();

Wyświetl plik

@ -42,7 +42,7 @@
/*global modules, contains*/
modules.locale = '2015-January-21';
modules.locale = '2015-August-06';
// Global stuff
@ -149,7 +149,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org',
'last_changed':
'2014-07-29'
'2015-08-06'
};
SnapTranslator.dict.it = {
@ -209,7 +209,7 @@ SnapTranslator.dict.pt = {
'translator_e-mail':
'mmsequeira@gmail.com',
'last_changed':
'2014-10-01'
'2015-08-02'
};
SnapTranslator.dict.cs = {
@ -257,7 +257,7 @@ SnapTranslator.dict.fr = {
'translator_e-mail':
'i.scool@mac.com',
'last_changed':
'2014-02-04'
'2015-06-25'
};
SnapTranslator.dict.si = {
@ -317,7 +317,7 @@ SnapTranslator.dict.pl = {
'translator_e-mail':
'witek@oeiizk.waw.pl',
'last_changed':
'2013-08-05'
'2015-08-06'
};
SnapTranslator.dict.tw = {
@ -439,3 +439,75 @@ SnapTranslator.dict.kn = {
'last_changed':
'2014-12-02'
};
SnapTranslator.dict.ml = {
// translations meta information
'language_name':
'Malayalam',
'language_translator':
'vinayakumar R',
'translator_e-mail':
'vnkmr7620@gmail.com',
'last_changed':
'2015-02-20'
};
SnapTranslator.dict.ta = {
// translations meta information
'language_name':
'Tamil',
'language_translator':
'vinayakumar R',
'translator_e-mail':
'vnkmr7620@gmail.com',
'last_changed':
'2015-02-20'
};
SnapTranslator.dict.te = {
// translations meta information
'language_name':
'Telagu', // the name as it should appear in the language menu
'language_translator':
'vinayakumar R', // your name for the Translators tab
'translator_e-mail':
'vnkmr7620@gmail.com', // optional
'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'
};
SnapTranslator.dict.ia = {
// translations meta information
'language_name':
'Interlingua',
'language_translator':
'Ken Dickey',
'translator_e-mail':
'Ken.Dickey@whidbey.com',
'last_changed':
'2015-08-09'
};

Plik diff jest za duży Load Diff

Wyświetl plik

@ -7,9 +7,9 @@
written by Jens Mönig
jens@moenig.org
Copyright (C) 2012 by Jens Mönig
Copyright (C) 2015 by Jens Mönig
this documentation last changed: April 07, 2013
this documentation last changed: June 26, 2015
This file is part of Snap!.
@ -465,9 +465,15 @@
MyMorph.prototype.mouseMove = function(pos) {};
The only optional parameter of such a method is a Point object
All of these methods have as optional parameter a Point object
indicating the current position of the Hand inside the World's
coordinate system.
coordinate system. The
mouseMove(pos, button)
event method has an additional optional parameter indicating the
currently pressed mouse button, which is either 'left' or 'right'.
You can use this to let users interact with 3D environments.
Events may be "bubbled" up a morph's owner chain by calling
@ -522,6 +528,12 @@
a duplicate of the template whose "isDraggable" flag is true and
whose "isTemplate" flag is false, in other words: a non-template.
When creating a copy from a template, the copy's
reactToTemplateCopy
is invoked, if it is present.
Dragging is indicated by adding a drop shadow to the morph in hand.
If a morph follows the hand without displaying a drop shadow it is
merely being moved about without changing its parent (owner morph),
@ -817,13 +829,13 @@
// use context to paint stuff here
};
If your new morph stores or references other morphs outside of the
submorph tree in other properties, be sure to also override the
If your new morph stores or references to other morphs outside of
the submorph tree in other properties, be sure to also override the
default
copyRecordingReferences()
updateReferences()
method accordingly if you want it to support duplication.
method if you want it to support duplication.
(6) development and user modes
@ -1015,16 +1027,17 @@
programming hero.
I have originally written morphic.js in Florian Balmer's Notepad2
editor for Windows and later switched to Apple's Dashcode. I've also
come to depend on both Douglas Crockford's JSLint, Mozilla's Firebug
and Google's Chrome to get it right.
editor for Windows, later switched to Apple's Dashcode and later
still to Apple's Xcode. I've also come to depend on both Douglas
Crockford's JSLint, Mozilla's Firebug and Google's Chrome to get
it right.
IX. contributors
----------------------
Joe Otto found and fixed many early bugs and taught me some tricks.
Nathan Dinsmore contributed mouse wheel scrolling, cached
background texture handling and countless bug fixes.
background texture handling, countless bug fixes and optimizations.
Ian Reynolds contributed backspace key handling for Chrome.
Davide Della Casa contributed performance optimizations for Firefox.

Plik diff jest za duży Load Diff

Wyświetl plik

@ -5,7 +5,7 @@
inspired by the Scratch paint editor.
written by Kartik Chandra
Copyright (C) 2014 by Kartik Chandra
Copyright (C) 2015 by Kartik Chandra
This file is part of Snap!.
@ -69,7 +69,7 @@
// Global stuff ////////////////////////////////////////////////////////
modules.paint = '2014-September-29';
modules.paint = '2015-June-25';
// Declarations

Wyświetl plik

@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Snap! Build Your Own Blocks. Beta</title>
<title>Snap! Build Your Own Blocks</title>
<link rel="shortcut icon" href="favicon.ico">
<script type="text/javascript" src="morphic.js"></script>
<script type="text/javascript" src="widgets.js"></script>

Wyświetl plik

@ -1289,7 +1289,7 @@ IDE_Morph.prototype.createSpriteBar = function () {
active.refresh(); // needed when programmatically tabbing
myself.createSpriteEditor();
myself.fixLayout('tabEditor');
};
};t
tab = new TabMorph(
tabColors,
@ -1699,11 +1699,6 @@ IDE_Morph.prototype.snapMenu = function () {
menu.popup(world, this.logo.bottomLeft());
};
IDE_Morph.prototype.originalCreatePalette = IDE_Morph.prototype.createPalette;
IDE_Morph.prototype.createPalette = function(){
this.originalCreatePalette();
this.palette.color = new Color(230, 230, 230);
}
IDE_Morph.prototype.originalCreateSpriteEditor = IDE_Morph.prototype.createSpriteEditor;
IDE_Morph.prototype.createSpriteEditor = function(){

Wyświetl plik

@ -61,7 +61,7 @@ SyntaxElementMorph, Variable*/
// Global stuff ////////////////////////////////////////////////////////
modules.store = '2015-January-21';
modules.store = '2015-July-27';
// XML_Serializer ///////////////////////////////////////////////////////
@ -320,7 +320,7 @@ SnapSerializer.prototype.loadProjectModel = function (xmlNode, ide) {
var appInfo = xmlNode.attributes.app,
app = appInfo ? appInfo.split(' ')[0] : null;
if (ide && app !== this.app.split(' ')[0]) {
if (ide && app && app !== this.app.split(' ')[0]) {
ide.inform(
app + ' Project',
'This project has been created by a different app:\n\n' +
@ -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;
@ -531,8 +542,8 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) {
}
watcher.setStyle(model.attributes.style || 'normal');
if (watcher.style === 'slider') {
watcher.setSliderMin(model.attributes.min || '1');
watcher.setSliderMax(model.attributes.max || '100');
watcher.setSliderMin(model.attributes.min || '1', true);
watcher.setSliderMax(model.attributes.max || '100', true);
}
watcher.setPosition(
project.stage.topLeft().add(new Point(
@ -639,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) {
@ -651,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;
@ -699,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');
@ -782,7 +810,7 @@ SnapSerializer.prototype.loadCustomBlocks = function (
names = definition.parseSpec(definition.spec).filter(
function (str) {
return str.charAt(0) === '%';
return str.charAt(0) === '%' && str.length > 1;
}
).map(function (str) {
return str.substr(1);
@ -977,7 +1005,11 @@ SnapSerializer.prototype.loadBlock = function (model, isReporter) {
);
}
if (!receiver) {
return this.obsoleteBlock(isReporter);
if (!isGlobal) {
receiver = this.project.stage;
} else {
return this.obsoleteBlock(isReporter);
}
}
if (isGlobal) {
info = detect(receiver.globalBlocks, function (block) {
@ -1023,6 +1055,7 @@ SnapSerializer.prototype.loadBlock = function (model, isReporter) {
this.loadInput(child, inputs[i], block);
}
}, this);
block.cachedInputs = null;
return block;
};
@ -1403,6 +1436,7 @@ StageMorph.prototype.toXML = function (serializer) {
'costume="@" tempo="@" threadsafe="@" ' +
'lines="@" ' +
'codify="@" ' +
'inheritance="@" ' +
'scheduled="@" ~>' +
'<pentrails>$</pentrails>' +
'<costumes>%</costumes>' +
@ -1430,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'),
@ -1462,6 +1497,7 @@ SpriteMorph.prototype.toXML = function (serializer) {
' draggable="@"' +
'%' +
' costume="@" color="@,@,@" pen="@" ~>' +
'%' + // inheritance info
'%' + // nesting info
'<costumes>%</costumes>' +
'<sounds>%</sounds>' +
@ -1484,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="' +

Wyświetl plik

@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/
// Global stuff ////////////////////////////////////////////////////////
modules.threads = '2015-January-12';
modules.threads = '2015-July-27';
var ThreadManager;
var Process;
@ -339,7 +339,7 @@ ThreadManager.prototype.findProcess = function (block) {
*/
Process.prototype = {};
Process.prototype.contructor = Process;
Process.prototype.constructor = Process;
Process.prototype.timeout = 500; // msecs after which to force yield
Process.prototype.isCatchingErrors = true;
@ -1153,13 +1153,17 @@ Process.prototype.doDeclareVariables = function (varNames) {
Process.prototype.doSetVar = function (varName, value) {
var varFrame = this.context.variables,
name = varName;
if (name instanceof Context) {
if (name.expression.selector === 'reportGetVar') {
name = name.expression.blockSpec;
name.variables.setVar(
name.expression.blockSpec,
value,
this.blockReceiver()
);
return;
}
}
varFrame.setVar(name, value);
varFrame.setVar(name, value, this.blockReceiver());
};
Process.prototype.doChangeVar = function (varName, value) {
@ -1168,10 +1172,15 @@ Process.prototype.doChangeVar = function (varName, value) {
if (name instanceof Context) {
if (name.expression.selector === 'reportGetVar') {
name = name.expression.blockSpec;
name.variables.changeVar(
name.expression.blockSpec,
value,
this.blockReceiver()
);
return;
}
}
varFrame.changeVar(name, value);
varFrame.changeVar(name, value, this.blockReceiver());
};
Process.prototype.reportGetVar = function () {
@ -1199,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,
@ -1216,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) {
@ -1295,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) {
@ -1323,6 +1350,8 @@ Process.prototype.doDeleteFromList = function (index, list) {
}
if (this.inputOption(index) === 'last') {
idx = list.length();
} else if (isNaN(+this.inputOption(index))) {
return null;
}
list.remove(idx);
};
@ -1807,6 +1836,7 @@ Process.prototype.doAsk = function (data) {
isStage = this.blockReceiver() instanceof StageMorph,
activePrompter;
stage.keysPressed = {};
if (!this.prompter) {
activePrompter = detect(
stage.children,
@ -1926,7 +1956,7 @@ Process.prototype.reportTypeOf = function (thing) {
if (thing === true || (thing === false)) {
return 'Boolean';
}
if (!isNaN(parseFloat(thing))) {
if (!isNaN(+thing)) {
return 'number';
}
if (isString(thing)) {
@ -2112,14 +2142,14 @@ Process.prototype.reportMonadic = function (fname, n) {
case 'ln':
result = Math.log(x);
break;
case 'log':
result = 0;
case 'log': // base 10
result = Math.log(x) / Math.LN10;
break;
case 'e^':
result = Math.exp(x);
break;
case '10^':
result = 0;
result = Math.pow(10, x);
break;
default:
nop();
@ -2175,6 +2205,9 @@ Process.prototype.reportJoinWords = function (aList) {
// Process string ops
Process.prototype.reportLetter = function (idx, string) {
if (string instanceof List) { // catch a common user error
return '';
}
var i = +(idx || 0),
str = (string || '').toString();
return str[i - 1] || '';
@ -2627,31 +2660,30 @@ Process.prototype.reportTimer = function () {
};
// Process Dates and times in Snap
// Map block options to built-in functions
var dateMap = {
'year' : 'getFullYear',
'month' : 'getMonth',
'date': 'getDate',
'day of week' : 'getDay',
'hour' : 'getHours',
'minute' : 'getMinutes',
'second' : 'getSeconds',
'time in milliseconds' : 'getTime'
};
Process.prototype.reportDate = function (datefn) {
var inputFn = this.inputOption(datefn),
currDate = new Date(),
func = dateMap[inputFn],
result = currDate[func]();
var currDate, func, result,
inputFn = this.inputOption(datefn),
// Map block options to built-in functions
dateMap = {
'year' : 'getFullYear',
'month' : 'getMonth',
'date': 'getDate',
'day of week' : 'getDay',
'hour' : 'getHours',
'minute' : 'getMinutes',
'second' : 'getSeconds',
'time in milliseconds' : 'getTime'
};
if (!dateMap[inputFn]) { return ''; }
currDate = new Date();
func = dateMap[inputFn];
result = currDate[func]();
// Show months as 1-12 and days as 1-7
if (inputFn === 'month' || inputFn === 'day of week') {
result += 1;
}
return result;
};
@ -3103,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

Wyświetl plik

@ -7,7 +7,7 @@
written by Jens Mönig
jens@moenig.org
Copyright (C) 2014 by Jens Mönig
Copyright (C) 2015 by Jens Mönig
This file is part of Snap!.
@ -74,7 +74,7 @@ HTMLCanvasElement, fontHeight, SymbolMorph, localize, SpeechBubbleMorph,
ArrowMorph, MenuMorph, isString, isNil, SliderMorph, MorphicPreferences,
ScrollFrameMorph*/
modules.widgets = '2014-February-13';
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);
}
};

129
xml.js 100644 → 100755
Wyświetl plik

@ -7,7 +7,7 @@
written by Jens Mönig
jens@moenig.org
Copyright (C) 2014 by Jens Mönig
Copyright (C) 2015 by Jens Mönig
This file is part of Snap!.
@ -57,15 +57,17 @@
Nathan Dinsmore contributed to the design and implemented a first
working version of a complete XMLSerializer. I have taken much of the
overall design and many of the functions and methods in this file from
Nathan's fine original prototype.
Nathan's fine original prototype. Recently Nathan has once again
worked his magic on the parser and optimized it by an order of
magnitude.
*/
/*global modules, isString, detect, Node, isNil*/
/*global modules, detect, Node, isNil*/
// Global stuff ////////////////////////////////////////////////////////
modules.xml = '2014-January-09';
modules.xml = '2015-June-25';
// Declarations
@ -85,7 +87,8 @@ function ReadStream(arrayOrString) {
// ReadStream constants:
ReadStream.prototype.space = /[\s]/;
ReadStream.prototype.nonSpace = /\S|$/g;
ReadStream.prototype.nonWord = /[\s\>\/\=]|$/g;
// ReadStream accessing:
@ -115,46 +118,26 @@ ReadStream.prototype.atEnd = function () {
// ReadStream accessing String contents:
ReadStream.prototype.upTo = function (regex) {
var i, start;
if (!isString(this.contents)) {return ''; }
i = this.contents.substr(this.index).search(regex);
if (i === -1) {
return '';
}
start = this.index;
this.index += i;
return this.contents.substring(start, this.index);
ReadStream.prototype.upTo = function (str) {
var i = this.contents.indexOf(str, this.index);
return i === -1 ? '' : this.contents.slice(this.index, this.index = i);
};
ReadStream.prototype.peekUpTo = function (regex) {
if (!isString(this.contents)) {return ''; }
var i = this.contents.substr(this.index).search(regex);
if (i === -1) {
return '';
}
return this.contents.substring(this.index, this.index + i);
ReadStream.prototype.peekUpTo = function (str) {
var i = this.contents.indexOf(str, this.index);
return i === -1 ? '' : this.contents.slice(this.index, i);
};
ReadStream.prototype.skipSpace = function () {
if (!isString(this.contents)) {return ''; }
var ch = this.peek();
while (this.space.test(ch) && ch !== '') {
this.skip();
ch = this.peek();
}
this.nonSpace.lastIndex = this.index;
var result = this.nonSpace.exec(this.contents);
if (result) this.index = result.index;
};
ReadStream.prototype.word = function () {
var i, start;
if (!isString(this.contents)) {return ''; }
i = this.contents.substr(this.index).search(/[\s\>\/\=]|$/);
if (i === -1) {
return '';
}
start = this.index;
this.index += i;
return this.contents.substring(start, this.index);
this.nonWord.lastIndex = this.index;
var result = this.nonWord.exec(this.contents);
return result ? this.contents.slice(this.index, this.index = result.index) : '';
};
// XML_Element ///////////////////////////////////////////////////////////
@ -166,7 +149,7 @@ ReadStream.prototype.word = function () {
// XML_Element inherits from Node:
XML_Element.prototype = new Node();
XML_Element.prototype = Object.create(Node.prototype);
XML_Element.prototype.constructor = XML_Element;
XML_Element.uber = Node.prototype;
@ -190,9 +173,7 @@ XML_Element.prototype.init = function (tag, contents, parent) {
XML_Element.uber.init.call(this);
// override inherited properties
if (parent instanceof XML_Element) {
parent.addChild(this);
}
if (parent) parent.addChild(this);
};
// XML_Element DOM navigation: (aside from what's inherited from Node)
@ -318,51 +299,18 @@ XML_Element.prototype.escape = function (string, ignoreQuotes) {
};
XML_Element.prototype.unescape = function (string) {
var stream = new ReadStream(string),
result = '',
ch,
esc;
function nextPut(str) {
result += str;
stream.upTo(';');
stream.skip();
}
while (!stream.atEnd()) {
ch = stream.next();
if (ch === '&') {
esc = stream.peekUpTo(';');
switch (esc) {
case 'apos':
nextPut('\'');
break;
case 'quot':
nextPut('\"');
break;
case 'lt':
nextPut('<');
break;
case 'gt':
nextPut('>');
break;
case 'amp':
nextPut('&');
break;
case '#xD':
nextPut('\n');
break;
case '#126':
nextPut('~');
break;
default:
result += ch;
}
} else {
result += ch;
return string.replace(/&(amp|apos|quot|lt|gt|#xD|#126);/g, function(_, name) {
switch (name) {
case 'amp': return '&';
case 'apos': return '\'';
case 'quot': return '"';
case 'lt': return '<';
case 'gt': return '>';
case '#xD': return '\n';
case '#126': return '~';
default: console.warn('unreachable');
}
}
return result;
});
};
// XML_Element parsing:
@ -375,10 +323,7 @@ XML_Element.prototype.parseString = function (string) {
};
XML_Element.prototype.parseStream = function (stream) {
var key,
value,
ch,
child;
var key, value, ch, child;
// tag:
this.tag = stream.word();
@ -395,9 +340,7 @@ XML_Element.prototype.parseStream = function (stream) {
stream.skipSpace();
ch = stream.next();
if (ch !== '"' && ch !== "'") {
throw new Error(
'Expected single- or double-quoted attribute value'
);
throw new Error('Expected single- or double-quoted attribute value');
}
value = stream.upTo(ch);
stream.skip(1);
@ -407,7 +350,7 @@ XML_Element.prototype.parseStream = function (stream) {
}
// empty tag:
if (stream.peek() === '/') {
if (ch === '/') {
stream.skip();
if (stream.next() !== '>') {
throw new Error('Expected ">" after "/" in empty tag');