resolve merge conflict

snap7
Michael Ball 2021-05-24 19:09:33 -10:00
commit 221b46bd02
6 zmienionych plików z 268 dodań i 186 usunięć

Wyświetl plik

@ -8,6 +8,33 @@
* **Notable Fixes:**
* made scrollbars in the wardrobe and jukebox more responsive
### 2021-05-21
* gui, scenes, store: proxied thumbnail, name and notes in project, restored in XML
* gui: distinguished project name from scene names, removed hidden "export as plain text" option
* gui: sceneified project notes
* gui: adjusted project thumbnail in "save" dialog
* gui: some cleanups
* gui, scenes: sceneified unsaved changes management
* blocks: fixed search-blocks for scenesMenu
### 2021-05-20
* gui: marked projectName to be refactored and sceneified
### 2021-05-19
* gui: disabled scene icon context menu for project scene
* gui: disabled dragging the project scene icon
* gui: made sure the project scene stays in place
* gui: added exporting single scenes
* scenes, store: removed redundant properties "notes" and "thumbnail" from project
* store: removed "thumbnail" property from scene xml
### 2021-05-18
* gui: fixed exporting media only for a single scene
* gui: fixed cloud file format components
* gui: "projectized" cloud file format for a single scene
* gui: fixed cloud file format for multi-scene projects
* gui: ensured unique scene names
### 2021-05-11
* gui: add multi-scene projects
* gui: adjusted scene album rendering

Wyświetl plik

@ -8,11 +8,11 @@
<script src="src/morphic.js?version=2021-04-12"></script>
<script src="src/symbols.js?version=2021-03-03"></script>
<script src="src/widgets.js?version=2021-01-05"></script>
<script src="src/blocks.js?version=2021-04-12"></script>
<script src="src/blocks.js?version=2021-05-21"></script>
<script src="src/threads.js?version=2021-04-17"></script>
<script src="src/objects.js?version=2021-04-23"></script>
<script src="src/scenes.js?version=2021-04-23"></script>
<script src="src/gui.js?version=2021-05-11"></script>
<script src="src/scenes.js?version=2021-05-21"></script>
<script src="src/gui.js?version=2021-05-21"></script>
<script src="src/paint.js?version=2021-03-17"></script>
<script src="src/lists.js?version=2021-03-15"></script>
<script src="src/byob.js?version=2021-05-04"></script>
@ -21,7 +21,7 @@
<script src="src/video.js?version=2019-06-27"></script>
<script src="src/maps.js?version=2020-03-25"></script>
<script src="src/xml.js?version=2020-04-27"></script>
<script src="src/store.js?version=2021-04-23"></script>
<script src="src/store.js?version=2021-05-21"></script>
<script src="src/locale.js?version=2021-03-15"></script>
<script src="src/cloud.js?version=2021-02-04"></script>
<script src="src/api.js?version=2021-01-25"></script>

Wyświetl plik

