2015-02-16 19:35:02 +00:00
|
|
|
// Force flat design
|
|
|
|
IDE_Morph.prototype.setDefaultDesign = IDE_Morph.prototype.setFlatDesign;
|
|
|
|
|
2015-05-10 00:13:32 +00:00
|
|
|
|
|
|
|
IDE_Morph.prototype.originalInit = IDE_Morph.prototype.init;
|
|
|
|
|
|
|
|
IDE_Morph.prototype.init = function(isAutoFill) {
|
|
|
|
this.originalInit();
|
|
|
|
// Borders are actually just paddings, so we set the bg white to get them to be white
|
|
|
|
//this.backgroundColor = new Color(255,255,255);
|
|
|
|
//this.setColor(this.backgroundColor);
|
2015-05-10 08:38:27 +00:00
|
|
|
this.padding = 1;
|
2015-05-10 00:13:32 +00:00
|
|
|
//this.frameColor = new Color(220,220,220);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-16 19:35:02 +00:00
|
|
|
// change logo
|
|
|
|
IDE_Morph.prototype.originalCreateLogo = IDE_Morph.prototype.createLogo;
|
|
|
|
IDE_Morph.prototype.createLogo = function () {
|
|
|
|
this.originalCreateLogo();
|
|
|
|
if (MorphicPreferences.isFlat) {
|
|
|
|
this.logo.texture = 'stitchcode/stitchcode_logo_small.png';
|
|
|
|
} else {
|
|
|
|
this.logo.texture = 'stitchcode/stitchcode_logo_small_black.png';
|
|
|
|
}
|
2015-05-10 00:13:32 +00:00
|
|
|
|
|
|
|
this.logo.color = new Color(230, 230, 230);
|
2015-02-16 19:35:02 +00:00
|
|
|
this.logo.drawNew();
|
|
|
|
}
|
|
|
|
|
2015-05-09 19:16:56 +00:00
|
|
|
IDE_Morph.prototype.buildPanes = function () {
|
|
|
|
this.createLogo();
|
|
|
|
this.createControlBar();
|
|
|
|
this.createCategories();
|
|
|
|
this.createPalette();
|
|
|
|
this.createStage();
|
|
|
|
this.createSpriteEditor();
|
2015-05-10 00:13:32 +00:00
|
|
|
this.createSpriteBar();
|
2015-05-09 19:16:56 +00:00
|
|
|
this.createStatusDisplay();
|
|
|
|
};
|
|
|
|
|
2015-02-16 19:35:02 +00:00
|
|
|
// add buttons
|
|
|
|
|
|
|
|
IDE_Morph.prototype.createControlBar = function () {
|
|
|
|
// assumes the logo has already been created
|
2015-05-10 00:13:32 +00:00
|
|
|
var padding = 4,
|
2015-02-16 19:35:02 +00:00
|
|
|
button,
|
|
|
|
stopButton,
|
|
|
|
pauseButton,
|
|
|
|
startButton,
|
|
|
|
projectButton,
|
|
|
|
settingsButton,
|
|
|
|
stageSizeButton,
|
2015-05-09 19:16:56 +00:00
|
|
|
//largeStageSizeButton,
|
2015-02-16 19:35:02 +00:00
|
|
|
appModeButton,
|
|
|
|
cloudButton,
|
|
|
|
upstitchButton,
|
|
|
|
x,
|
|
|
|
colors = [
|
|
|
|
this.groupColor,
|
|
|
|
this.frameColor.darker(50),
|
|
|
|
this.frameColor.darker(50)
|
|
|
|
],
|
|
|
|
myself = this;
|
|
|
|
|
|
|
|
if (this.controlBar) {
|
|
|
|
this.controlBar.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.controlBar = new Morph();
|
|
|
|
this.controlBar.color = this.frameColor;
|
2015-05-10 00:13:32 +00:00
|
|
|
this.controlBar.color = new Color(250, 250, 250);
|
2015-02-16 19:35:02 +00:00
|
|
|
this.controlBar.setHeight(this.logo.height()); // height is fixed
|
|
|
|
this.controlBar.mouseClickLeft = function () {
|
|
|
|
this.world().fillPage();
|
|
|
|
};
|
|
|
|
this.add(this.controlBar);
|
2015-05-09 19:16:56 +00:00
|
|
|
/*
|
|
|
|
button = new ToggleButtonMorph(
|
|
|
|
null, //colors,
|
|
|
|
myself, // the IDE is the target
|
|
|
|
'setLargeStageSize',
|
|
|
|
new SymbolMorph('largeStage', 14)
|
|
|
|
);
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = this.buttonLabelColor;
|
|
|
|
button.query = function(){};
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
button.fixLayout();
|
|
|
|
button.refresh();
|
|
|
|
largeStageSizeButton = button;
|
|
|
|
this.controlBar.add(largeStageSizeButton);
|
|
|
|
this.controlBar.largeStageSizeButton = button; // for refreshing
|
|
|
|
*/
|
2015-02-16 19:35:02 +00:00
|
|
|
|
2015-05-09 19:16:56 +00:00
|
|
|
|
2015-02-16 19:35:02 +00:00
|
|
|
//smallStageButton
|
|
|
|
button = new ToggleButtonMorph(
|
|
|
|
null, //colors,
|
|
|
|
myself, // the IDE is the target
|
|
|
|
'toggleStageSize',
|
|
|
|
[
|
|
|
|
new SymbolMorph('smallStage', 14),
|
|
|
|
new SymbolMorph('normalStage', 14)
|
|
|
|
],
|
|
|
|
function () { // query
|
|
|
|
return myself.isSmallStage;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = this.buttonLabelColor;
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'stage size\nsmall & normal';
|
|
|
|
button.fixLayout();
|
|
|
|
button.refresh();
|
|
|
|
stageSizeButton = button;
|
|
|
|
this.controlBar.add(stageSizeButton);
|
|
|
|
this.controlBar.stageSizeButton = button; // for refreshing
|
|
|
|
|
|
|
|
//appModeButton
|
|
|
|
button = new ToggleButtonMorph(
|
|
|
|
null, //colors,
|
|
|
|
myself, // the IDE is the target
|
|
|
|
'toggleAppMode',
|
|
|
|
[
|
|
|
|
new SymbolMorph('fullScreen', 14),
|
|
|
|
new SymbolMorph('normalScreen', 14)
|
|
|
|
],
|
|
|
|
function () { // query
|
|
|
|
return myself.isAppMode;
|
|
|
|
}
|
2015-05-09 19:16:56 +00:00
|
|
|
);
|
2015-02-16 19:35:02 +00:00
|
|
|
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = this.buttonLabelColor;
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'app & edit\nmodes';
|
|
|
|
button.fixLayout();
|
|
|
|
button.refresh();
|
|
|
|
appModeButton = button;
|
|
|
|
this.controlBar.add(appModeButton);
|
|
|
|
this.controlBar.appModeButton = appModeButton; // for refreshing
|
|
|
|
|
|
|
|
// upload StitchButton
|
|
|
|
button = new PushButtonMorph(
|
|
|
|
this,
|
2015-07-13 17:12:38 +00:00
|
|
|
'uploadMe',
|
2015-02-16 19:35:02 +00:00
|
|
|
new SymbolMorph('arrowUp', 14)
|
|
|
|
);
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = this.buttonLabelColor;
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'stop\nevery-\nthing';
|
|
|
|
button.fixLayout();
|
|
|
|
upstitchButton = button;
|
|
|
|
this.controlBar.add(upstitchButton);
|
|
|
|
|
|
|
|
|
|
|
|
// stopButton
|
|
|
|
button = new PushButtonMorph(
|
|
|
|
this,
|
|
|
|
'stopAllScripts',
|
|
|
|
new SymbolMorph('octagon', 14)
|
|
|
|
);
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = new Color(200, 0, 0);
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'stop\nevery-\nthing';
|
|
|
|
button.fixLayout();
|
|
|
|
stopButton = button;
|
|
|
|
this.controlBar.add(stopButton);
|
|
|
|
|
|
|
|
//pauseButton
|
|
|
|
button = new ToggleButtonMorph(
|
|
|
|
null, //colors,
|
|
|
|
myself, // the IDE is the target
|
|
|
|
'togglePauseResume',
|
|
|
|
[
|
|
|
|
new SymbolMorph('pause', 12),
|
|
|
|
new SymbolMorph('pointRight', 14)
|
|
|
|
],
|
|
|
|
function () { // query
|
|
|
|
return myself.isPaused();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = new Color(255, 220, 0);
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'pause/resume\nall scripts';
|
|
|
|
button.fixLayout();
|
|
|
|
button.refresh();
|
|
|
|
pauseButton = button;
|
|
|
|
this.controlBar.add(pauseButton);
|
|
|
|
this.controlBar.pauseButton = pauseButton; // for refreshing
|
|
|
|
|
|
|
|
// startButton
|
|
|
|
button = new PushButtonMorph(
|
|
|
|
this,
|
|
|
|
'pressStart',
|
|
|
|
new SymbolMorph('flag', 14)
|
|
|
|
);
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = new Color(0, 200, 0);
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'start green\nflag scripts';
|
|
|
|
button.fixLayout();
|
|
|
|
startButton = button;
|
|
|
|
this.controlBar.add(startButton);
|
|
|
|
this.controlBar.startButton = startButton;
|
|
|
|
|
|
|
|
// projectButton
|
|
|
|
button = new PushButtonMorph(
|
|
|
|
this,
|
|
|
|
'projectMenu',
|
|
|
|
new SymbolMorph('file', 14)
|
|
|
|
//'\u270E'
|
|
|
|
);
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = this.buttonLabelColor;
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'open, save, & annotate project';
|
|
|
|
button.fixLayout();
|
|
|
|
projectButton = button;
|
|
|
|
this.controlBar.add(projectButton);
|
|
|
|
this.controlBar.projectButton = projectButton; // for menu positioning
|
|
|
|
|
|
|
|
// settingsButton
|
|
|
|
button = new PushButtonMorph(
|
|
|
|
this,
|
|
|
|
'settingsMenu',
|
|
|
|
new SymbolMorph('gears', 14)
|
|
|
|
//'\u2699'
|
|
|
|
);
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = this.buttonLabelColor;
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'edit settings';
|
|
|
|
button.fixLayout();
|
|
|
|
settingsButton = button;
|
|
|
|
this.controlBar.add(settingsButton);
|
|
|
|
this.controlBar.settingsButton = settingsButton; // for menu positioning
|
|
|
|
|
|
|
|
// cloudButton
|
|
|
|
button = new PushButtonMorph(
|
|
|
|
this,
|
|
|
|
'cloudMenu',
|
|
|
|
new SymbolMorph('cloud', 11)
|
|
|
|
);
|
|
|
|
button.corner = 12;
|
|
|
|
button.color = colors[0];
|
|
|
|
button.highlightColor = colors[1];
|
|
|
|
button.pressColor = colors[2];
|
|
|
|
button.labelMinExtent = new Point(36, 18);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = this.buttonLabelColor;
|
|
|
|
button.contrast = this.buttonContrast;
|
|
|
|
button.drawNew();
|
|
|
|
// button.hint = 'cloud operations';
|
|
|
|
button.fixLayout();
|
|
|
|
cloudButton = button;
|
|
|
|
this.controlBar.add(cloudButton);
|
|
|
|
this.controlBar.cloudButton = cloudButton; // for menu positioning
|
|
|
|
|
|
|
|
this.controlBar.fixLayout = function () {
|
|
|
|
x = this.right() - padding;
|
|
|
|
[stopButton, pauseButton, startButton].forEach(
|
|
|
|
function (button) {
|
|
|
|
button.setCenter(myself.controlBar.center());
|
|
|
|
button.setRight(x);
|
|
|
|
x -= button.width();
|
|
|
|
x -= padding;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
x = Math.min(
|
|
|
|
startButton.left() - (3 * padding + 2 * stageSizeButton.width()),
|
|
|
|
myself.right() - StageMorph.prototype.dimensions.x *
|
|
|
|
(myself.isSmallStage ? myself.stageRatio : 1)
|
|
|
|
);
|
2015-05-09 19:16:56 +00:00
|
|
|
[upstitchButton, stageSizeButton, appModeButton].forEach(
|
2015-02-16 19:35:02 +00:00
|
|
|
function (button) {
|
|
|
|
x += padding;
|
|
|
|
button.setCenter(myself.controlBar.center());
|
|
|
|
button.setLeft(x);
|
|
|
|
x += button.width();
|
|
|
|
}
|
|
|
|
);
|
2015-05-09 19:16:56 +00:00
|
|
|
|
2015-02-16 19:35:02 +00:00
|
|
|
settingsButton.setCenter(myself.controlBar.center());
|
|
|
|
settingsButton.setLeft(this.left());
|
|
|
|
|
|
|
|
cloudButton.setCenter(myself.controlBar.center());
|
|
|
|
cloudButton.setRight(settingsButton.left() - padding);
|
|
|
|
|
|
|
|
projectButton.setCenter(myself.controlBar.center());
|
|
|
|
projectButton.setRight(cloudButton.left() - padding);
|
|
|
|
|
|
|
|
this.updateLabel();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.controlBar.updateLabel = function () {
|
|
|
|
var suffix = myself.world().isDevMode ?
|
|
|
|
' - ' + localize('development mode') : '';
|
|
|
|
|
|
|
|
if (this.label) {
|
|
|
|
this.label.destroy();
|
|
|
|
}
|
|
|
|
if (myself.isAppMode) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.label = new StringMorph(
|
|
|
|
(myself.projectName || localize('untitled')) + suffix,
|
|
|
|
14,
|
|
|
|
'sans-serif',
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
MorphicPreferences.isFlat ? null : new Point(2, 1),
|
|
|
|
myself.frameColor.darker(myself.buttonContrast)
|
|
|
|
);
|
|
|
|
this.label.color = myself.buttonLabelColor;
|
|
|
|
this.label.drawNew();
|
|
|
|
this.add(this.label);
|
|
|
|
this.label.setCenter(this.center());
|
|
|
|
this.label.setLeft(this.settingsButton.right() + padding);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-05-09 19:16:56 +00:00
|
|
|
IDE_Morph.prototype.setLargeStageSize = function () {
|
|
|
|
this.setStageSize(1.5);
|
|
|
|
}
|
|
|
|
IDE_Morph.prototype.setNormalStageSize = function () {
|
|
|
|
this.setStageSize(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
IDE_Morph.prototype.setSmallStageSize = function () {
|
|
|
|
this.setStageSize(0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
IDE_Morph.prototype.setStageSize = function (ratio) {
|
|
|
|
/* var myself = this,
|
|
|
|
world = this.world(),
|
|
|
|
shiftClicked = (world.currentKey === 16);*/
|
2015-02-16 19:35:02 +00:00
|
|
|
|
2015-05-09 19:16:56 +00:00
|
|
|
this.setStageExtent(new Point(480 * ratio, 360 * ratio))
|
|
|
|
|
|
|
|
/*
|
|
|
|
myself.step = function () {
|
|
|
|
myself.stageRatio = ratio;
|
|
|
|
myself.setExtent(world.extent());
|
|
|
|
myself.controlBar.stageSizeButton.refresh();
|
|
|
|
delete myself.step;
|
|
|
|
}
|
|
|
|
|
|
|
|
// not working yet
|
|
|
|
if (shiftClicked) {
|
|
|
|
ratio = SpriteIconMorph.prototype.thumbSize.x * 3 /
|
|
|
|
this.stage.dimensions.x;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
};
|
2015-02-16 19:35:02 +00:00
|
|
|
|
|
|
|
IDE_Morph.prototype.uploadStitches = function () {
|
|
|
|
tStitch.upload();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ProjectDialogMorph.prototype.getExamplesProjectList = function () {
|
|
|
|
var dir,
|
|
|
|
projects = [];
|
|
|
|
|
|
|
|
//dir = this.ide.getURL('http://snap.berkeley.edu/snapsource/Examples/');
|
2015-03-24 20:10:49 +00:00
|
|
|
dir = this.ide.getURL(tStitch.getBaseURL() + '/stitchcode/examples/');
|
2015-02-16 19:35:02 +00:00
|
|
|
dir.split('\n').forEach(
|
|
|
|
function (line) {
|
|
|
|
var startIdx = line.search(new RegExp('href=".*xml"')),
|
|
|
|
endIdx,
|
|
|
|
name,
|
|
|
|
dta;
|
|
|
|
if (startIdx > 0) {
|
|
|
|
endIdx = line.search(new RegExp('.xml'));
|
|
|
|
name = line.substring(startIdx + 6, endIdx);
|
|
|
|
dta = {
|
|
|
|
name: name,
|
|
|
|
thumb: null,
|
|
|
|
notes: null
|
|
|
|
};
|
|
|
|
projects.push(dta);
|
2015-07-09 21:59:59 +00:00
|
|
|
console.log(dta);
|
2015-02-16 19:35:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
projects.sort(function (x, y) {
|
|
|
|
return x.name < y.name ? -1 : 1;
|
|
|
|
});
|
|
|
|
return projects;
|
|
|
|
};
|
|
|
|
|
2015-03-24 20:10:49 +00:00
|
|
|
ProjectDialogMorph.prototype.setSource = function (source) {
|
|
|
|
var myself = this,
|
|
|
|
msg;
|
|
|
|
|
|
|
|
this.source = source; //this.task === 'save' ? 'local' : source;
|
|
|
|
this.srcBar.children.forEach(function (button) {
|
|
|
|
button.refresh();
|
|
|
|
});
|
|
|
|
switch (this.source) {
|
|
|
|
case 'cloud':
|
|
|
|
msg = myself.ide.showMessage('Updating\nproject list...');
|
|
|
|
this.projectList = [];
|
|
|
|
SnapCloud.getProjectList(
|
|
|
|
function (projectList) {
|
|
|
|
myself.installCloudProjectList(projectList);
|
|
|
|
msg.destroy();
|
|
|
|
},
|
|
|
|
function (err, lbl) {
|
|
|
|
msg.destroy();
|
|
|
|
myself.ide.cloudError().call(null, err, lbl);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
case 'examples':
|
|
|
|
this.projectList = this.getExamplesProjectList();
|
|
|
|
break;
|
|
|
|
case 'local':
|
|
|
|
this.projectList = this.getLocalProjectList();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.listField.destroy();
|
|
|
|
this.listField = new ListMorph(
|
|
|
|
this.projectList,
|
|
|
|
this.projectList.length > 0 ?
|
|
|
|
function (element) {
|
|
|
|
return element.name;
|
|
|
|
} : null,
|
|
|
|
null,
|
|
|
|
function () {myself.ok(); }
|
|
|
|
);
|
|
|
|
|
|
|
|
this.fixListFieldItemColors();
|
|
|
|
this.listField.fixLayout = nop;
|
|
|
|
this.listField.edge = InputFieldMorph.prototype.edge;
|
|
|
|
this.listField.fontSize = InputFieldMorph.prototype.fontSize;
|
|
|
|
this.listField.typeInPadding = InputFieldMorph.prototype.typeInPadding;
|
|
|
|
this.listField.contrast = InputFieldMorph.prototype.contrast;
|
|
|
|
this.listField.drawNew = InputFieldMorph.prototype.drawNew;
|
|
|
|
this.listField.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
|
|
|
|
|
|
|
|
if (this.source === 'local') {
|
|
|
|
this.listField.action = function (item) {
|
|
|
|
var src, xml;
|
|
|
|
|
|
|
|
if (item === undefined) {return; }
|
|
|
|
if (myself.nameField) {
|
|
|
|
myself.nameField.setContents(item.name || '');
|
|
|
|
}
|
|
|
|
if (myself.task === 'open') {
|
|
|
|
|
|
|
|
src = localStorage['-snap-project-' + item.name];
|
|
|
|
xml = myself.ide.serializer.parse(src);
|
|
|
|
|
|
|
|
myself.notesText.text = xml.childNamed('notes').contents
|
|
|
|
|| '';
|
|
|
|
myself.notesText.drawNew();
|
|
|
|
myself.notesField.contents.adjustBounds();
|
|
|
|
myself.preview.texture = xml.childNamed('thumbnail').contents
|
|
|
|
|| null;
|
|
|
|
myself.preview.cachedTexture = null;
|
|
|
|
myself.preview.drawNew();
|
|
|
|
}
|
|
|
|
myself.edit();
|
|
|
|
};
|
|
|
|
} else { // 'examples', 'cloud' is initialized elsewhere
|
|
|
|
this.listField.action = function (item) {
|
|
|
|
var src, xml;
|
|
|
|
if (item === undefined) {return; }
|
|
|
|
if (myself.nameField) {
|
|
|
|
myself.nameField.setContents(item.name || '');
|
|
|
|
}
|
|
|
|
src = myself.ide.getURL(
|
|
|
|
// 'http://snap.berkeley.edu/snapsource/Examples/' +
|
|
|
|
tStitch.getBaseURL() + 'stitchcode/examples/' +
|
|
|
|
item.name + '.xml'
|
|
|
|
);
|
|
|
|
|
|
|
|
xml = myself.ide.serializer.parse(src);
|
|
|
|
myself.notesText.text = xml.childNamed('notes').contents
|
|
|
|
|| '';
|
|
|
|
myself.notesText.drawNew();
|
|
|
|
myself.notesField.contents.adjustBounds();
|
|
|
|
myself.preview.texture = xml.childNamed('thumbnail').contents
|
|
|
|
|| null;
|
|
|
|
myself.preview.cachedTexture = null;
|
|
|
|
myself.preview.drawNew();
|
|
|
|
myself.edit();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
this.body.add(this.listField);
|
|
|
|
this.shareButton.hide();
|
|
|
|
this.unshareButton.hide();
|
|
|
|
if (this.source === 'local') {
|
|
|
|
this.deleteButton.show();
|
|
|
|
} else { // examples
|
|
|
|
this.deleteButton.hide();
|
|
|
|
}
|
|
|
|
this.buttons.fixLayout();
|
|
|
|
this.fixLayout();
|
|
|
|
if (this.task === 'open') {
|
|
|
|
this.clearDetails();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ProjectDialogMorph.prototype.openProject = function () {
|
|
|
|
var proj = this.listField.selected, src;
|
|
|
|
if (!proj) {return; }
|
|
|
|
this.ide.source = this.source;
|
|
|
|
if (this.source === 'cloud') {
|
|
|
|
this.openCloudProject(proj);
|
|
|
|
} else if (this.source === 'examples') {
|
|
|
|
src = this.ide.getURL(tStitch.getBaseURL() + 'stitchcode/examples/' + proj.name + '.xml');
|
|
|
|
this.ide.openProjectString(src);
|
|
|
|
this.destroy();
|
|
|
|
} else { // 'local'
|
|
|
|
this.ide.openProject(proj.name);
|
|
|
|
this.destroy();
|
|
|
|
}
|
|
|
|
};
|
2015-05-09 19:16:56 +00:00
|
|
|
|
|
|
|
IDE_Morph.prototype.toggleAppMode = function (appMode) {
|
|
|
|
var world = this.world(),
|
|
|
|
elements = [
|
|
|
|
this.logo,
|
|
|
|
this.controlBar.projectButton,
|
|
|
|
this.controlBar.cloudButton,
|
|
|
|
this.controlBar.settingsButton,
|
|
|
|
this.controlBar.stageSizeButton,
|
|
|
|
this.controlBar.stageSizeButton,
|
|
|
|
//this.controlBar.largeStageSizeButton,
|
|
|
|
this.spriteEditor,
|
|
|
|
this.palette,
|
|
|
|
this.categories ];
|
|
|
|
|
|
|
|
this.isAppMode = isNil(appMode) ? !this.isAppMode : appMode;
|
|
|
|
|
|
|
|
Morph.prototype.trackChanges = false;
|
|
|
|
if (this.isAppMode) {
|
|
|
|
this.setColor(this.appModeColor);
|
|
|
|
this.controlBar.setColor(this.color);
|
|
|
|
this.controlBar.appModeButton.refresh();
|
|
|
|
elements.forEach(function (e) {
|
|
|
|
e.hide();
|
|
|
|
});
|
|
|
|
world.children.forEach(function (morph) {
|
|
|
|
if (morph instanceof DialogBoxMorph) {
|
|
|
|
morph.hide();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setColor(this.backgroundColor);
|
|
|
|
this.controlBar.setColor(this.frameColor);
|
|
|
|
elements.forEach(function (e) {
|
|
|
|
e.show();
|
|
|
|
});
|
|
|
|
this.stage.setScale(1);
|
|
|
|
// show all hidden dialogs
|
|
|
|
world.children.forEach(function (morph) {
|
|
|
|
if (morph instanceof DialogBoxMorph) {
|
|
|
|
morph.show();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// prevent scrollbars from showing when morph appears
|
|
|
|
world.allChildren().filter(function (c) {
|
|
|
|
return c instanceof ScrollFrameMorph;
|
|
|
|
}).forEach(function (s) {
|
|
|
|
s.adjustScrollBars();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
this.setExtent(this.world().extent()); // resume trackChanges
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IDE_Morph.prototype.createStatusDisplay = function () {
|
|
|
|
var frame,
|
2015-05-10 08:38:27 +00:00
|
|
|
padding = 1,
|
2015-05-09 19:16:56 +00:00
|
|
|
myself = this,
|
|
|
|
elements = [],
|
|
|
|
beetle = this.currentSprite.beetle,
|
|
|
|
stage = this.stage;
|
|
|
|
|
|
|
|
if (this.statusDisplay) {
|
|
|
|
this.statusDisplay.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.statusDisplay = new Morph();
|
|
|
|
this.statusDisplay.color = this.groupColor;
|
|
|
|
this.add(this.statusDisplay);
|
|
|
|
|
|
|
|
frame = new ScrollFrameMorph(null, null, this.sliderColor);
|
|
|
|
frame.acceptsDrops = false;
|
|
|
|
frame.contents.acceptsDrops = false;
|
|
|
|
|
|
|
|
frame.alpha = 0;
|
|
|
|
|
|
|
|
this.statusDisplay.frame = frame;
|
|
|
|
this.statusDisplay.add(frame);
|
|
|
|
|
|
|
|
this.statusDisplay.fixLayout = function () {
|
|
|
|
this.setLeft(myself.stage.left());
|
|
|
|
this.setTop(myself.stage.bottom() + padding);
|
|
|
|
this.setWidth(myself.stage.width());
|
|
|
|
this.setHeight(myself.height() - myself.stage.height() - myself.controlBar.height() - padding);
|
|
|
|
this.frame.setExtent(this.extent());
|
|
|
|
this.arrangeContents()
|
|
|
|
this.refresh();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.statusDisplay.arrangeContents = function () {
|
|
|
|
var x = this.left() + padding,
|
|
|
|
y = this.top() + padding,
|
|
|
|
max = this.right() - padding,
|
|
|
|
start = x,
|
|
|
|
middle = (max - start) / 2 + start;
|
|
|
|
|
|
|
|
this.frame.contents.children.forEach(function (element) {
|
|
|
|
element.setPosition(new Point(x, y));
|
|
|
|
x += element.width();
|
|
|
|
|
|
|
|
if (element instanceof ToggleMorph) { x+= element.label.width() + 2 };
|
|
|
|
|
|
|
|
if (element.newLines) {
|
|
|
|
y += 14 * element.newLines;
|
|
|
|
x = start;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (element.newColumn) {
|
|
|
|
if (element.columns) {
|
|
|
|
x = ((max - start) / element.columns) * element.newColumn + start;
|
|
|
|
} else {
|
|
|
|
x = middle;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
this.frame.contents.adjustBounds();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.statusDisplay.addElement = function (element) {
|
|
|
|
|
|
|
|
if (typeof element == 'string') {
|
|
|
|
element = new StringMorph(localize(element), 12, null, true);
|
|
|
|
};
|
|
|
|
|
|
|
|
this.frame.contents.add(element);
|
|
|
|
this.fixLayout();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.statusDisplay.refresh = function () {
|
|
|
|
this.frame.contents.children.forEach(function (element) {
|
|
|
|
if (element.hasOwnProperty('update')) {
|
|
|
|
element.update();
|
|
|
|
element.changed();
|
|
|
|
element.drawNew();
|
|
|
|
element.changed();
|
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
this.statusDisplay.acceptsDrops = function () {
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.statusDisplay.watchers = function (leftPos) {
|
|
|
|
/* answer an array of all currently visible watchers.
|
|
|
|
If leftPos is specified, filter the list for all
|
|
|
|
shown or hidden watchers whose left side equals
|
|
|
|
the given border (for automatic positioning) */
|
|
|
|
|
|
|
|
return this.children.filter(function (morph) {
|
|
|
|
if (morph instanceof WatcherMorph) {
|
|
|
|
if (leftPos) {
|
|
|
|
return morph.left() === leftPos;
|
|
|
|
}
|
|
|
|
return morph.isVisible;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
this.statusDisplay.step = function() {
|
|
|
|
// update watchers
|
|
|
|
current = Date.now();
|
|
|
|
elapsed = current - this.lastWatcherUpdate;
|
|
|
|
leftover = (1000 / this.watcherUpdateFrequency) - elapsed;
|
|
|
|
if (leftover < 1) {
|
|
|
|
this.watchers().forEach(function (w) {
|
|
|
|
w.update();
|
|
|
|
});
|
|
|
|
this.lastWatcherUpdate = Date.now();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.statusDisplay.lastWatcherUpdate = Date.now();
|
|
|
|
this.statusDisplay.watcherUpdateFrequency = 250;
|
|
|
|
|
|
|
|
// Buttons and toggles
|
|
|
|
|
|
|
|
|
|
|
|
var toogleShowStitchButton = new ToggleMorph(
|
|
|
|
'checkbox',
|
|
|
|
null,
|
|
|
|
function () {
|
|
|
|
tStitch.toogleShowStitches();
|
|
|
|
},
|
|
|
|
'Show Stitches',
|
|
|
|
function () {
|
|
|
|
return tStitch.getShowStitches();
|
|
|
|
});
|
|
|
|
toogleShowStitchButton.columns = 2
|
|
|
|
toogleShowStitchButton.newLines = 1;
|
2015-05-10 00:13:32 +00:00
|
|
|
|
2015-05-09 19:16:56 +00:00
|
|
|
elements.push(toogleShowStitchButton);
|
|
|
|
|
|
|
|
var toogleShowJumpsButton = new ToggleMorph(
|
|
|
|
'checkbox',
|
|
|
|
null,
|
|
|
|
function () {
|
2015-05-09 19:49:38 +00:00
|
|
|
tStitch.toogleShowJumpStitches();
|
2015-05-09 19:16:56 +00:00
|
|
|
},
|
|
|
|
'Show Jump Stitches',
|
|
|
|
function () {
|
2015-05-09 19:49:38 +00:00
|
|
|
return tStitch.getShowJumpStitches();
|
2015-05-09 19:16:56 +00:00
|
|
|
});
|
2015-05-10 08:38:27 +00:00
|
|
|
toogleShowJumpsButton.columns = 1;
|
2015-05-09 19:16:56 +00:00
|
|
|
|
|
|
|
elements.push(toogleShowJumpsButton);
|
|
|
|
|
|
|
|
|
|
|
|
elements.forEach(function(each) { myself.statusDisplay.addElement(each) });
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// IDE_Morph layout
|
|
|
|
|
|
|
|
IDE_Morph.prototype.fixLayout = function (situation) {
|
|
|
|
// situation is a string, i.e.
|
|
|
|
// 'selectSprite' or 'refreshPalette' or 'tabEditor'
|
|
|
|
var padding = this.padding;
|
|
|
|
|
|
|
|
Morph.prototype.trackChanges = false;
|
|
|
|
|
|
|
|
if (situation !== 'refreshPalette') {
|
|
|
|
// controlBar
|
|
|
|
this.controlBar.setPosition(this.logo.topRight());
|
|
|
|
this.controlBar.setWidth(this.right() - this.controlBar.left());
|
|
|
|
this.controlBar.fixLayout();
|
|
|
|
|
|
|
|
// categories
|
2015-05-10 00:13:32 +00:00
|
|
|
this.categories.padding = this.padding;
|
2015-05-09 19:16:56 +00:00
|
|
|
this.categories.setLeft(this.logo.left());
|
2015-05-10 00:13:32 +00:00
|
|
|
this.categories.setTop(this.logo.bottom()+padding);
|
|
|
|
|
2015-05-09 19:16:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// palette
|
|
|
|
this.palette.setLeft(this.logo.left());
|
2015-05-10 00:13:32 +00:00
|
|
|
this.palette.setTop(this.categories.bottom() + padding);
|
2015-05-09 19:16:56 +00:00
|
|
|
this.palette.setHeight(this.bottom() - this.palette.top());
|
|
|
|
|
|
|
|
if (situation !== 'refreshPalette') {
|
|
|
|
// stage
|
|
|
|
if (this.isAppMode) {
|
|
|
|
this.stage.setScale(Math.floor(Math.min(
|
|
|
|
(this.width() - padding * 2) / this.stage.dimensions.x,
|
|
|
|
(this.height() - this.controlBar.height() * 2 - padding * 2)
|
|
|
|
/ this.stage.dimensions.y
|
|
|
|
) * 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());
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
// spriteBar
|
|
|
|
this.spriteBar.setPosition(this.logo.bottomRight().add(padding));
|
|
|
|
this.spriteBar.setExtent(new Point(
|
|
|
|
Math.max(0, this.stage.left() - padding - this.spriteBar.left()),
|
|
|
|
this.categories.bottom() - this.spriteBar.top() - padding
|
|
|
|
));
|
|
|
|
this.spriteBar.fixLayout();
|
|
|
|
*/
|
|
|
|
// spriteEditor
|
|
|
|
if (this.spriteEditor.isVisible) {
|
|
|
|
//this.spriteEditor.setPosition(this.spriteBar.bottomLeft());
|
|
|
|
this.spriteEditor.setPosition(this.logo.bottomRight().add(padding));
|
|
|
|
this.spriteEditor.setExtent(new Point(
|
|
|
|
//this.spriteBar.width(),
|
|
|
|
Math.max(0, this.stage.left() - padding - this.spriteEditor.left()),
|
|
|
|
this.bottom() - this.spriteEditor.top()
|
|
|
|
));
|
|
|
|
}
|
|
|
|
this.statusDisplay.fixLayout();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Morph.prototype.trackChanges = true;
|
|
|
|
this.changed();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// SVG export
|
|
|
|
IDE_Morph.prototype.downloadSVG = function() {
|
|
|
|
|
2015-08-11 14:52:04 +00:00
|
|
|
|
2015-05-09 19:42:01 +00:00
|
|
|
var minX=999999999, maxX=0, minY=999999999, maxY=0;
|
|
|
|
for (var i=0; i<tStitch.stitches.x.length; i++) {
|
2015-05-09 19:16:56 +00:00
|
|
|
|
2015-05-09 19:42:01 +00:00
|
|
|
var x1 = tStitch.stitches.x[i];
|
|
|
|
var y1 = tStitch.stitches.y[i];
|
2015-05-09 19:16:56 +00:00
|
|
|
|
|
|
|
if (x1<minX) minX = x1;
|
|
|
|
if (x1>maxX) maxX = x1;
|
|
|
|
|
|
|
|
if (y1<minY) minY = y1;
|
|
|
|
if (y1>maxY) maxY = y1;
|
2015-05-09 19:42:01 +00:00
|
|
|
}
|
2015-08-11 14:52:04 +00:00
|
|
|
|
|
|
|
var svgStr = "<?xml version=\"1.0\" standalone=\"no\"?>\n";
|
|
|
|
svgStr += "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \n\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
|
|
|
|
svgStr += "<svg width=\"" + parseInt(maxX-minX) + "\" height=\"" + parseInt(maxY-minY) + "\" viewBox=\"0 -" + parseInt(maxX-minX) + " " + parseInt(maxY-minY) + " 0\"\n";
|
|
|
|
svgStr += " xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n";
|
|
|
|
svgStr += "<title>Embroidery export</title>\n";
|
|
|
|
svgStr += "<path fill=\"none\" stroke=\"black\" d=\"";
|
|
|
|
|
|
|
|
svgStr += "M "+ (tStitch.stitches.x[0] - minX) + " " + (parseInt(maxY-minY) - (tStitch.stitches.y[0] - minY));
|
|
|
|
|
|
|
|
for (var i=1; i < tStitch.stitches.x.length; i++) {
|
2015-05-09 19:42:01 +00:00
|
|
|
|
2015-08-11 14:52:04 +00:00
|
|
|
if ( tStitch.stitches.jump[i]) {
|
|
|
|
if ( !tStitch.stitches.jump[i-1]) {
|
|
|
|
svgStr += "\" />\n";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (tStitch.stitches.jump[i-1]&& i>1) {
|
|
|
|
svgStr +=" <path fill=\"none\" stroke=\"black\" d=\"M "+
|
|
|
|
(tStitch.stitches.x[i] + minX) + " " + (parseInt(maxY-minY) - (tStitch.stitches.y[i] - minY));
|
|
|
|
}
|
|
|
|
svgStr += " L "+ (tStitch.stitches.x[i] - minX) + " " + (parseInt(maxY-minY) - (tStitch.stitches.y[i] - minY));
|
2015-05-09 22:08:00 +00:00
|
|
|
}
|
2015-05-09 19:16:56 +00:00
|
|
|
}
|
|
|
|
|
2015-08-11 14:52:04 +00:00
|
|
|
svgStr += "\" />\n</svg>\n"
|
2015-05-09 19:16:56 +00:00
|
|
|
|
|
|
|
blob = new Blob([svgStr], {type: 'text/plain;charset=utf-8'});
|
|
|
|
saveAs(blob, (this.projectName ? this.projectName : 'turtlestitch') + '.svg');
|
|
|
|
}
|
|
|
|
|
2015-05-09 21:44:11 +00:00
|
|
|
// EXP export
|
|
|
|
IDE_Morph.prototype.downloadEXP = function() {
|
|
|
|
var expArr = new Array();
|
|
|
|
|
2015-08-19 13:23:10 +00:00
|
|
|
pixels_per_millimeter = 5
|
|
|
|
scale = 10 / pixels_per_millimeter;
|
2015-05-09 21:44:11 +00:00
|
|
|
|
|
|
|
function move(x, y) {
|
|
|
|
y *= -1;
|
|
|
|
if (x<0) x = x + 256;
|
|
|
|
expArr.push(x);
|
|
|
|
if (y<0) y = y + 256;
|
|
|
|
expArr.push(y);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var i=1; i<tStitch.stitches.x.length; i++) {
|
|
|
|
x1 = tStitch.stitches.x[i] * scale;
|
|
|
|
y1 = tStitch.stitches.y[i] * scale;
|
|
|
|
x0 = tStitch.stitches.x[i-1] * scale;
|
|
|
|
y0 = tStitch.stitches.y[i-1] * scale;
|
|
|
|
|
|
|
|
sum_x = 0;
|
|
|
|
sum_y = 0;
|
|
|
|
dmax = Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0));
|
|
|
|
dsteps = Math.abs(dmax / 127) + 1;
|
|
|
|
if (dsteps == 1) {
|
|
|
|
if (tStitch.stitches.jump[i]) {
|
|
|
|
expArr.push(0x80);
|
|
|
|
expArr.push(0x04);
|
|
|
|
}
|
|
|
|
move((x1 - x0), (y1 - y0));
|
|
|
|
} else {
|
|
|
|
for(j=0;j<dsteps;j++) {
|
|
|
|
if (tStitch.stitches.jump[i]) {
|
|
|
|
expArr.push(0x80);
|
|
|
|
expArr.push(0x04);
|
|
|
|
}
|
|
|
|
if (j < dsteps -1) {
|
|
|
|
move((x1 - x0)/dsteps, (y1 - y0)/dsteps);
|
|
|
|
sum_x += (x1 - x0)/dsteps;
|
|
|
|
sum_y += (y1 - y0)/dsteps;
|
|
|
|
} else {
|
|
|
|
move((x1 - x0) - sum_x, (y1 - y0) - sum_y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expUintArr = new Uint8Array(expArr.length);
|
|
|
|
for (i=0;i<expArr.length;i++) {
|
|
|
|
expUintArr[i] = Math.round(expArr[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
blob = new Blob([expUintArr], {type: 'application/octet-stream'});
|
|
|
|
saveAs(blob, (this.projectName ? this.projectName : 'turtlestitch') + '.exp');
|
|
|
|
}
|
2015-05-09 19:16:56 +00:00
|
|
|
|
2015-07-13 17:12:38 +00:00
|
|
|
IDE_Morph.prototype.saveToDisk = function() {
|
|
|
|
var myself = this;
|
|
|
|
if (!this.projectName) {
|
|
|
|
myself.prompt('Save as ...', function (name) {
|
|
|
|
myself.setProjectName(name);
|
|
|
|
myself.saveProjectToDisk();
|
|
|
|
}, null, 'upload');
|
|
|
|
} else {
|
|
|
|
myself.saveProjectToDisk();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-13 11:12:08 +00:00
|
|
|
IDE_Morph.prototype.saveProjectToDisk = function() {
|
2015-07-13 17:12:38 +00:00
|
|
|
var myself = this,
|
|
|
|
data,
|
2015-07-13 11:12:08 +00:00
|
|
|
blob;
|
|
|
|
|
2015-07-13 17:12:38 +00:00
|
|
|
|
2015-07-13 11:12:08 +00:00
|
|
|
if (Process.prototype.isCatchingErrors) {
|
|
|
|
try {
|
|
|
|
data = this.serializer.serialize(this.stage);
|
|
|
|
} catch (err) {
|
|
|
|
this.showMessage('Saving failed: ' + err);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
data = this.serializer.serialize(this.stage);
|
|
|
|
}
|
|
|
|
|
2015-07-13 17:12:38 +00:00
|
|
|
myself.prompt('Save as ...', function (name) {
|
|
|
|
myself.upload(name);
|
|
|
|
}, null, 'upload');
|
2015-07-13 11:12:08 +00:00
|
|
|
blob = new Blob([data], {type: 'text/xml;charset=utf-8'});
|
|
|
|
saveAs(blob, (this.projectName ? this.projectName : 'turtlestitch_project') + '.xml');
|
|
|
|
}
|
2015-05-09 19:16:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IDE_Morph.prototype.setProjectName = function (string) {
|
|
|
|
this.projectName = string.replace(/['"]/g, ''); // filter quotation marks
|
|
|
|
this.hasChangedMedia = true;
|
|
|
|
this.controlBar.updateLabel();
|
|
|
|
};
|
|
|
|
|
2015-07-13 17:12:38 +00:00
|
|
|
IDE_Morph.prototype.uploadMe = function () {
|
2015-07-20 11:51:55 +00:00
|
|
|
var myself = this,
|
2015-07-13 17:12:38 +00:00
|
|
|
world = this.world();
|
|
|
|
myself.prompt('Upload as ...', function (name) {
|
|
|
|
myself.upload(name);
|
|
|
|
}, null, 'upload');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-20 11:51:55 +00:00
|
|
|
IDE_Morph.prototype.upload = function (name) {
|
2015-07-13 17:12:38 +00:00
|
|
|
var request = new XMLHttpRequest(),
|
|
|
|
myself = this,
|
|
|
|
world = this.world();
|
2015-07-20 11:51:55 +00:00
|
|
|
|
|
|
|
if (name) this.setProjectName(name);
|
|
|
|
data = this.serializer.serialize(this.stage);
|
|
|
|
|
2015-07-13 17:12:38 +00:00
|
|
|
tStitch.debug_msg("uploading points... sending SAVE with num points= " + tStitch.stitches.x.length, true);
|
|
|
|
params = {
|
|
|
|
"x[]": tStitch.stitches.x,
|
|
|
|
"y[]":tStitch.stitches.y,
|
|
|
|
"j[]":tStitch.stitches.jump,
|
|
|
|
"name":name,
|
|
|
|
"project_data": data
|
|
|
|
};
|
|
|
|
|
|
|
|
if (tStitch.stitches.x.length <= 1 || tStitch.stitches.y <= 1) {
|
|
|
|
new DialogBoxMorph().inform(
|
|
|
|
'Upload Error',
|
|
|
|
'No stitches to upload, please (re)generate a drawing first!',
|
|
|
|
world);
|
|
|
|
|
|
|
|
} else {
|
2015-07-20 11:51:55 +00:00
|
|
|
|
2015-07-13 17:12:38 +00:00
|
|
|
$.post(
|
|
|
|
"/upload",
|
|
|
|
data = params,
|
|
|
|
successCallback = function (data) {
|
|
|
|
if (data.slice(0,2) == "OK") {
|
|
|
|
fid = data.slice(3);
|
|
|
|
window.open('http://' + window.location.hostname + '/view/'+fid, 'TurtleStitch file preview');
|
|
|
|
} else {
|
|
|
|
new DialogBoxMorph().inform(
|
|
|
|
'Upload Error',
|
|
|
|
'Sorry! Upload failed for an unknown reason',
|
|
|
|
world);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/* replace jquery (not yet working)
|
|
|
|
params =
|
|
|
|
"x="+ tStitch.stitches.x +
|
|
|
|
"&y[]="+tStitch.stitches.y +
|
|
|
|
"&j[]="+tStitch.stitches.jump +
|
|
|
|
"&name="+name +
|
|
|
|
"&project_data="+data;
|
|
|
|
|
|
|
|
try {
|
|
|
|
console.log("post");
|
|
|
|
request.open("POST", '/upload',true);
|
|
|
|
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
|
|
|
request.setRequestHeader("Content-length", params.length);
|
|
|
|
request.setRequestHeader("Connection", "close");
|
|
|
|
|
|
|
|
request.onreadystatechange = function () {
|
|
|
|
if (request.readyState === 4) {
|
|
|
|
if (request.responseText) {
|
|
|
|
if (request.responseText.slice(0,2) == "OK") {
|
|
|
|
fid = request.responseText.slice(3);
|
|
|
|
window.open('http://' + window.location.hostname + '/view/'+fid, 'TurtleStitch file preview');
|
|
|
|
} else {
|
|
|
|
console.log(request.responseText);
|
|
|
|
new DialogBoxMorph().inform(
|
|
|
|
'Upload Error',
|
|
|
|
'Sorry! Upload failed for some reasons on the server ',
|
|
|
|
world);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
new DialogBoxMorph().inform(
|
|
|
|
'Upload Error',
|
|
|
|
'Sorry! Upload failed for an unknown reason',
|
|
|
|
world);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
request.send(params);
|
|
|
|
} catch (err) {
|
|
|
|
new DialogBoxMorph().inform(
|
|
|
|
'Upload Error',
|
|
|
|
err.toString(),
|
|
|
|
world);
|
|
|
|
}
|
|
|
|
|
|
|
|
} */
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-05-09 19:16:56 +00:00
|
|
|
IDE_Morph.prototype.createSpriteBar = function () {
|
|
|
|
// assumes that the categories pane has already been created
|
|
|
|
var rotationStyleButtons = [],
|
|
|
|
thumbSize = new Point(45, 45),
|
|
|
|
nameField,
|
|
|
|
padlock,
|
|
|
|
thumbnail,
|
|
|
|
tabCorner = 15,
|
|
|
|
tabColors = this.tabColors,
|
|
|
|
tabBar = new AlignmentMorph('row', -tabCorner * 2),
|
|
|
|
tab,
|
|
|
|
symbols = ['\u2192', '\u21BB', '\u2194'],
|
|
|
|
labels = ['don\'t rotate', 'can rotate', 'only face left/right'],
|
|
|
|
myself = this;
|
|
|
|
|
|
|
|
if (this.spriteBar) {
|
|
|
|
this.spriteBar.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.spriteBar = new Morph();
|
|
|
|
this.spriteBar.color = this.frameColor;
|
|
|
|
//this.add(this.spriteBar);
|
|
|
|
|
|
|
|
function addRotationStyleButton(rotationStyle) {
|
|
|
|
var colors = myself.rotationStyleColors,
|
|
|
|
button;
|
|
|
|
|
|
|
|
button = new ToggleButtonMorph(
|
|
|
|
colors,
|
|
|
|
myself, // the IDE is the target
|
|
|
|
function () {
|
|
|
|
if (myself.currentSprite instanceof SpriteMorph) {
|
|
|
|
myself.currentSprite.rotationStyle = rotationStyle;
|
|
|
|
myself.currentSprite.changed();
|
|
|
|
myself.currentSprite.drawNew();
|
|
|
|
myself.currentSprite.changed();
|
|
|
|
}
|
|
|
|
rotationStyleButtons.forEach(function (each) {
|
|
|
|
each.refresh();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
symbols[rotationStyle], // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentSprite instanceof SpriteMorph
|
|
|
|
&& myself.currentSprite.rotationStyle === rotationStyle;
|
|
|
|
},
|
|
|
|
null, // environment
|
|
|
|
localize(labels[rotationStyle])
|
|
|
|
);
|
|
|
|
|
|
|
|
button.corner = 8;
|
|
|
|
button.labelMinExtent = new Point(11, 11);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = myself.buttonLabelColor;
|
|
|
|
button.fixLayout();
|
|
|
|
button.refresh();
|
|
|
|
rotationStyleButtons.push(button);
|
|
|
|
button.setPosition(myself.spriteBar.position().add(2));
|
|
|
|
button.setTop(button.top()
|
|
|
|
+ ((rotationStyleButtons.length - 1) * (button.height() + 2))
|
|
|
|
);
|
|
|
|
myself.spriteBar.add(button);
|
|
|
|
if (myself.currentSprite instanceof StageMorph) {
|
|
|
|
button.hide();
|
|
|
|
}
|
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
|
|
|
addRotationStyleButton(1);
|
|
|
|
addRotationStyleButton(2);
|
|
|
|
addRotationStyleButton(0);
|
|
|
|
this.rotationStyleButtons = rotationStyleButtons;
|
|
|
|
|
|
|
|
thumbnail = new Morph();
|
|
|
|
thumbnail.setExtent(thumbSize);
|
|
|
|
thumbnail.image = this.currentSprite.thumbnail(thumbSize);
|
|
|
|
thumbnail.setPosition(
|
|
|
|
rotationStyleButtons[0].topRight().add(new Point(5, 3))
|
|
|
|
);
|
|
|
|
this.spriteBar.add(thumbnail);
|
|
|
|
|
|
|
|
thumbnail.fps = 3;
|
|
|
|
|
|
|
|
thumbnail.step = function () {
|
|
|
|
if (thumbnail.version !== myself.currentSprite.version) {
|
|
|
|
thumbnail.image = myself.currentSprite.thumbnail(thumbSize);
|
|
|
|
thumbnail.changed();
|
|
|
|
thumbnail.version = myself.currentSprite.version;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
nameField = new InputFieldMorph(this.currentSprite.name);
|
|
|
|
nameField.setWidth(100); // fixed dimensions
|
|
|
|
nameField.contrast = 90;
|
|
|
|
nameField.setPosition(thumbnail.topRight().add(new Point(10, 3)));
|
|
|
|
this.spriteBar.add(nameField);
|
|
|
|
nameField.drawNew();
|
|
|
|
nameField.accept = function () {
|
|
|
|
var newName = nameField.getValue();
|
|
|
|
myself.currentSprite.setName(
|
|
|
|
myself.newSpriteName(newName, myself.currentSprite)
|
|
|
|
);
|
|
|
|
nameField.setContents(myself.currentSprite.name);
|
|
|
|
};
|
|
|
|
this.spriteBar.reactToEdit = nameField.accept;
|
|
|
|
|
|
|
|
// padlock
|
|
|
|
padlock = new ToggleMorph(
|
|
|
|
'checkbox',
|
|
|
|
null,
|
|
|
|
function () {
|
|
|
|
myself.currentSprite.isDraggable =
|
|
|
|
!myself.currentSprite.isDraggable;
|
|
|
|
},
|
|
|
|
localize('draggable'),
|
|
|
|
function () {
|
|
|
|
return myself.currentSprite.isDraggable;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
padlock.label.isBold = false;
|
|
|
|
padlock.label.setColor(this.buttonLabelColor);
|
|
|
|
padlock.color = tabColors[2];
|
|
|
|
padlock.highlightColor = tabColors[0];
|
|
|
|
padlock.pressColor = tabColors[1];
|
|
|
|
|
|
|
|
padlock.tick.shadowOffset = MorphicPreferences.isFlat ?
|
|
|
|
new Point() : new Point(-1, -1);
|
|
|
|
padlock.tick.shadowColor = new Color(); // black
|
|
|
|
padlock.tick.color = this.buttonLabelColor;
|
|
|
|
padlock.tick.isBold = false;
|
|
|
|
padlock.tick.drawNew();
|
|
|
|
|
|
|
|
padlock.setPosition(nameField.bottomLeft().add(2));
|
|
|
|
padlock.drawNew();
|
|
|
|
this.spriteBar.add(padlock);
|
|
|
|
if (this.currentSprite instanceof StageMorph) {
|
|
|
|
padlock.hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
// tab bar
|
|
|
|
tabBar.tabTo = function (tabString) {
|
|
|
|
var active;
|
|
|
|
myself.currentTab = tabString;
|
|
|
|
this.children.forEach(function (each) {
|
|
|
|
each.refresh();
|
|
|
|
if (each.state) {active = each; }
|
|
|
|
});
|
|
|
|
active.refresh(); // needed when programmatically tabbing
|
|
|
|
myself.createSpriteEditor();
|
|
|
|
myself.fixLayout('tabEditor');
|
2015-08-19 14:33:00 +00:00
|
|
|
};t
|
2015-05-09 19:16:56 +00:00
|
|
|
|
|
|
|
tab = new TabMorph(
|
|
|
|
tabColors,
|
|
|
|
null, // target
|
|
|
|
function () {tabBar.tabTo('scripts'); },
|
|
|
|
localize('Scripts'), // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentTab === 'scripts';
|
|
|
|
}
|
|
|
|
);
|
|
|
|
tab.padding = 3;
|
|
|
|
tab.corner = tabCorner;
|
|
|
|
tab.edge = 1;
|
|
|
|
tab.labelShadowOffset = new Point(-1, -1);
|
|
|
|
tab.labelShadowColor = tabColors[1];
|
|
|
|
tab.labelColor = this.buttonLabelColor;
|
|
|
|
tab.drawNew();
|
|
|
|
tab.fixLayout();
|
|
|
|
tabBar.add(tab);
|
|
|
|
|
|
|
|
tab = new TabMorph(
|
|
|
|
tabColors,
|
|
|
|
null, // target
|
|
|
|
function () {tabBar.tabTo('costumes'); },
|
|
|
|
localize('Costumes'), // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentTab === 'costumes';
|
|
|
|
}
|
|
|
|
);
|
|
|
|
tab.padding = 3;
|
|
|
|
tab.corner = tabCorner;
|
|
|
|
tab.edge = 1;
|
|
|
|
tab.labelShadowOffset = new Point(-1, -1);
|
|
|
|
tab.labelShadowColor = tabColors[1];
|
|
|
|
tab.labelColor = this.buttonLabelColor;
|
|
|
|
tab.drawNew();
|
|
|
|
tab.fixLayout();
|
|
|
|
tabBar.add(tab);
|
|
|
|
|
|
|
|
tab = new TabMorph(
|
|
|
|
tabColors,
|
|
|
|
null, // target
|
|
|
|
function () {tabBar.tabTo('sounds'); },
|
|
|
|
localize('Sounds'), // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentTab === 'sounds';
|
|
|
|
}
|
|
|
|
);
|
|
|
|
tab.padding = 3;
|
|
|
|
tab.corner = tabCorner;
|
|
|
|
tab.edge = 1;
|
|
|
|
tab.labelShadowOffset = new Point(-1, -1);
|
|
|
|
tab.labelShadowColor = tabColors[1];
|
|
|
|
tab.labelColor = this.buttonLabelColor;
|
|
|
|
tab.drawNew();
|
|
|
|
tab.fixLayout();
|
|
|
|
tabBar.add(tab);
|
|
|
|
|
|
|
|
tabBar.fixLayout();
|
|
|
|
tabBar.children.forEach(function (each) {
|
|
|
|
each.refresh();
|
|
|
|
});
|
|
|
|
this.spriteBar.tabBar = tabBar;
|
|
|
|
this.spriteBar.add(this.spriteBar.tabBar);
|
|
|
|
|
|
|
|
this.spriteBar.fixLayout = function () {
|
|
|
|
this.tabBar.setLeft(this.left());
|
|
|
|
this.tabBar.setBottom(this.bottom());
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// StageMorph user menu
|
|
|
|
|
|
|
|
StageMorph.prototype.userMenu = function () {
|
|
|
|
var ide = this.parentThatIsA(IDE_Morph),
|
|
|
|
menu = new MenuMorph(this),
|
|
|
|
shiftClicked = this.world().currentKey === 16,
|
|
|
|
myself = this;
|
|
|
|
|
|
|
|
if (ide && ide.isAppMode) {
|
|
|
|
// menu.addItem('help', 'nop');
|
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
//menu.addItem("edit", 'edit');
|
|
|
|
menu.addItem("show all", 'showAll');
|
|
|
|
menu.addItem(
|
|
|
|
"pic...",
|
|
|
|
function () {
|
|
|
|
window.open(myself.fullImageClassic().toDataURL());
|
|
|
|
},
|
|
|
|
'open a new window\nwith a picture of the stage'
|
|
|
|
);
|
|
|
|
if (shiftClicked) {
|
|
|
|
menu.addLine();
|
|
|
|
menu.addItem(
|
|
|
|
"turn pen trails into new costume...",
|
|
|
|
function () {
|
|
|
|
var costume = new Costume(
|
|
|
|
myself.trailsCanvas,
|
|
|
|
Date.now().toString()
|
|
|
|
).copy();
|
|
|
|
ide.currentSprite.addCostume(costume);
|
|
|
|
ide.currentSprite.wearCostume(costume);
|
|
|
|
ide.hasChangedMedia = true;
|
|
|
|
},
|
|
|
|
'turn all pen trails and stamps\n' +
|
|
|
|
'into a new costume for the\ncurrently selected sprite',
|
|
|
|
new Color(100, 0, 0)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return menu;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
IDE_Morph.prototype.createCategories = function () {
|
|
|
|
// assumes the logo has already been created
|
|
|
|
var myself = this;
|
|
|
|
|
|
|
|
if (this.categories) {
|
|
|
|
this.categories.destroy();
|
|
|
|
}
|
|
|
|
this.categories = new Morph();
|
|
|
|
this.categories.color = this.groupColor;
|
|
|
|
this.categories.silentSetWidth(this.logo.width()); // width is fixed
|
|
|
|
|
|
|
|
function addCategoryButton(category) {
|
|
|
|
var labelWidth = 75,
|
|
|
|
colors = [
|
|
|
|
myself.frameColor,
|
|
|
|
myself.frameColor.darker(50),
|
|
|
|
SpriteMorph.prototype.blockColor[category]
|
|
|
|
],
|
|
|
|
button;
|
|
|
|
|
|
|
|
button = new ToggleButtonMorph(
|
|
|
|
colors,
|
|
|
|
myself, // the IDE is the target
|
|
|
|
function () {
|
|
|
|
myself.currentCategory = category;
|
|
|
|
myself.categories.children.forEach(function (each) {
|
|
|
|
each.refresh();
|
|
|
|
});
|
|
|
|
myself.refreshPalette(true);
|
|
|
|
},
|
|
|
|
category[0].toUpperCase().concat(category.slice(1)), // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentCategory === category;
|
|
|
|
},
|
|
|
|
null, // env
|
|
|
|
null, // hint
|
|
|
|
null, // template cache
|
|
|
|
labelWidth, // minWidth
|
|
|
|
true // has preview
|
|
|
|
);
|
|
|
|
|
|
|
|
button.corner = 8;
|
2015-05-10 00:13:32 +00:00
|
|
|
button.padding = 3;
|
2015-05-09 19:16:56 +00:00
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = myself.buttonLabelColor;
|
|
|
|
button.fixLayout();
|
|
|
|
button.refresh();
|
|
|
|
myself.categories.add(button);
|
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
|
|
|
function fixCategoriesLayout() {
|
|
|
|
var buttonWidth = myself.categories.children[0].width(),
|
|
|
|
buttonHeight = myself.categories.children[0].height(),
|
|
|
|
border = 3,
|
|
|
|
rows = Math.ceil((myself.categories.children.length) / 2),
|
|
|
|
xPadding = (myself.categories.width()
|
|
|
|
- border
|
|
|
|
- buttonWidth * 2) / 3,
|
|
|
|
yPadding = 2,
|
|
|
|
l = myself.categories.left(),
|
|
|
|
t = myself.categories.top(),
|
|
|
|
i = 0,
|
|
|
|
row,
|
|
|
|
col;
|
|
|
|
|
|
|
|
myself.categories.children.forEach(function (button) {
|
|
|
|
i += 1;
|
|
|
|
row = Math.ceil(i / 2);
|
|
|
|
col = 2 - (i % 2);
|
|
|
|
button.setPosition(new Point(
|
|
|
|
l + (col * xPadding + ((col - 1) * buttonWidth)),
|
|
|
|
t + (row * yPadding + ((row - 1) * buttonHeight) + border)
|
|
|
|
));
|
|
|
|
});
|
|
|
|
|
|
|
|
myself.categories.setHeight(
|
|
|
|
(rows + 1) * yPadding
|
|
|
|
+ rows * buttonHeight
|
|
|
|
+ 2 * border
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
SpriteMorph.prototype.categories.forEach(function (cat) {
|
|
|
|
if (!contains(['lists', 'other','sound','looks'], cat)) {
|
|
|
|
addCategoryButton(cat);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
fixCategoriesLayout();
|
|
|
|
this.add(this.categories);
|
|
|
|
};
|
|
|
|
|
|
|
|
IDE_Morph.prototype.projectMenu = function () {
|
|
|
|
var menu,
|
|
|
|
myself = this,
|
|
|
|
world = this.world(),
|
|
|
|
pos = this.controlBar.projectButton.bottomLeft(),
|
|
|
|
graphicsName = this.currentSprite instanceof SpriteMorph ?
|
|
|
|
'Costumes' : 'Backgrounds',
|
|
|
|
shiftClicked = (world.currentKey === 16);
|
|
|
|
|
|
|
|
menu = new MenuMorph(this);
|
|
|
|
menu.addItem('Project notes...', 'editProjectNotes');
|
|
|
|
menu.addLine();
|
|
|
|
menu.addItem('New', 'createNewProject');
|
|
|
|
menu.addItem('Open...', 'openProjectsBrowser');
|
2015-08-10 22:33:36 +00:00
|
|
|
//menu.addItem('Save', "save");
|
2015-05-09 19:16:56 +00:00
|
|
|
menu.addItem('Save As...', 'saveProjectsBrowser');
|
2015-07-13 17:12:38 +00:00
|
|
|
menu.addItem('Save to Disk', 'saveToDisk');
|
2015-05-09 19:16:56 +00:00
|
|
|
menu.addLine();
|
|
|
|
menu.addItem(
|
|
|
|
'Import...',
|
|
|
|
function () {
|
|
|
|
var inp = document.createElement('input');
|
|
|
|
if (myself.filePicker) {
|
|
|
|
document.body.removeChild(myself.filePicker);
|
|
|
|
myself.filePicker = null;
|
|
|
|
}
|
|
|
|
inp.type = 'file';
|
|
|
|
inp.style.color = "transparent";
|
|
|
|
inp.style.backgroundColor = "transparent";
|
|
|
|
inp.style.border = "none";
|
|
|
|
inp.style.outline = "none";
|
|
|
|
inp.style.position = "absolute";
|
|
|
|
inp.style.top = "0px";
|
|
|
|
inp.style.left = "0px";
|
|
|
|
inp.style.width = "0px";
|
|
|
|
inp.style.height = "0px";
|
|
|
|
inp.addEventListener(
|
|
|
|
"change",
|
|
|
|
function () {
|
|
|
|
document.body.removeChild(inp);
|
|
|
|
myself.filePicker = null;
|
|
|
|
world.hand.processDrop(inp.files);
|
|
|
|
},
|
|
|
|
false
|
|
|
|
);
|
|
|
|
document.body.appendChild(inp);
|
|
|
|
myself.filePicker = inp;
|
|
|
|
inp.click();
|
|
|
|
},
|
|
|
|
'file menu import hint' // looks up the actual text in the translator
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
menu.addItem(
|
|
|
|
shiftClicked ?
|
|
|
|
'Export project as plain text...' : 'Export project...',
|
|
|
|
function () {
|
|
|
|
if (myself.projectName) {
|
|
|
|
myself.exportProject(myself.projectName, shiftClicked);
|
|
|
|
} else {
|
|
|
|
myself.prompt('Export Project As...', function (name) {
|
|
|
|
myself.exportProject(name);
|
|
|
|
}, null, 'exportProject');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'show project data as XML\nin a new browser window',
|
|
|
|
shiftClicked ? new Color(100, 0, 0) : null
|
|
|
|
);
|
|
|
|
|
|
|
|
menu.addItem(
|
|
|
|
'Export blocks...',
|
|
|
|
function () {myself.exportGlobalBlocks(); },
|
|
|
|
'show global custom block definitions as XML\nin a new browser window'
|
|
|
|
);
|
|
|
|
|
|
|
|
menu.addLine();
|
2015-07-13 17:12:38 +00:00
|
|
|
menu.addItem('Upload stitch file', 'uploadMe','Export stage drawing to stitch file (EXP)..');
|
2015-05-09 19:16:56 +00:00
|
|
|
menu.addItem(
|
|
|
|
'Export as SVG',
|
|
|
|
function() { myself.downloadSVG() },
|
2015-05-09 21:44:11 +00:00
|
|
|
'download current drawing as SVG file'
|
2015-05-09 19:16:56 +00:00
|
|
|
);
|
2015-05-09 21:44:11 +00:00
|
|
|
menu.addItem(
|
|
|
|
'Export as EXP',
|
|
|
|
function() { myself.downloadEXP() },
|
|
|
|
'download current drawing as EXP file'
|
|
|
|
);
|
2015-05-09 19:16:56 +00:00
|
|
|
|
|
|
|
if (shiftClicked) {
|
|
|
|
menu.addItem(
|
|
|
|
'Export all scripts as pic...',
|
|
|
|
function () {myself.exportScriptsPicture(); },
|
|
|
|
'show a picture of all scripts\nand block definitions',
|
|
|
|
new Color(100, 0, 0)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
menu.addLine();
|
|
|
|
menu.addItem(
|
|
|
|
'Import tools',
|
|
|
|
function () {
|
|
|
|
myself.droppedText(
|
|
|
|
myself.getURLsbeOrRelative(
|
|
|
|
'tools.xml'
|
|
|
|
),
|
|
|
|
'tools'
|
|
|
|
);
|
|
|
|
},
|
|
|
|
'load the official library of\npowerful blocks'
|
|
|
|
);
|
|
|
|
menu.addItem(
|
|
|
|
'Libraries...',
|
|
|
|
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';
|
|
|
|
|
|
|
|
function loadLib(name) {
|
|
|
|
var url = 'http://snap.berkeley.edu/snapsource/libraries/'
|
|
|
|
+ name
|
|
|
|
+ '.xml';
|
|
|
|
myself.droppedText(myself.getURL(url), name);
|
|
|
|
}
|
|
|
|
|
|
|
|
myself.getURL(libUrl).split('\n').forEach(function (line) {
|
|
|
|
if (line.length > 0) {
|
|
|
|
libMenu.addItem(
|
|
|
|
line.substring(line.indexOf('\t') + 1),
|
|
|
|
function () {
|
|
|
|
loadLib(
|
|
|
|
line.substring(0, line.indexOf('\t'))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
libMenu.popup(world, pos);
|
|
|
|
},
|
|
|
|
'Select categories of additional blocks to add to this project.'
|
|
|
|
);
|
|
|
|
|
|
|
|
menu.popup(world, pos);
|
|
|
|
};
|
|
|
|
|
|
|
|
IDE_Morph.prototype.snapMenu = function () {
|
|
|
|
var menu,
|
|
|
|
world = this.world();
|
|
|
|
|
|
|
|
menu = new MenuMorph(this);
|
|
|
|
menu.addItem('About...', 'aboutSnap');
|
|
|
|
menu.addLine();
|
|
|
|
menu.addItem(
|
|
|
|
'Reference manual',
|
|
|
|
function () {
|
|
|
|
window.open('help/SnapManual.pdf', 'SnapReferenceManual');
|
|
|
|
}
|
|
|
|
);
|
|
|
|
menu.addItem(
|
|
|
|
'TurtleStich! website',
|
|
|
|
function () {
|
|
|
|
window.open('http://'+window.location.hostname, 'SnapWebsite');
|
|
|
|
}
|
|
|
|
);
|
|
|
|
menu.addItem(
|
|
|
|
'Snap! website',
|
|
|
|
function () {
|
|
|
|
window.open('http://snap.berkeley.edu/', 'SnapWebsite');
|
|
|
|
}
|
|
|
|
);
|
|
|
|
menu.addItem(
|
|
|
|
'Download source',
|
|
|
|
function () {
|
|
|
|
window.open(
|
|
|
|
'http://snap.berkeley.edu/snapsource/snap.zip',
|
|
|
|
'SnapSource'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
if (world.isDevMode) {
|
|
|
|
menu.addLine();
|
|
|
|
menu.addItem(
|
|
|
|
'Switch back to user mode',
|
|
|
|
'switchToUserMode',
|
|
|
|
'disable deep-Morphic\ncontext menus'
|
|
|
|
+ '\nand show user-friendly ones',
|
|
|
|
new Color(0, 100, 0)
|
|
|
|
);
|
|
|
|
} else if (world.currentKey === 16) { // shift-click
|
|
|
|
menu.addLine();
|
|
|
|
menu.addItem(
|
|
|
|
'Switch to dev mode',
|
|
|
|
'switchToDevMode',
|
|
|
|
'enable Morphic\ncontext menus\nand inspectors,'
|
|
|
|
+ '\nnot user-friendly!',
|
|
|
|
new Color(100, 0, 0)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
menu.popup(world, this.logo.bottomLeft());
|
|
|
|
};
|
|
|
|
|
2015-05-10 00:13:32 +00:00
|
|
|
|
|
|
|
IDE_Morph.prototype.originalCreateSpriteEditor = IDE_Morph.prototype.createSpriteEditor;
|
|
|
|
IDE_Morph.prototype.createSpriteEditor = function(){
|
|
|
|
this.originalCreateSpriteEditor();
|
|
|
|
this.spriteEditor.color = new Color(240, 240, 240);
|
|
|
|
this.currentSprite.scripts.color = new Color(240, 240, 240);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IDE_Morph.prototype.createSpriteBar = function () {
|
|
|
|
// assumes that the categories pane has already been created
|
|
|
|
var rotationStyleButtons = [],
|
|
|
|
thumbSize = new Point(45, 45),
|
|
|
|
nameField,
|
|
|
|
padlock,
|
|
|
|
thumbnail,
|
|
|
|
tabCorner = 15,
|
|
|
|
tabColors = this.tabColors,
|
|
|
|
tabBar = new AlignmentMorph('row', -tabCorner * 2),
|
|
|
|
tab,
|
|
|
|
symbols = ['\u2192', '\u21BB', '\u2194'],
|
|
|
|
labels = ['don\'t rotate', 'can rotate', 'only face left/right'],
|
|
|
|
myself = this;
|
|
|
|
|
|
|
|
if (this.spriteBar) {
|
|
|
|
this.spriteBar.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.spriteBar = new Morph();
|
|
|
|
this.spriteBar.color = this.frameColor;
|
|
|
|
//this.add(this.spriteBar);
|
|
|
|
|
|
|
|
function addRotationStyleButton(rotationStyle) {
|
|
|
|
var colors = myself.rotationStyleColors,
|
|
|
|
button;
|
|
|
|
|
|
|
|
button = new ToggleButtonMorph(
|
|
|
|
colors,
|
|
|
|
myself, // the IDE is the target
|
|
|
|
function () {
|
|
|
|
if (myself.currentSprite instanceof SpriteMorph) {
|
|
|
|
myself.currentSprite.rotationStyle = rotationStyle;
|
|
|
|
myself.currentSprite.changed();
|
|
|
|
myself.currentSprite.drawNew();
|
|
|
|
myself.currentSprite.changed();
|
|
|
|
}
|
|
|
|
rotationStyleButtons.forEach(function (each) {
|
|
|
|
each.refresh();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
symbols[rotationStyle], // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentSprite instanceof SpriteMorph
|
|
|
|
&& myself.currentSprite.rotationStyle === rotationStyle;
|
|
|
|
},
|
|
|
|
null, // environment
|
|
|
|
localize(labels[rotationStyle])
|
|
|
|
);
|
|
|
|
|
|
|
|
button.corner = 8;
|
|
|
|
button.labelMinExtent = new Point(11, 11);
|
|
|
|
button.padding = 0;
|
|
|
|
button.labelShadowOffset = new Point(-1, -1);
|
|
|
|
button.labelShadowColor = colors[1];
|
|
|
|
button.labelColor = myself.buttonLabelColor;
|
|
|
|
button.fixLayout();
|
|
|
|
button.refresh();
|
|
|
|
rotationStyleButtons.push(button);
|
|
|
|
button.setPosition(myself.spriteBar.position().add(2));
|
|
|
|
button.setTop(button.top()
|
|
|
|
+ ((rotationStyleButtons.length - 1) * (button.height() + 2))
|
|
|
|
);
|
|
|
|
myself.spriteBar.add(button);
|
|
|
|
if (myself.currentSprite instanceof StageMorph) {
|
|
|
|
button.hide();
|
|
|
|
}
|
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
|
|
|
addRotationStyleButton(1);
|
|
|
|
addRotationStyleButton(2);
|
|
|
|
addRotationStyleButton(0);
|
|
|
|
this.rotationStyleButtons = rotationStyleButtons;
|
|
|
|
|
|
|
|
thumbnail = new Morph();
|
|
|
|
thumbnail.setExtent(thumbSize);
|
|
|
|
thumbnail.image = this.currentSprite.thumbnail(thumbSize);
|
|
|
|
thumbnail.setPosition(
|
|
|
|
rotationStyleButtons[0].topRight().add(new Point(5, 3))
|
|
|
|
);
|
|
|
|
this.spriteBar.add(thumbnail);
|
|
|
|
|
|
|
|
thumbnail.fps = 3;
|
|
|
|
|
|
|
|
thumbnail.step = function () {
|
|
|
|
if (thumbnail.version !== myself.currentSprite.version) {
|
|
|
|
thumbnail.image = myself.currentSprite.thumbnail(thumbSize);
|
|
|
|
thumbnail.changed();
|
|
|
|
thumbnail.version = myself.currentSprite.version;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
nameField = new InputFieldMorph(this.currentSprite.name);
|
|
|
|
nameField.setWidth(100); // fixed dimensions
|
|
|
|
nameField.contrast = 90;
|
|
|
|
nameField.setPosition(thumbnail.topRight().add(new Point(10, 3)));
|
|
|
|
this.spriteBar.add(nameField);
|
|
|
|
nameField.drawNew();
|
|
|
|
nameField.accept = function () {
|
|
|
|
var newName = nameField.getValue();
|
|
|
|
myself.currentSprite.setName(
|
|
|
|
myself.newSpriteName(newName, myself.currentSprite)
|
|
|
|
);
|
|
|
|
nameField.setContents(myself.currentSprite.name);
|
|
|
|
};
|
|
|
|
this.spriteBar.reactToEdit = nameField.accept;
|
|
|
|
|
|
|
|
// padlock
|
|
|
|
padlock = new ToggleMorph(
|
|
|
|
'checkbox',
|
|
|
|
null,
|
|
|
|
function () {
|
|
|
|
myself.currentSprite.isDraggable =
|
|
|
|
!myself.currentSprite.isDraggable;
|
|
|
|
},
|
|
|
|
localize('draggable'),
|
|
|
|
function () {
|
|
|
|
return myself.currentSprite.isDraggable;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
padlock.label.isBold = false;
|
|
|
|
padlock.label.setColor(this.buttonLabelColor);
|
|
|
|
padlock.color = tabColors[2];
|
|
|
|
padlock.highlightColor = tabColors[0];
|
|
|
|
padlock.pressColor = tabColors[1];
|
|
|
|
|
|
|
|
padlock.tick.shadowOffset = MorphicPreferences.isFlat ?
|
|
|
|
new Point() : new Point(-1, -1);
|
|
|
|
padlock.tick.shadowColor = new Color(); // black
|
|
|
|
padlock.tick.color = this.buttonLabelColor;
|
|
|
|
padlock.tick.isBold = false;
|
|
|
|
padlock.tick.drawNew();
|
|
|
|
|
|
|
|
padlock.setPosition(nameField.bottomLeft().add(2));
|
|
|
|
padlock.drawNew();
|
|
|
|
this.spriteBar.add(padlock);
|
|
|
|
if (this.currentSprite instanceof StageMorph) {
|
|
|
|
padlock.hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
// tab bar
|
|
|
|
tabBar.tabTo = function (tabString) {
|
|
|
|
var active;
|
|
|
|
myself.currentTab = tabString;
|
|
|
|
this.children.forEach(function (each) {
|
|
|
|
each.refresh();
|
|
|
|
if (each.state) {active = each; }
|
|
|
|
});
|
|
|
|
active.refresh(); // needed when programmatically tabbing
|
|
|
|
myself.createSpriteEditor();
|
|
|
|
myself.fixLayout('tabEditor');
|
|
|
|
};
|
|
|
|
|
|
|
|
tab = new TabMorph(
|
|
|
|
tabColors,
|
|
|
|
null, // target
|
|
|
|
function () {tabBar.tabTo('scripts'); },
|
|
|
|
localize('Scripts'), // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentTab === 'scripts';
|
|
|
|
}
|
|
|
|
);
|
|
|
|
tab.padding = 3;
|
|
|
|
tab.corner = tabCorner;
|
|
|
|
tab.edge = 1;
|
|
|
|
tab.labelShadowOffset = new Point(-1, -1);
|
|
|
|
tab.labelShadowColor = tabColors[1];
|
|
|
|
tab.labelColor = this.buttonLabelColor;
|
|
|
|
tab.drawNew();
|
|
|
|
tab.fixLayout();
|
|
|
|
tabBar.add(tab);
|
|
|
|
|
|
|
|
tab = new TabMorph(
|
|
|
|
tabColors,
|
|
|
|
null, // target
|
|
|
|
function () {tabBar.tabTo('costumes'); },
|
|
|
|
localize('Costumes'), // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentTab === 'costumes';
|
|
|
|
}
|
|
|
|
);
|
|
|
|
tab.padding = 3;
|
|
|
|
tab.corner = tabCorner;
|
|
|
|
tab.edge = 1;
|
|
|
|
tab.labelShadowOffset = new Point(-1, -1);
|
|
|
|
tab.labelShadowColor = tabColors[1];
|
|
|
|
tab.labelColor = this.buttonLabelColor;
|
|
|
|
tab.drawNew();
|
|
|
|
tab.fixLayout();
|
|
|
|
tabBar.add(tab);
|
|
|
|
|
|
|
|
tab = new TabMorph(
|
|
|
|
tabColors,
|
|
|
|
null, // target
|
|
|
|
function () {tabBar.tabTo('sounds'); },
|
|
|
|
localize('Sounds'), // label
|
|
|
|
function () { // query
|
|
|
|
return myself.currentTab === 'sounds';
|
|
|
|
}
|
|
|
|
);
|
|
|
|
tab.padding = 3;
|
|
|
|
tab.corner = tabCorner;
|
|
|
|
tab.edge = 1;
|
|
|
|
tab.labelShadowOffset = new Point(-1, -1);
|
|
|
|
tab.labelShadowColor = tabColors[1];
|
|
|
|
tab.labelColor = this.buttonLabelColor;
|
|
|
|
tab.drawNew();
|
|
|
|
tab.fixLayout();
|
|
|
|
tabBar.add(tab);
|
|
|
|
|
|
|
|
tabBar.fixLayout();
|
|
|
|
tabBar.children.forEach(function (each) {
|
|
|
|
each.refresh();
|
|
|
|
});
|
|
|
|
this.spriteBar.tabBar = tabBar;
|
|
|
|
this.spriteBar.add(this.spriteBar.tabBar);
|
|
|
|
|
|
|
|
this.spriteBar.fixLayout = function () {
|
|
|
|
this.tabBar.setLeft(this.left());
|
|
|
|
this.tabBar.setBottom(this.bottom());
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
IDE_Morph.prototype.createCorral = function () {
|
|
|
|
// assumes the corral bar has already been created
|
|
|
|
var frame, template, padding = 5, myself = this;
|
|
|
|
|
|
|
|
if (this.corral) {
|
|
|
|
this.corral.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.corral = new Morph();
|
|
|
|
this.corral.color = this.groupColor;
|
|
|
|
//this.add(this.corral);
|
|
|
|
|
|
|
|
this.corral.stageIcon = new SpriteIconMorph(this.stage);
|
|
|
|
this.corral.stageIcon.isDraggable = false;
|
|
|
|
this.corral.add(this.corral.stageIcon);
|
|
|
|
|
|
|
|
frame = new ScrollFrameMorph(null, null, this.sliderColor);
|
|
|
|
frame.acceptsDrops = false;
|
|
|
|
frame.contents.acceptsDrops = false;
|
|
|
|
|
|
|
|
frame.contents.wantsDropOf = function (morph) {
|
|
|
|
return morph instanceof SpriteIconMorph;
|
|
|
|
};
|
|
|
|
|
|
|
|
frame.contents.reactToDropOf = function (spriteIcon) {
|
|
|
|
myself.corral.reactToDropOf(spriteIcon);
|
|
|
|
};
|
|
|
|
|
|
|
|
frame.alpha = 0;
|
|
|
|
|
|
|
|
this.sprites.asArray().forEach(function (morph) {
|
|
|
|
template = new SpriteIconMorph(morph, template);
|
|
|
|
frame.contents.add(template);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.corral.frame = frame;
|
|
|
|
this.corral.add(frame);
|
|
|
|
|
|
|
|
this.corral.fixLayout = function () {
|
|
|
|
this.stageIcon.setCenter(this.center());
|
|
|
|
this.stageIcon.setLeft(this.left() + padding);
|
|
|
|
this.frame.setLeft(this.stageIcon.right() + padding);
|
|
|
|
this.frame.setExtent(new Point(
|
|
|
|
this.right() - this.frame.left(),
|
|
|
|
this.height()
|
|
|
|
));
|
|
|
|
this.arrangeIcons();
|
|
|
|
this.refresh();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.corral.arrangeIcons = function () {
|
|
|
|
var x = this.frame.left(),
|
|
|
|
y = this.frame.top(),
|
|
|
|
max = this.frame.right(),
|
|
|
|
start = this.frame.left();
|
2015-05-09 19:16:56 +00:00
|
|
|
|
2015-05-10 00:13:32 +00:00
|
|
|
this.frame.contents.children.forEach(function (icon) {
|
|
|
|
var w = icon.width();
|
|
|
|
|
|
|
|
if (x + w > max) {
|
|
|
|
x = start;
|
|
|
|
y += icon.height(); // they're all the same
|
|
|
|
}
|
|
|
|
icon.setPosition(new Point(x, y));
|
|
|
|
x += w;
|
|
|
|
});
|
|
|
|
this.frame.contents.adjustBounds();
|
|
|
|
};
|
2015-05-09 19:16:56 +00:00
|
|
|
|
2015-05-10 00:13:32 +00:00
|
|
|
this.corral.addSprite = function (sprite) {
|
|
|
|
this.frame.contents.add(new SpriteIconMorph(sprite));
|
|
|
|
this.fixLayout();
|
|
|
|
};
|
|
|
|
|
|
|
|
this.corral.refresh = function () {
|
|
|
|
this.stageIcon.refresh();
|
|
|
|
this.frame.contents.children.forEach(function (icon) {
|
|
|
|
icon.refresh();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
this.corral.wantsDropOf = function (morph) {
|
|
|
|
return morph instanceof SpriteIconMorph;
|
|
|
|
};
|
|
|
|
|
|
|
|
this.corral.reactToDropOf = function (spriteIcon) {
|
|
|
|
var idx = 1,
|
|
|
|
pos = spriteIcon.position();
|
|
|
|
spriteIcon.destroy();
|
|
|
|
this.frame.contents.children.forEach(function (icon) {
|
|
|
|
if (pos.gt(icon.position()) || pos.y > icon.bottom()) {
|
|
|
|
idx += 1;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
myself.sprites.add(spriteIcon.object, idx);
|
|
|
|
myself.createCorral();
|
|
|
|
myself.fixLayout();
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
2015-07-21 13:06:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
ProjectDialogMorph.prototype.buildContents = function () {
|
|
|
|
var thumbnail, notification;
|
|
|
|
|
|
|
|
this.addBody(new Morph());
|
|
|
|
this.body.color = this.color;
|
|
|
|
|
|
|
|
this.srcBar = new AlignmentMorph('column', this.padding / 2);
|
|
|
|
|
|
|
|
if (this.ide.cloudMsg) {
|
|
|
|
notification = new TextMorph(
|
|
|
|
this.ide.cloudMsg,
|
|
|
|
10,
|
|
|
|
null, // style
|
|
|
|
false, // bold
|
|
|
|
null, // italic
|
|
|
|
null, // alignment
|
|
|
|
null, // width
|
|
|
|
null, // font name
|
|
|
|
new Point(1, 1), // shadow offset
|
|
|
|
new Color(255, 255, 255) // shadowColor
|
|
|
|
);
|
|
|
|
notification.refresh = nop;
|
|
|
|
this.srcBar.add(notification);
|
|
|
|
}
|
|
|
|
|
|
|
|
//disable cloud for now
|
2015-07-21 18:03:57 +00:00
|
|
|
// this.addSourceButton('cloud', localize('Cloud'), 'cloud');
|
2015-07-21 13:06:54 +00:00
|
|
|
this.addSourceButton('local', localize('Browser'), 'storage');
|
|
|
|
if (this.task === 'open') {
|
|
|
|
this.addSourceButton('examples', localize('Examples'), 'poster');
|
|
|
|
}
|
|
|
|
this.srcBar.fixLayout();
|
|
|
|
this.body.add(this.srcBar);
|
|
|
|
|
|
|
|
if (this.task === 'save') {
|
|
|
|
this.nameField = new InputFieldMorph(this.ide.projectName);
|
|
|
|
this.body.add(this.nameField);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.listField = new ListMorph([]);
|
|
|
|
this.fixListFieldItemColors();
|
|
|
|
this.listField.fixLayout = nop;
|
|
|
|
this.listField.edge = InputFieldMorph.prototype.edge;
|
|
|
|
this.listField.fontSize = InputFieldMorph.prototype.fontSize;
|
|
|
|
this.listField.typeInPadding = InputFieldMorph.prototype.typeInPadding;
|
|
|
|
this.listField.contrast = InputFieldMorph.prototype.contrast;
|
|
|
|
this.listField.drawNew = InputFieldMorph.prototype.drawNew;
|
|
|
|
this.listField.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
|
|
|
|
|
|
|
|
this.body.add(this.listField);
|
|
|
|
|
|
|
|
this.preview = new Morph();
|
|
|
|
this.preview.fixLayout = nop;
|
|
|
|
this.preview.edge = InputFieldMorph.prototype.edge;
|
|
|
|
this.preview.fontSize = InputFieldMorph.prototype.fontSize;
|
|
|
|
this.preview.typeInPadding = InputFieldMorph.prototype.typeInPadding;
|
|
|
|
this.preview.contrast = InputFieldMorph.prototype.contrast;
|
|
|
|
this.preview.drawNew = function () {
|
|
|
|
InputFieldMorph.prototype.drawNew.call(this);
|
|
|
|
if (this.texture) {
|
|
|
|
this.drawTexture(this.texture);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
this.preview.drawCachedTexture = function () {
|
|
|
|
var context = this.image.getContext('2d');
|
|
|
|
context.drawImage(this.cachedTexture, this.edge, this.edge);
|
|
|
|
this.changed();
|
|
|
|
};
|
|
|
|
this.preview.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
|
|
|
|
this.preview.setExtent(
|
|
|
|
this.ide.serializer.thumbnailSize.add(this.preview.edge * 2)
|
|
|
|
);
|
|
|
|
|
|
|
|
this.body.add(this.preview);
|
|
|
|
this.preview.drawNew();
|
|
|
|
if (this.task === 'save') {
|
|
|
|
thumbnail = this.ide.stage.thumbnail(
|
|
|
|
SnapSerializer.prototype.thumbnailSize
|
|
|
|
);
|
|
|
|
this.preview.texture = null;
|
|
|
|
this.preview.cachedTexture = thumbnail;
|
|
|
|
this.preview.drawCachedTexture();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.notesField = new ScrollFrameMorph();
|
|
|
|
this.notesField.fixLayout = nop;
|
|
|
|
|
|
|
|
this.notesField.edge = InputFieldMorph.prototype.edge;
|
|
|
|
this.notesField.fontSize = InputFieldMorph.prototype.fontSize;
|
|
|
|
this.notesField.typeInPadding = InputFieldMorph.prototype.typeInPadding;
|
|
|
|
this.notesField.contrast = InputFieldMorph.prototype.contrast;
|
|
|
|
this.notesField.drawNew = InputFieldMorph.prototype.drawNew;
|
|
|
|
this.notesField.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
|
|
|
|
|
|
|
|
this.notesField.acceptsDrops = false;
|
|
|
|
this.notesField.contents.acceptsDrops = false;
|
|
|
|
|
|
|
|
if (this.task === 'open') {
|
|
|
|
this.notesText = new TextMorph('');
|
|
|
|
} else { // 'save'
|
|
|
|
this.notesText = new TextMorph(this.ide.projectNotes);
|
|
|
|
this.notesText.isEditable = true;
|
|
|
|
this.notesText.enableSelecting();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.notesField.isTextLineWrapping = true;
|
|
|
|
this.notesField.padding = 3;
|
|
|
|
this.notesField.setContents(this.notesText);
|
|
|
|
this.notesField.setWidth(this.preview.width());
|
|
|
|
|
|
|
|
this.body.add(this.notesField);
|
|
|
|
|
|
|
|
if (this.task === 'open') {
|
|
|
|
this.addButton('openProject', 'Open');
|
|
|
|
this.action = 'openProject';
|
|
|
|
} else { // 'save'
|
|
|
|
this.addButton('saveProject', 'Save');
|
|
|
|
this.action = 'saveProject';
|
|
|
|
}
|
|
|
|
this.shareButton = this.addButton('shareProject', 'Share');
|
|
|
|
this.unshareButton = this.addButton('unshareProject', 'Unshare');
|
|
|
|
this.shareButton.hide();
|
|
|
|
this.unshareButton.hide();
|
|
|
|
this.deleteButton = this.addButton('deleteProject', 'Delete');
|
|
|
|
this.addButton('cancel', 'Cancel');
|
|
|
|
|
|
|
|
if (notification) {
|
|
|
|
this.setExtent(new Point(455, 335).add(notification.extent()));
|
|
|
|
} else {
|
|
|
|
this.setExtent(new Point(455, 335));
|
|
|
|
}
|
|
|
|
this.fixLayout();
|
|
|
|
|
|
|
|
};
|
|
|
|
|