summaryrefslogtreecommitdiff
path: root/gui.js
diff options
context:
space:
mode:
Diffstat (limited to 'gui.js')
-rw-r--r--gui.js246
1 files changed, 193 insertions, 53 deletions
diff --git a/gui.js b/gui.js
index d80e61a..f711847 100644
--- a/gui.js
+++ b/gui.js
@@ -9,7 +9,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!.
@@ -69,7 +69,7 @@ SpeechBubbleMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.gui = '2014-November-20';
+modules.gui = '2015-June-25';
// Declarations
@@ -82,6 +82,11 @@ var WardrobeMorph;
var SoundIconMorph;
var JukeboxMorph;
+// Get the full url without "snap.html"
+var baseUrl = document.URL.split('/');
+baseUrl.pop(baseUrl.length - 1);
+baseUrl = baseUrl.join('/') + '/';
+
// IDE_Morph ///////////////////////////////////////////////////////////
// I am SNAP's top-level frame, the Editor window
@@ -119,7 +124,7 @@ IDE_Morph.prototype.setDefaultDesign = function () {
];
IDE_Morph.prototype.rotationStyleColors = IDE_Morph.prototype.tabColors;
IDE_Morph.prototype.appModeColor = new Color();
- IDE_Morph.prototype.scriptsPaneTexture = 'scriptsPaneTexture.gif';
+ IDE_Morph.prototype.scriptsPaneTexture = this.scriptsTexture();
IDE_Morph.prototype.padding = 5;
SpriteIconMorph.prototype.labelColor
@@ -172,6 +177,22 @@ IDE_Morph.prototype.setFlatDesign = function () {
= IDE_Morph.prototype.buttonLabelColor;
};
+IDE_Morph.prototype.scriptsTexture = function () {
+ var pic = newCanvas(new Point(100, 100)), // bigger scales faster
+ ctx = pic.getContext('2d'),
+ i;
+ for (i = 0; i < 100; i += 4) {
+ ctx.fillStyle = this.frameColor.toString();
+ ctx.fillRect(i, 0, 1, 100);
+ ctx.fillStyle = this.groupColor.lighter(6).toString();
+ ctx.fillRect(i + 1, 0, 1, 100);
+ ctx.fillRect(i + 3, 0, 1, 100);
+ ctx.fillStyle = this.groupColor.toString();
+ ctx.fillRect(i + 2, 0, 1, 100);
+ }
+ return pic;
+};
+
IDE_Morph.prototype.setDefaultDesign();
// IDE_Morph instance creation:
@@ -186,11 +207,12 @@ 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:
this.cloudMsg = null;
- this.source = SnapCloud.username ? 'cloud' : 'local';
+ this.source = 'local';
this.serializer = new SnapSerializer();
this.globalVariables = new VariableFrame();
@@ -233,10 +255,6 @@ IDE_Morph.prototype.init = function (isAutoFill) {
IDE_Morph.prototype.openIn = function (world) {
var hash, usr, myself = this, urlLanguage = null;
- this.buildPanes();
- world.add(this);
- world.userMenu = this.userMenu;
-
// get persistent user data, if any
if (localStorage) {
usr = localStorage['-snap-user'];
@@ -245,10 +263,17 @@ IDE_Morph.prototype.openIn = function (world) {
if (usr) {
SnapCloud.username = usr.username || null;
SnapCloud.password = usr.password || null;
+ if (SnapCloud.username) {
+ this.source = 'cloud';
+ }
}
}
}
+ this.buildPanes();
+ world.add(this);
+ world.userMenu = this.userMenu;
+
// override SnapCloud's user message with Morphic
SnapCloud.message = function (string) {
var m = new MenuMorph(null, string),
@@ -284,7 +309,8 @@ IDE_Morph.prototype.openIn = function (world) {
}
throw new Error('unable to retrieve ' + url);
} catch (err) {
- return;
+ myself.showMessage('unable to retrieve project');
+ return '';
}
}
@@ -297,7 +323,6 @@ IDE_Morph.prototype.openIn = function (world) {
this.inform('Snap!', motd);
}
*/
-
function interpretUrlAnchors() {
var dict;
if (location.hash.substr(0, 6) === '#open:') {
@@ -350,6 +375,7 @@ IDE_Morph.prototype.openIn = function (world) {
function () {
msg = myself.showMessage('Opening project...');
},
+ function () {nop(); }, // yield (bug in Chrome)
function () {
if (projectData.indexOf('<snapdata') === 0) {
myself.rawOpenCloudDataString(projectData);
@@ -364,8 +390,61 @@ 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(); };
+ }
+ }
+ ]);
+ },
+ this.cloudError()
+ );
+ } else if (location.hash.substr(0, 7) === '#cloud:') {
+ this.shield = new Morph();
+ this.shield.alpha = 0;
+ this.shield.setExtent(this.parent.extent());
+ this.parent.add(this.shield);
+ myself.showMessage('Fetching project\nfrom the cloud...');
+
+ // make sure to lowercase the username
+ dict = SnapCloud.parseDict(location.hash.substr(7));
+ dict.Username = dict.Username.toLowerCase();
+
+ SnapCloud.getPublicProject(
+ SnapCloud.encodeDict(dict),
+ function (projectData) {
+ var msg;
+ myself.nextSteps([
+ function () {
+ msg = myself.showMessage('Opening project...');
+ },
+ function () {nop(); }, // yield (bug in Chrome)
+ function () {
+ if (projectData.indexOf('<snapdata') === 0) {
+ myself.rawOpenCloudDataString(projectData);
+ } else if (
+ projectData.indexOf('<project') === 0
+ ) {
+ myself.rawOpenProjectString(projectData);
+ }
+ myself.hasChangedMedia = true;
+ },
+ function () {
+ myself.shield.destroy();
+ myself.shield = null;
+ msg.destroy();
+ myself.toggleAppMode(false);
}
]);
},
@@ -1149,7 +1228,7 @@ IDE_Morph.prototype.createSpriteEditor = function () {
if (this.currentTab === 'scripts') {
scripts.isDraggable = false;
scripts.color = this.groupColor;
- scripts.texture = this.scriptsPaneTexture;
+ scripts.cachedTexture = this.scriptsPaneTexture;
this.spriteEditor = new ScrollFrameMorph(
scripts,
@@ -1720,6 +1799,7 @@ IDE_Morph.prototype.applySavedSettings = function () {
language = this.getSetting('language'),
click = this.getSetting('click'),
longform = this.getSetting('longform'),
+ longurls = this.getSetting('longurls'),
plainprototype = this.getSetting('plainprototype');
// design
@@ -1753,6 +1833,13 @@ IDE_Morph.prototype.applySavedSettings = function () {
InputSlotDialogMorph.prototype.isLaunchingExpanded = true;
}
+ // project data in URLs
+ if (longurls) {
+ this.projectsInURLs = true;
+ } else {
+ this.projectsInURLs = false;
+ }
+
// plain prototype labels
if (plainprototype) {
BlockLabelPlaceHolderMorph.prototype.plainLabel = true;
@@ -2043,6 +2130,7 @@ IDE_Morph.prototype.cloudMenu = function () {
'Opening project...'
);
},
+ function () {nop(); }, // yield (Chrome)
function () {
myself.rawOpenCloudDataString(
projectData
@@ -2198,6 +2286,17 @@ IDE_Morph.prototype.settingsMenu = function () {
'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 () {
MorphicPreferences.rasterizeSVGs =
@@ -2222,6 +2321,21 @@ IDE_Morph.prototype.settingsMenu = function () {
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 () {
SpriteMorph.prototype.enableNesting =
@@ -2293,7 +2407,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)
);
}
@@ -2382,13 +2497,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);
}
@@ -2505,8 +2617,8 @@ 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'
- + 'Copyright \u24B8 2014 Jens M\u00F6nig and '
+ aboutTxt = 'Snap! 4.0.1\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'
@@ -2539,7 +2651,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'
@@ -2768,7 +2880,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);
@@ -2776,7 +2888,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);
}
}
@@ -2817,7 +2929,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();
@@ -2830,7 +2942,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();
@@ -2855,7 +2967,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="'
@@ -2922,6 +3036,7 @@ IDE_Morph.prototype.openProjectString = function (str) {
function () {
msg = myself.showMessage('Opening project...');
},
+ function () {nop(); }, // yield (bug in Chrome)
function () {
myself.rawOpenProjectString(str);
},
@@ -2940,12 +3055,18 @@ IDE_Morph.prototype.rawOpenProjectString = function (str) {
StageMorph.prototype.enableCodeMapping = false;
if (Process.prototype.isCatchingErrors) {
try {
- this.serializer.openProject(this.serializer.load(str), this);
+ this.serializer.openProject(
+ this.serializer.load(str, this),
+ this
+ );
} catch (err) {
this.showMessage('Load failed: ' + err);
}
} else {
- this.serializer.openProject(this.serializer.load(str), this);
+ this.serializer.openProject(
+ this.serializer.load(str, this),
+ this
+ );
}
this.stopFastTracking();
};
@@ -2957,6 +3078,7 @@ IDE_Morph.prototype.openCloudDataString = function (str) {
function () {
msg = myself.showMessage('Opening project...');
},
+ function () {nop(); }, // yield (bug in Chrome)
function () {
myself.rawOpenCloudDataString(str);
},
@@ -2977,7 +3099,10 @@ IDE_Morph.prototype.rawOpenCloudDataString = function (str) {
model = this.serializer.parse(str);
this.serializer.loadMediaModel(model.childNamed('media'));
this.serializer.openProject(
- this.serializer.loadProjectModel(model.childNamed('project')),
+ this.serializer.loadProjectModel(
+ model.childNamed('project'),
+ this
+ ),
this
);
} catch (err) {
@@ -2987,7 +3112,10 @@ IDE_Morph.prototype.rawOpenCloudDataString = function (str) {
model = this.serializer.parse(str);
this.serializer.loadMediaModel(model.childNamed('media'));
this.serializer.openProject(
- this.serializer.loadProjectModel(model.childNamed('project')),
+ this.serializer.loadProjectModel(
+ model.childNamed('project'),
+ this
+ ),
this
);
}
@@ -3001,6 +3129,7 @@ IDE_Morph.prototype.openBlocksString = function (str, name, silently) {
function () {
msg = myself.showMessage('Opening blocks...');
},
+ function () {nop(); }, // yield (bug in Chrome)
function () {
myself.rawOpenBlocksString(str, name, silently);
},
@@ -3047,6 +3176,7 @@ IDE_Morph.prototype.openSpritesString = function (str) {
function () {
msg = myself.showMessage('Opening sprite...');
},
+ function () {nop(); }, // yield (bug in Chrome)
function () {
myself.rawOpenSpritesString(str);
},
@@ -3088,7 +3218,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;
}
};
@@ -3323,6 +3459,15 @@ IDE_Morph.prototype.toggleAppMode = function (appMode) {
}).forEach(function (s) {
s.adjustScrollBars();
});
+ // prevent rotation and draggability controls from
+ // showing for the stage
+ if (this.currentSprite === this.stage) {
+ this.spriteBar.children.forEach(function (child) {
+ if (child instanceof PushButtonMorph) {
+ child.hide();
+ }
+ });
+ }
}
this.setExtent(this.world().extent()); // resume trackChanges
};
@@ -3498,7 +3643,8 @@ IDE_Morph.prototype.userSetBlocksScale = function () {
sample = new FrameMorph();
sample.acceptsDrops = false;
- sample.texture = this.scriptsPaneTexture;
+ sample.color = IDE_Morph.prototype.groupColor;
+ sample.cachedTexture = this.scriptsPaneTexture;
sample.setExtent(new Point(250, 180));
scrpt.setPosition(sample.position().add(10));
sample.add(scrpt);
@@ -3971,6 +4117,9 @@ IDE_Morph.prototype.cloudResponse = function () {
IDE_Morph.prototype.cloudError = function () {
var myself = this;
+ // try finding an eplanation what's going on
+ // has some issues, commented out for now
+ /*
function getURL(url) {
try {
var request = new XMLHttpRequest();
@@ -3984,13 +4133,15 @@ IDE_Morph.prototype.cloudError = function () {
return null;
}
}
+ */
return function (responseText, url) {
// first, try to find out an explanation for the error
// and notify the user about it,
// if none is found, show an error dialog box
var response = responseText,
- explanation = getURL('http://snap.berkeley.edu/cloudmsg.txt');
+ // explanation = getURL('http://snap.berkeley.edu/cloudmsg.txt'),
+ explanation = null;
if (myself.shield) {
myself.shield.destroy();
myself.shield = null;
@@ -4041,14 +4192,7 @@ IDE_Morph.prototype.setCloudURL = function () {
null,
{
'Snap!Cloud' :
- 'https://snapcloud.miosoft.com/miocon/app/' +
- 'login?_app=SnapCloud',
- 'local network lab' :
- '192.168.2.107:8087/miocon/app/login?_app=SnapCloud',
- 'local network office' :
- '192.168.186.146:8087/miocon/app/login?_app=SnapCloud',
- 'localhost dev' :
- 'localhost/miocon/app/login?_app=SnapCloud'
+ 'https://snap.apps.miosoft.com/SnapCloud'
}
);
};
@@ -4075,8 +4219,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;
@@ -4517,8 +4660,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);
@@ -4572,8 +4714,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"')),
@@ -4592,8 +4735,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;
};
@@ -4692,10 +4835,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'