@ -158,7 +158,7 @@ CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/
// Global stuff ////////////////////////////////////////////////////////
modules.blocks = '2021-April-12';
modules.blocks = '2021-May-21';
var SyntaxElementMorph;
var BlockMorph;
@ -9745,15 +9745,17 @@ InputSlotMorph.prototype.audioMenu = function (searching) {
};
InputSlotMorph.prototype.scenesMenu = function (searching) {
var scenes = this.parentThatIsA(IDE_Morph).scenes,
dict = {};
if (!searching && scenes.length() > 1) {
scenes.itemsArray().forEach(scn => {
if (scn.name) {
dict[scn.name] = scn.name;
}
});
var dict = {},
scenes;
if (!searching) {
scenes = this.parentThatIsA(IDE_Morph).scenes;
if (scenes.length() > 1) {
scenes.itemsArray().forEach(scn => {
if (scn.name) {
dict[scn.name] = scn.name;
}
});
}
}
dict['~'] = null;
dict.next = ['next'];

Wyświetl plik

@ -68,7 +68,7 @@
/*global modules, Morph, SpriteMorph, SyntaxElementMorph, Color, Cloud, Audio,
ListWatcherMorph, TextMorph, newCanvas, useBlurredShadows, Sound, Scene, Note,
StringMorph, Point, MenuMorph, morphicVersion, DialogBoxMorph, normalizeCanvas,
StringMorph, Point, MenuMorph, morphicVersion, DialogBoxMorph, BlockEditorMorph,
ToggleButtonMorph, contains, ScrollFrameMorph, StageMorph, PushButtonMorph, sb,
InputFieldMorph, FrameMorph, Process, nop, SnapSerializer, ListMorph, detect,
AlignmentMorph, TabMorph, Costume, MorphicPreferences,BlockMorph, ToggleMorph,
@ -79,11 +79,11 @@ CommandBlockMorph, BooleanSlotMorph, RingReporterSlotMorph, ScriptFocusMorph,
BlockLabelPlaceHolderMorph, SpeechBubbleMorph, XML_Element, WatcherMorph, WHITE,
BlockRemovalDialogMorph,TableMorph, isSnapObject, isRetinaEnabled, SliderMorph,
disableRetinaSupport, enableRetinaSupport, isRetinaSupported, MediaRecorder,
Animation, BoxMorph, BlockEditorMorph, BlockDialogMorph, Project, ZERO, BLACK*/
Animation, BoxMorph, BlockDialogMorph, Project, ZERO, BLACK*/
// Global stuff ////////////////////////////////////////////////////////
modules.gui = '2021-May-11';
modules.gui = '2021-May-21';
// Declarations
@ -248,8 +248,6 @@ IDE_Morph.prototype.init = function (isAutoFill) {
this.globalVariables = this.scene.globalVariables;
this.currentSprite = this.scene.addDefaultSprite();
this.sprites = this.scene.sprites;
this.projectName = this.scene.name;
this.projectNotes = this.scene.notes;
if (this.scene.unifiedPalette) {
this.currentCategory = 'unified';
} else {
@ -283,9 +281,7 @@ IDE_Morph.prototype.init = function (isAutoFill) {
this.filePicker = null;
// incrementally saving projects to the cloud is currently unused
this.hasChangedMedia = false;
this.hasUnsavedEdits = false; // keeping track of when to internally backup
this.hasChangedMedia = false; // +++ sceneify, or get of it
this.isAnimating = true;
this.paletteWidth = 200; // initially same as logo width
@ -1181,7 +1177,7 @@ IDE_Morph.prototype.createControlBar = function () {
};
this.controlBar.updateLabel = function () {
var prefix = myself.hasUnsavedEdits ? '\u270E ' : '',
var prefix = myself.hasUnsavedEdits() ? '\u270E ' : '',
suffix = myself.world().isDevMode ?
' - ' + localize('development mode') : '',
txt;
@ -1193,7 +1189,7 @@ IDE_Morph.prototype.createControlBar = function () {
return;
}
txt = new StringMorph(
prefix + (myself.projectName || localize('untitled')) + suffix,
prefix + (myself.scene.name || localize('untitled')) + suffix,
14,
'sans-serif',
true,
@ -1941,17 +1937,17 @@ IDE_Morph.prototype.createCorral = function (keepSceneAlbum) {
this.corral.frame = frame;
this.corral.add(frame);
// scenes ++++
// scenes corral
this.corral.album = keepSceneAlbum ? album
: new SceneAlbumMorph(this, this.sliderColor);
this.corral.album.color = this.frameColor; // this.groupColor;
this.corral.album.color = this.frameColor;
this.corral.add(this.corral.album);
this.corral.fixLayout = function () {
this.stageIcon.setCenter(this.center());
this.stageIcon.setLeft(this.left() + padding);
// scenes +++
// scenes
if (myself.scenes.length() < 2) {
this.album.hide();
} else {
@ -1960,7 +1956,9 @@ IDE_Morph.prototype.createCorral = function (keepSceneAlbum) {
this.album.setLeft(this.left());
this.album.setTop(this.stageIcon.bottom() + padding);
this.album.setWidth(this.stageIcon.width() + padding * 2);
this.album.setHeight(this.height() - this.stageIcon.height() - padding); // +++
this.album.setHeight(
this.height() - this.stageIcon.height() - padding
);
}
this.frame.setLeft(this.stageIcon.right() + padding);
@ -2130,10 +2128,40 @@ IDE_Morph.prototype.fixLayout = function (situation) {
}
};
// IDE_Morph project properties
IDE_Morph.prototype.getProjectName = function () {
return this.scenes.at(1).name;
};
IDE_Morph.prototype.setProjectName = function (string) {
this.projectName = string.replace(/['"]/g, ''); // filter quotation marks
this.hasChangedMedia = true;
this.controlBar.updateLabel();
var projectScene = this.scenes.at(1),
name = this.newSceneName(string, projectScene);
if (name !== projectScene.name) {
projectScene.name = name;
projectScene.stage.version = Date.now();
this.recordUnsavedChanges(); // +++ sceneify this
if (projectScene === this.scene) {
this.controlBar.updateLabel();
}
}
return name;
};
IDE_Morph.prototype.getProjectNotes = function () {
return this.scenes.at(1).notes;
};
IDE_Morph.prototype.setProjectNotes = function (string) {
var projectScene = this.scenes.at(1);
if (string !== projectScene.notes) {
projectScene.notes = string;
projectScene.stage.version = Date.now();
this.recordUnsavedChanges(); // +++ sceneify this
if (projectScene === this.scene) {
this.controlBar.updateLabel();
}
}
};
// IDE_Morph resizing
@ -2783,13 +2811,17 @@ IDE_Morph.prototype.hasLocalStorage = function () {
// IDE_Morph recording unsaved changes
IDE_Morph.prototype.hasUnsavedEdits = function () {
return this.scenes.itemsArray().some(any => any.hasUnsavedEdits);
};
IDE_Morph.prototype.recordUnsavedChanges = function () {
this.hasUnsavedEdits = true;
this.scene.hasUnsavedEdits = true;
this.updateChanges();
};
IDE_Morph.prototype.recordSavedChanges = function () {
this.hasUnsavedEdits = false;
this.scenes.itemsArray().forEach(scene => scene.hasUnsavedEdits = false);
this.updateChanges();
};
@ -2813,7 +2845,7 @@ IDE_Morph.prototype.backup = function (callback) {
// Save the current project for the currently logged in user
// to localstorage, then perform the given callback, e.g.
// load a new project.
if (this.hasUnsavedEdits) {
if (this.hasUnsavedEdits()) {
this.confirm(
'Replace the current project with a new one?',
'Unsaved Changes!',
@ -3229,6 +3261,14 @@ IDE_Morph.prototype.newSpriteName = function (name, ignoredSprite) {
return this.newName(name, all);
};
IDE_Morph.prototype.newSceneName = function (name, ignoredScene) {
var sName = name.replace(/['"]/g, ''), // filter out quotation marks
all = this.scenes.asArray().filter(each =>
each !== ignoredScene
).map(each => each.name);
return this.newName(sName, all);
};
IDE_Morph.prototype.newName = function (name, elements) {
var ix = name.indexOf('('),
stem = (ix < 0) ? name : name.substring(0, ix),
@ -3372,8 +3412,9 @@ IDE_Morph.prototype.cloudMenu = function () {
menu.addItem(
'export project media only...',
() => {
if (this.projectName) {
this.exportProjectMedia(this.projectName);
var pn = this.getProjectName();
if (pn) {
this.exportProjectMedia(pn);
} else {
this.prompt(
'Export Project As...',
@ -3389,8 +3430,9 @@ IDE_Morph.prototype.cloudMenu = function () {
menu.addItem(
'export project without media...',
() => {
if (this.projectName) {
this.exportProjectNoMedia(this.projectName);
var pn = this.getProjectName();
if (pn) {
this.exportProjectNoMedia(pn);
} else {
this.prompt(
'Export Project As...',
@ -3406,8 +3448,9 @@ IDE_Morph.prototype.cloudMenu = function () {
menu.addItem(
'export project as cloud data...',
() => {
if (this.projectName) {
this.exportProjectAsCloudData(this.projectName);
var pn = this.getProjectName();
if (pn) {
this.exportProjectAsCloudData(pn);
} else {
this.prompt(
'Export Project As...',
@ -3984,10 +4027,7 @@ IDE_Morph.prototype.projectMenu = function () {
backup = this.availableBackup(shiftClicked);
menu = new MenuMorph(this);
if (this.scenes.length() > 1) {
menu.addItem('Scenes...', 'scenesMenu');
}
menu.addItem('Project notes...', 'editProjectNotes');
menu.addItem('Notes...', 'editNotes');
menu.addLine();
menu.addPair('New', 'createNewProject', '^N');
menu.addPair('Open...', 'openProjectsBrowser', '^O');
@ -4015,46 +4055,22 @@ IDE_Morph.prototype.projectMenu = function () {
'importLocalFile',
'file menu import hint' // looks up the actual text in the translator
);
if (shiftClicked) {
menu.addItem(
localize(
'Export project...') + ' ' + localize('(in a new window)'
),
() => {
if (this.projectName) {
this.exportProject(this.projectName, shiftClicked);
} else {
this.prompt(
'Export Project As...',
// false - override the shiftClick setting to use XML:
name => this.exportProject(name, false),
null,
'exportProject'
);
}
},
'show project data as XML\nin a new browser window',
new Color(100, 0, 0)
);
}
menu.addItem(
shiftClicked ?
'Export project as plain text...' : 'Export project...',
'Export project...',
() => {
if (this.projectName) {
this.exportProject(this.projectName, shiftClicked);
var pn = this.getProjectName();
if (pn) {
this.exportProject(pn);
} else {
this.prompt(
'Export Project As...',
name => this.exportProject(name, shiftClicked),
name => this.exportProject(name),
null,
'exportProject'
);
}
},
'save project data as XML\nto your downloads folder',
shiftClicked ? new Color(100, 0, 0) : null
'save project data as XML\nto your downloads folder'
);
if (this.stage.globalBlocks.length) {
@ -4095,12 +4111,12 @@ IDE_Morph.prototype.projectMenu = function () {
);
}
// +++
menu.addLine();
if (this.scenes.length() > 1) {
menu.addItem('Scenes...', 'scenesMenu');
}
menu.addPair('New scene', 'createNewScene');
menu.addPair('Add scene...', 'addScene');
// +++
menu.addLine();
menu.addItem(
'Libraries...',
@ -4682,10 +4698,10 @@ IDE_Morph.prototype.scenesMenu = function () {
menu.popup(world, pos);
};
IDE_Morph.prototype.editProjectNotes = function () {
var dialog = new DialogBoxMorph().withKey('projectNotes'),
IDE_Morph.prototype.editNotes = function () {
var dialog = new DialogBoxMorph().withKey('notes'),
frame = new ScrollFrameMorph(),
text = new TextMorph(this.projectNotes || ''),
text = new TextMorph(this.scene.notes || ''),
size = 250,
world = this.world();
@ -4715,13 +4731,13 @@ IDE_Morph.prototype.editProjectNotes = function () {
dialog.target = this;
dialog.action = (note) => {
this.projectNotes = note;
this.recordUnsavedChanges();
this.scene.notes = note;
this.recordUnsavedChanges(); // +++ sceneify this
};
dialog.justDropped = () => text.edit();
dialog.labelString = 'Project Notes';
dialog.labelString = 'Notes';
dialog.createLabel();
dialog.addBody(frame);
dialog.addButton('ok', 'OK');
@ -4743,7 +4759,7 @@ IDE_Morph.prototype.newProject = function () {
this.openProject(project);
};
IDE_Morph.prototype.createNewScene = function () { // +++
IDE_Morph.prototype.createNewScene = function () {
var setting = this.isAddingScenes;
this.isAddingScenes = true;
this.newProject();
@ -4753,13 +4769,14 @@ IDE_Morph.prototype.createNewScene = function () { // +++
IDE_Morph.prototype.save = function () {
// temporary hack - only allow exporting projects to disk
// when running Snap! locally without a web server
var pn = this.getProjectName();
if (location.protocol === 'file:') {
if (this.projectName) {
this.exportProject(this.projectName, false);
if (pn) {
this.exportProject(pn);
} else {
this.prompt(
'Export Project As...',
name => this.exportProject(name, false),
name => this.exportProject(name),
null,
'exportProject'
);
@ -4774,11 +4791,11 @@ IDE_Morph.prototype.save = function () {
if (this.cloud.disabled) {this.source = 'disk'; }
if (this.projectName) {
if (pn) {
if (this.source === 'disk') {
this.exportProject(this.projectName);
this.exportProject(pn);
} else if (this.source === 'cloud') {
this.saveProjectToCloud(this.projectName);
this.saveProjectToCloud(pn);
} else {
this.saveProjectsBrowser();
}
@ -4787,22 +4804,17 @@ IDE_Morph.prototype.save = function () {
}
};
IDE_Morph.prototype.exportProject = function (name, plain) {
IDE_Morph.prototype.exportProject = function (name) {
// Export project XML, saving a file to disk
// newWindow requests displaying the project in a new tab.
var menu, str, dataPrefix;
name = this.scenes.at(1).name; // +++
var menu, str;
if (name) {
this.setProjectName(name);
dataPrefix = 'data:text/' + plain ? 'plain,' : 'xml,';
name = this.setProjectName(name);
try {
menu = this.showMessage('Exporting');
str = this.serializer.serialize(
new Project(this.scenes, this.scene)
);
this.setURL('#open:' + dataPrefix + encodeURIComponent(str));
this.setURL('#open:data:text/xml,' + encodeURIComponent(str));
this.saveXMLAs(str, name);
menu.destroy();
this.recordSavedChanges();
@ -4928,7 +4940,7 @@ IDE_Morph.prototype.exportScriptsPicture = function () {
y += padding;
y += each.height;
});
this.saveCanvasAs(pic, this.projectName || localize('Untitled'));
this.saveCanvasAs(pic, this.scene.name || localize('Untitled'));
};
IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
@ -5031,7 +5043,7 @@ IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
}
}
pname = this.projectName || localize('untitled');
pname = this.scene.name || localize('untitled');
html = new XML_Element('html');
html.attributes.lang = SnapTranslator.language;
@ -5092,7 +5104,7 @@ IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
}
// project notes
notes = Process.prototype.reportTextSplit(this.projectNotes, 'line');
notes = Process.prototype.reportTextSplit(this.scene.notes, 'line');
notes.asArray().forEach(paragraph => add(paragraph));
// table of contents
@ -5212,7 +5224,7 @@ IDE_Morph.prototype.exportProjectSummary = function (useDropShadows) {
IDE_Morph.prototype.openProjectString = function (str, callback) {
var msg;
if (this.bulkDropInProgress || this.isAddingScenes) { // +++
if (this.bulkDropInProgress || this.isAddingScenes) {
this.rawOpenProjectString(str);
if (callback) {callback(); }
return;
@ -5260,7 +5272,7 @@ IDE_Morph.prototype.openCloudDataString = function (str) {
IDE_Morph.prototype.rawOpenCloudDataString = function (str) {
var model,
setting = this.isAddingScenes; // +++
setting = this.isAddingScenes;
if (this.isAddingNextScene) {
this.isAddingScenes = true;
@ -5484,7 +5496,10 @@ IDE_Morph.prototype.openProjectName = function (name) {
IDE_Morph.prototype.openProject = function (project) {
if (this.isAddingScenes) {
project.scenes.itemsArray().forEach(scene => this.scenes.add(scene));
project.scenes.itemsArray().forEach(scene => {
scene.name = this.newSceneName(scene.name, scene);
this.scenes.add(scene);
});
} else {
this.scenes = project.scenes;
}
@ -5503,8 +5518,6 @@ IDE_Morph.prototype.switchToScene = function (scene, refreshAlbum) {
);
this.scene.captureGlobalSettings();
this.scene = scene;
this.projectName = scene.name;
this.projectNotes = scene.notes || '';
this.globalVariables = scene.globalVariables;
this.stage.destroy();
this.add(scene.stage);
@ -5521,7 +5534,6 @@ IDE_Morph.prototype.switchToScene = function (scene, refreshAlbum) {
}
});
scene.applyGlobalSettings();
this.hasUnsavedEdits = false;
this.world().keyboardFocus = this.stage;
};
@ -5978,7 +5990,7 @@ IDE_Morph.prototype.createNewProject = function () {
this.backup(() => this.newProject());
};
IDE_Morph.prototype.addScene = function () { // +++
IDE_Morph.prototype.addScene = function () {
var setting = this.isAddingScenes;
if (location.protocol === 'file:') {
// bypass the project import dialog and directly pop up
@ -6013,7 +6025,7 @@ IDE_Morph.prototype.saveProjectsBrowser = function () {
if (location.protocol === 'file:') {
this.prompt(
'Export Project As...',
name => this.exportProject(name, false),
name => this.exportProject(name),
null,
'exportProject'
);
@ -6574,22 +6586,23 @@ IDE_Morph.prototype.logout = function () {
);
};
IDE_Morph.prototype.buildProjectRequest = function () { // +++ Oh, sweet Jesus!
var xml = this.serializer.serialize(this.scene),
thumbnail = normalizeCanvas(
this.stage.thumbnail(
SnapSerializer.prototype.thumbnailSize
)).toDataURL(),
body;
IDE_Morph.prototype.buildProjectRequest = function () {
var proj = new Project(this.scenes, this.scene),
body,
xml;
this.serializer.isCollectingMedia = true;
xml = this.serializer.serialize(proj);
body = {
notes: this.projectNotes,
notes: proj.notes,
xml: xml,
media: this.hasChangedMedia ?
this.serializer.mediaXML(this.projectName) : null,
thumbnail: thumbnail,
remixID: this.stage.remixID
/*
media: this.hasChangedMedia ? // incremental media upload, disabled
this.serializer.mediaXML(proj.name) : null,
*/
media: this.serializer.mediaXML(proj.name),
thumbnail: proj.thumbnail.toDataURL(),
remixID: this.stage.remixID // +++ sceneify remixID
};
this.serializer.isCollectingMedia = false;
this.serializer.flushMedia();
@ -6637,7 +6650,7 @@ IDE_Morph.prototype.saveProjectToCloud = function (name) {
var projectBody, projectSize;
if (name) {
this.setProjectName(name);
name = this.setProjectName(name);
}
this.showMessage('Saving project\nto the cloud...');
@ -6648,7 +6661,7 @@ IDE_Morph.prototype.saveProjectToCloud = function (name) {
'Uploading ' + Math.round(projectSize / 1024) + ' KB...'
);
this.cloud.saveProject(
this.projectName,
name,
projectBody,
() => {
this.recordSavedChanges();
@ -6665,8 +6678,9 @@ IDE_Morph.prototype.exportProjectMedia = function (name) {
this.setProjectName(name);
try {
menu = this.showMessage('Exporting');
this.serializer.serialize(new Project(this.scenes, this.scene));
media = this.serializer.mediaXML(name);
this.saveXMLAs(media, this.projectName + ' media');
this.saveXMLAs(media, this.getProjectName() + ' media');
menu.destroy();
this.showMessage('Exported!', 1);
} catch (err) {
@ -6683,16 +6697,18 @@ IDE_Morph.prototype.exportProjectMedia = function (name) {
// this.hasChangedMedia = false;
};
IDE_Morph.prototype.exportProjectNoMedia = function (name) { // +++ Sigh...
IDE_Morph.prototype.exportProjectNoMedia = function (name) {
var menu, str;
this.serializer.isCollectingMedia = true;
if (name) {
this.setProjectName(name);
name = this.setProjectName(name);
if (Process.prototype.isCatchingErrors) {
try {
menu = this.showMessage('Exporting');
str = this.serializer.serialize(this.scene);
this.saveXMLAs(str, this.projectName);
str = this.serializer.serialize(
new Project(this.scenes, this.scene)
);
this.saveXMLAs(str, name);
menu.destroy();
this.showMessage('Exported!', 1);
} catch (err) {
@ -6701,8 +6717,10 @@ IDE_Morph.prototype.exportProjectNoMedia = function (name) { // +++ Sigh...
}
} else {
menu = this.showMessage('Exporting');
str = this.serializer.serialize(this.scene);
this.saveXMLAs(str, this.projectName);
str = this.serializer.serialize(
new Project(this.scenes, this.scene)
);
this.saveXMLAs(str, name);
menu.destroy();
this.showMessage('Exported!', 1);
}
@ -6711,18 +6729,20 @@ IDE_Morph.prototype.exportProjectNoMedia = function (name) { // +++ Sigh...
this.serializer.flushMedia();
};
IDE_Morph.prototype.exportProjectAsCloudData = function (name) { // +++ revisit
IDE_Morph.prototype.exportProjectAsCloudData = function (name) {
var menu, str, media, dta;
this.serializer.isCollectingMedia = true;
if (name) {
this.setProjectName(name);
name = this.setProjectName(name);
if (Process.prototype.isCatchingErrors) {
try {
menu = this.showMessage('Exporting');
str = this.serializer.serialize(this.scene);
str = this.serializer.serialize(
new Project(this.scenes, this.scene)
);
media = this.serializer.mediaXML(name);
dta = '<snapdata>' + str + media + '</snapdata>';
this.saveXMLAs(str, this.projectName);
this.saveXMLAs(dta, name);
menu.destroy();
this.showMessage('Exported!', 1);
} catch (err) {
@ -6731,10 +6751,12 @@ IDE_Morph.prototype.exportProjectAsCloudData = function (name) { // +++ revisit
}
} else {
menu = this.showMessage('Exporting');
str = this.serializer.serialize(this.scene);
str = this.serializer.serialize(
new Project(this.scenes, this.scene)
);
media = this.serializer.mediaXML(name);
dta = '<snapdata>' + str + media + '</snapdata>';
this.saveXMLAs(str, this.projectName);
this.saveXMLAs(str, name);
menu.destroy();
this.showMessage('Exported!', 1);
}
@ -7097,7 +7119,7 @@ ProjectDialogMorph.prototype.buildContents = function () {
this.body.add(this.srcBar);
if (this.task === 'save') {
this.nameField = new InputFieldMorph(this.ide.projectName);
this.nameField = new InputFieldMorph(this.ide.getProjectName());
this.body.add(this.nameField);
}
@ -7137,7 +7159,7 @@ ProjectDialogMorph.prototype.buildContents = function () {
this.body.add(this.preview);
if (this.task === 'save') {
thumbnail = this.ide.stage.thumbnail(
thumbnail = this.ide.scenes.at(1).stage.thumbnail(
SnapSerializer.prototype.thumbnailSize
);
this.preview.texture = null;
@ -7161,7 +7183,7 @@ ProjectDialogMorph.prototype.buildContents = function () {
if (this.task === 'open' || this.task === 'add') {
this.notesText = new TextMorph('');
} else { // 'save'
this.notesText = new TextMorph(this.ide.projectNotes);
this.notesText = new TextMorph(this.ide.getProjectNotes());
this.notesText.isEditable = true;
this.notesText.enableSelecting();
}
@ -7698,7 +7720,7 @@ ProjectDialogMorph.prototype.recoveryDialog = function () {
new ProjectRecoveryDialogMorph(this.ide, proj.projectname, this).popUp();
};
ProjectDialogMorph.prototype.addScene = function () { // +++
ProjectDialogMorph.prototype.addScene = function () {
var proj = this.listField.selected,
src;
if (!proj) {return; }
@ -7784,8 +7806,8 @@ ProjectDialogMorph.prototype.saveProject = function () {
var name = this.nameField.contents().text.text,
notes = this.notesText.text;
if (this.ide.projectNotes !== notes) {
this.ide.projectNotes = notes;
if (this.ide.getProjectNotes() !== notes) {
this.ide.setProjectNotes(notes);
}
if (name) {
if (this.source === 'cloud') {
@ -7808,7 +7830,7 @@ ProjectDialogMorph.prototype.saveProject = function () {
this.saveCloudProject();
}
} else if (this.source === 'disk') {
this.ide.exportProject(name, false);
this.ide.exportProject(name);
this.ide.source = 'disk';
this.destroy();
}
@ -7895,7 +7917,7 @@ ProjectDialogMorph.prototype.shareProject = function () {
this.ide.showMessage('shared.', 2);
// Set the Shared URL if the project is currently open
if (proj.projectname === ide.projectName) {
if (proj.projectname === ide.getProjectName()) {
var usr = ide.cloud.username,
projectId = 'Username=' +
encodeURIComponent(usr.toLowerCase()) +
@ -7939,7 +7961,7 @@ ProjectDialogMorph.prototype.unshareProject = function () {
this.buttons.fixLayout();
this.rerender();
this.ide.showMessage('unshared.', 2);
if (proj.projectname === ide.projectName) {
if (proj.projectname === ide.getProjectName()) {
location.hash = '';
}
},
@ -7979,7 +8001,7 @@ ProjectDialogMorph.prototype.publishProject = function () {
this.ide.showMessage('published.', 2);
// Set the Shared URL if the project is currently open
if (proj.projectname === ide.projectName) {
if (proj.projectname === ide.getProjectName()) {
var usr = ide.cloud.username,
projectId = 'Username=' +
encodeURIComponent(usr.toLowerCase()) +
@ -10253,7 +10275,7 @@ SceneIconMorph.uber = ToggleButtonMorph.prototype;
// SceneIconMorph settings
SceneIconMorph.prototype.thumbSize = new Point(40, 30); // +++ (40, 40), (80, 60);
SceneIconMorph.prototype.thumbSize = new Point(40, 30);
SceneIconMorph.prototype.labelShadowOffset = null;
SceneIconMorph.prototype.labelShadowColor = null;
SceneIconMorph.prototype.labelColor = WHITE;
@ -10302,7 +10324,7 @@ SceneIconMorph.prototype.init = function (aScene) {
colors, // color overrides, <array>: [normal, highlight, pressed]
null, // target - not needed here
action, // a toggle function
this.object.name || localize('untitled'), // label string // +++
this.object.name || localize('untitled'), // label string
query, // predicate/selector
null, // environment
null // hint
@ -10332,12 +10354,7 @@ SceneIconMorph.prototype.createThumbnail = function () {
this.add(this.thumbnail);
};
/* +++
SceneIconMorph.prototype.createLabel
= SpriteIconMorph.prototype.createLabel;
*/
SceneIconMorph.prototype.createLabel = function () { // +++
SceneIconMorph.prototype.createLabel = function () {
var txt;
if (this.label) {
@ -10384,31 +10401,34 @@ SceneIconMorph.prototype.fixLayout
// SceneIconMorph menu
SceneIconMorph.prototype.userMenu = function () {
var menu = new MenuMorph(this),
ide = this.parentThatIsA(IDE_Morph);
if (!(this.object instanceof Scene)) {return null; }
menu.addItem("rename", "renameScene");
if (ide.scenes.length() > 1) {
var menu = new MenuMorph(this);
if (!(this.object instanceof Scene)) {
return null;
}
if (!this.isProjectScene()) {
menu.addItem("rename", "renameScene");
menu.addItem("delete", "removeScene");
}
// menu.addItem("export", "exportScene");
menu.addItem("export", "exportScene");
return menu;
};
SceneIconMorph.prototype.renameScene = function () {
var scene = this.object,
album = this.parentThatIsA(SceneAlbumMorph),
ide = this.parentThatIsA(IDE_Morph);
new DialogBoxMorph(
null,
answer => {
if (answer && (answer !== scene.name)) {
scene.name = album.scene.newSceneName(
scene.name = ide.newSceneName(
answer,
scene
);
scene.stage.version = Date.now(); // +++ also do this in other places
ide.recordUnsavedChanges();
if (scene === ide.scene) {
ide.controlBar.updateLabel();
}
ide.recordUnsavedChanges(); // ++++ sceneify unsaved changes
}
}
).prompt(
@ -10430,9 +10450,35 @@ SceneIconMorph.prototype.removeScene = function () {
};
SceneIconMorph.prototype.exportScene = function () {
// under construction
var ide = this.parentThatIsA(IDE_Morph);
ide.saveFileAs(this.object.contents.src, 'text/svg', this.object.name);
// Export scene as project XML, saving a file to disk
var menu, str,
ide = this.parentThatIsA(IDE_Morph),
name = this.object.name || localize('untitled');
try {
menu = ide.showMessage('Exporting');
str = ide.serializer.serialize(
new Project(new List([this.object]), this.object)
);
ide.saveXMLAs(str, name);
menu.destroy();
ide.showMessage('Exported!', 1);
} catch (err) {
if (Process.prototype.isCatchingErrors) {
ide.showMessage('Export failed: ' + err);
} else {
throw err;
}
}
};
// SceneIconMorph ops
SceneIconMorph.prototype.isProjectScene = function (anIDE) {
// the first scene of a project cannot be renamed, deleted or rearranged,
// because its name and project notes are those of the project
var ide = anIDE || this.parentThatIsA(IDE_Morph);
return ide.scenes.indexOf(this.object) === 1;
};
// SceneIconMorph drawing
@ -10443,8 +10489,6 @@ SceneIconMorph.prototype.render
// SceneIconMorph drag & drop
SceneIconMorph.prototype.rootForGrab = function () {
// +++ to do: make sure scene icons can only be grabbed if there are
// more than 1
return this;
};
@ -10503,8 +10547,11 @@ SceneAlbumMorph.prototype.updateList = function () {
};
this.addBack(this.contents);
this.ide.scenes.asArray().forEach(scene => {
this.ide.scenes.asArray().forEach((scene, i) => {
icon = new SceneIconMorph(scene);
if (i < 1) {
icon.isDraggable = false; // project scene cannot be rearranged
}
icon.setPosition(new Point(x, y));
this.addContents(icon);
y = icon.bottom() + padding;
@ -10561,6 +10608,7 @@ SceneAlbumMorph.prototype.reactToDropOf = function (icon) {
idx += 1;
}
});
idx = Math.max(idx, 1); // the project scene cannot the rearranged
this.ide.scenes.add(scene, idx + 1);
this.updateList();
icon.mouseClickLeft(); // select

Wyświetl plik

@ -48,9 +48,10 @@
// Global stuff ////////////////////////////////////////////////////////
/*global modules, VariableFrame, StageMorph, SpriteMorph, Process, List*/
/*global modules, VariableFrame, StageMorph, SpriteMorph, Process, List,
normalizeCanvas, SnapSerializer*/
modules.scenes = '2021-April-23';
modules.scenes = '2021-May-21';
// Projecct /////////////////////////////////////////////////////////
@ -61,12 +62,25 @@ modules.scenes = '2021-April-23';
// Project instance creation:
function Project(scenes, current) {
this.name = 'Test';
this.notes = 'some notes';
this.thumbnail = null;
var projectScene;
this.scenes = scenes || new List();
this.currentScene = current;
// proxied for display
this.name = null;
this.notes = null;
this.thumbnail = null;
projectScene = this.scenes.at(1);
if (projectScene) {
this.name = projectScene.name;
this.notes = projectScene.notes;
this.thumbnail = normalizeCanvas(
projectScene.stage.thumbnail(SnapSerializer.prototype.thumbnailSize)
);
}
// for deserializing - do not persist
this.sceneIdx = null;
@ -102,6 +116,7 @@ function Scene(aStageMorph) {
this.globalVariables = aStageMorph ?
aStageMorph.globalVariables() : new VariableFrame();
this.stage = aStageMorph || new StageMorph(this.globalVariables);
this.hasUnsavedEdits = false;
// cached IDE state
this.sprites = new List();

Wyświetl plik

@ -61,7 +61,7 @@ Project*/
// Global stuff ////////////////////////////////////////////////////////
modules.store = '2021-April-23';
modules.store = '2021-May-21';
// XML_Serializer ///////////////////////////////////////////////////////
@ -1672,7 +1672,6 @@ Project.prototype.toXML = function (serializer) {
Scene.prototype.toXML = function (serializer) {
var tmp = new Scene(),
thumbdata,
xml;
function code(key) {
@ -1691,19 +1690,11 @@ Scene.prototype.toXML = function (serializer) {
return str;
}
// catch cross-origin tainting exception when using SVG costumes
try {
thumbdata = this.thumbnail.toDataURL('image/png');
} catch (error) {
thumbdata = null;
}
tmp.captureGlobalSettings();
this.applyGlobalSettings();
xml = serializer.format(
'<scene name="@">' +
'<notes>$</notes>' +
'<thumbnail>$</thumbnail>' +
'<hidden>$</hidden>' +
'<headers>%</headers>' +
'<code>%</code>' +
@ -1713,7 +1704,6 @@ Scene.prototype.toXML = function (serializer) {
'</scene>',
this.name || localize('Untitled'),
this.notes || '',
thumbdata,
Object.keys(StageMorph.prototype.hiddenPrimitives).reduce(
(a, b) => a + ' ' + b,
''