Merge branch 'master' into vector-edit

pull/89/head
Brian Harvey 2019-02-20 22:29:39 -08:00 zatwierdzone przez GitHub
commit 7287a3c2fa
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
9 zmienionych plików z 445 dodań i 27 usunięć

Wyświetl plik

@ -13,6 +13,7 @@
* blocks for changing and querying the "flat line ends" setting
* selectors for changing and querying "draggable" and "rotation style" settings
* special context-aware drop-downs for custom blocks
* new "stick to" submenu in the sprite context menu where applicable
* multi-line and monospaced "code" input slots for custom blocks
* new "string" library, thanks, Brian
* added "neg" selector to monadic function reporter in "Operators" category
@ -27,6 +28,7 @@
* remove all clones when the Green Flag is clicked
* adjust bottom of STOP block to reflect the menu selection (show / hide bottom notch)
* enable dropping commands into all rings
* colors in the vector editor are now named "Edge color" and "Fill color", thanks, Brian!
* Notable Fixes:
* "relabel" blocks with translated drop-down choices
* transforming arrayed to linked lists without loosing the last element
@ -39,6 +41,20 @@
* Greek, thanks, Alexandros!
* German
### 2019-02-21
* Blocks: fixed deleting a single command inside a stack
### 2019-02-20
* Tweaked German translation
* Vector editor color name changes, thanks, Brian!
### 2019-02-19
* Threads: fixed #2332. I hate it. It's fixes like this that bog Snap! down.
* Udated German translation
### 2019-02-18
* Objects: enable sprite nesting via the context menu
### 2019-02-15
* BYOB: tweaked yesterday's fix...
* Blocks: fixed a glitch in the custom block help mechanism (show only the prototype)

Wyświetl plik

@ -185,7 +185,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org, jadga.huegle@sap.com', // optional
'last_changed':
'2019-01-28', // this, too, will appear in the Translators tab
'2019-02-19', // this, too, will appear in the Translators tab
// GUI
// control bar:
@ -1065,6 +1065,8 @@ SnapTranslator.dict.de = {
'Drehpunkt des Kostüms\nanzeigen und verschieben',
'rotate':
'Drehen',
'stick to':
'Befestigen an',
'detach from':
'Abtrennen von',
'detach all parts':
@ -1279,8 +1281,10 @@ SnapTranslator.dict.de = {
'fülle einen Bereich mit der gewählten Farbe\n(Shift: Sekundärfarbe)',
'Pipette tool\n(pick a color from anywhere\nshift: secondary color)':
'Pipette\nklicke irgendwo auf die gewünschte Farbe\n um sie aufzunehmen (Shift: Sekundärfarbe)',
'Primary color Secondary color':
'Primärfarbe Sekundärfarbe',
'Edge color\n(left click)':
'Randfarbe\n(Linksklick)',
'Fill color\n(rigth click)':
'Füllfarbe\n(Rechtsklick)',
// 'Top':
// 'oben',
// 'Bottom':

Wyświetl plik

@ -6,20 +6,20 @@
<link rel="shortcut icon" href="src/favicon.ico">
<script type="text/javascript" src="src/morphic.js?version=2019-02-07"></script>
<script type="text/javascript" src="src/widgets.js?version=2018-10-02"></script>
<script type="text/javascript" src="src/blocks.js?version=2019-02-15"></script>
<script type="text/javascript" src="src/threads.js?version=2019-01-28"></script>
<script type="text/javascript" src="src/objects.js?version=2019-02-07"></script>
<script type="text/javascript" src="src/gui.js?version=2019-02-07"></script>
<script type="text/javascript" src="src/blocks.js?version=2019-02-21"></script>
<script type="text/javascript" src="src/threads.js?version=2019-02-19"></script>
<script type="text/javascript" src="src/objects.js?version=2019-02-18"></script>
<script type="text/javascript" src="src/gui.js?version=2019-02-20"></script>
<script type="text/javascript" src="src/paint.js?version=2018-10-02"></script>
<script type="text/javascript" src="src/lists.js?version=2019-02-07"></script>
<script type="text/javascript" src="src/byob.js?version=2019-02-15"></script>
<script type="text/javascript" src="src/tables.js?version=2019-02-07"></script>
<script type="text/javascript" src="src/symbols.js?version=2019-01-14"></script>
<script type="text/javascript" src="src/sketch.js?version=2018-10-02"></script>
<script type="text/javascript" src="src/sketch.js?version=2019-02-20"></script>
<script type="text/javascript" src="src/xml.js?version=2018-11-12"></script>
<script type="text/javascript" src="src/store.js?version=2019-02-07"></script>
<script type="text/javascript" src="src/locale.js?version=2019-01-28"></script>
<script type="text/javascript" src="src/cloud.js?version=2019-01-25"></script>
<script type="text/javascript" src="src/locale.js?version=2019-02-20"></script>
<script type="text/javascript" src="src/cloud.js?version=2019-02-20"></script>
<script type="text/javascript" src="src/sha512.js?version=2018-10-02"></script>
<script type="text/javascript" src="src/FileSaver.min.js?version=2018-10-02"></script>
<script type="text/javascript">

Wyświetl plik

@ -148,7 +148,7 @@ CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/
// Global stuff ////////////////////////////////////////////////////////
modules.blocks = '2019-February-15';
modules.blocks = '2019-February-21';
var SyntaxElementMorph;
var BlockMorph;
@ -4805,7 +4805,9 @@ CommandBlockMorph.prototype.userDestroyJustThis = function () {
this.destroy(true); // just this block
}
if (nb) {
if (above instanceof CommandSlotMorph, RingReporterSlotMorph) {
if (above instanceof CommandSlotMorph ||
above instanceof RingReporterSlotMorph
) {
above.nestedBlock(nb);
} else if (above instanceof CommandBlockMorph) {
above.nextBlock(nb);

Wyświetl plik

@ -34,7 +34,7 @@
/*global modules, hex_sha512*/
modules = modules || {};
modules.cloud = '2019-January-25';
modules.cloud = '2019-February-20';
// Global stuff
@ -567,12 +567,11 @@ Cloud.prototype.getProjectVersionMetadata = function (
Cloud.prototype.getRemixes = function (
username,
projectName,
page,
pageSize,
projectName,
onSuccess,
onError,
withThumbnail
onError
) {
var path = '/projects/' +
encodeURIComponent(username) + '/' +
@ -723,3 +722,367 @@ Cloud.prototype.updateProjectName = function (
);
};
// Collections
Cloud.prototype.newCollection = function (
collectionName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/%username/collections/' + encodeURIComponent(collectionName),
onSuccess,
onError,
'Could not create collection'
);
};
Cloud.prototype.getCollectionMetadata = function (
collectionUsername,
collectionName,
onSuccess,
onError
) {
this.request(
'GET',
'/users/' +
(collectionUsername ?
encodeURIComponent(collectionUsername) :
'%username') +
'/collections/' + encodeURIComponent(collectionName) +
'/metadata',
onSuccess,
onError,
'Could not fetch metadata for ' + collectionName
);
};
Cloud.prototype.getCollectionProjects = function (
collectionUsername,
page,
pageSize,
collectionName,
onSuccess,
onError,
withThumbnail
) {
var path = '/users/' +
(collectionUsername ?
encodeURIComponent(collectionUsername) :
'%username') +
'/collections/' + encodeURIComponent(collectionName) +
'/projects';
if (page) {
path += '?page=' + page + '&pagesize=' + (pageSize || 16);
}
if (withThumbnail) {
path += (page ? '&' : '?') + 'withthumbnail=true';
}
this.request(
'GET',
path,
onSuccess,
onError,
'Could not fetch projects'
);
};
Cloud.prototype.setCollectionThumbnail = function (
collectionUsername,
collectionName,
thumbnailId,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/thumbnail?id=' + encodeURIComponent(thumbnailId),
onSuccess,
onError,
'Could not set project thumbnail'
);
};
Cloud.prototype.updateCollectionDescription = function (
collectionUsername,
collectionName,
description,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/metadata',
onSuccess,
onError,
'Could not update collection description',
false, // wants raw response
JSON.stringify({ description: description })
);
};
Cloud.prototype.updateCollectionName = function (
collectionUsername,
collectionName,
newName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/metadata',
onSuccess,
onError,
'Could not update collection name',
false, // wants raw response
JSON.stringify({ name: newName })
);
};
Cloud.prototype.shareCollection = function (
collectionUsername,
collectionName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/metadata?shared=true',
onSuccess,
onError,
'Could not share collection'
);
};
Cloud.prototype.unshareCollection = function (
collectionUsername,
collectionName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/metadata?shared=false&published=false',
onSuccess,
onError,
'Could not unshare collection'
);
};
Cloud.prototype.publishCollection = function (
collectionUsername,
collectionName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/metadata?published=true',
onSuccess,
onError,
'Could not publish collection'
);
};
Cloud.prototype.unpublishCollection = function (
collectionUsername,
collectionName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/metadata?published=false',
onSuccess,
onError,
'Could not unpublish collection'
);
};
Cloud.prototype.addProjectToCollection = function (
collectionUsername,
collectionName,
projectUsername,
projectName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/projects',
onSuccess,
onError,
'Could not add project to collection',
false, // wants raw response
JSON.stringify({
username: projectUsername,
projectname: projectName
})
);
};
Cloud.prototype.removeProjectFromCollection = function (
collectionUsername,
collectionName,
projectId,
onSuccess,
onError
) {
this.withCredentialsRequest(
'DELETE',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/projects/' + encodeURIComponent(projectId),
onSuccess,
onError,
'Could not remove project from collection'
);
};
Cloud.prototype.getUserCollections = function (
collectionUsername,
page,
pageSize,
searchTerm,
onSuccess,
onError
) {
this.withCredentialsRequest(
'GET',
'/users/' +
(collectionUsername ?
encodeURIComponent(collectionUsername) :
'%username') +
'/collections?' +
this.encodeDict({
page: page || '',
pageSize: page ? pageSize | 16 : '',
matchtext: searchTerm ? encodeURIComponent(searchTerm) : ''
}),
onSuccess,
onError,
'Could not fetch collections'
);
};
Cloud.prototype.getCollectionsContainingProject = function (
username,
projectName,
page,
pageSize,
onSuccess,
onError
) {
var path = '/projects/' +
encodeURIComponent(username) + '/' +
encodeURIComponent(projectName) + '/collections';
if (page) {
path += '?page=' + page + '&pagesize=' + (pageSize || 16);
}
this.request(
'GET',
path,
onSuccess,
onError,
'Could not fetch collections for project ' + projectName
);
};
Cloud.prototype.getCollections = function (
page,
pageSize,
searchTerm,
onSuccess,
onError
) {
this.request(
'GET',
'/collections?' +
this.encodeDict({
page: page,
pageSize: page ? pageSize | 16 : '',
matchtext: encodeURIComponent(searchTerm)
}),
onSuccess,
onError,
'Could not fetch collections'
);
};
Cloud.prototype.deleteCollection = function (
collectionUsername,
collectionName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'DELETE',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName),
onSuccess,
onError,
'Could not remove collection'
);
};
Cloud.prototype.addEditorToCollection = function (
collectionUsername,
collectionName,
editorUsername,
onSuccess,
onError
) {
this.withCredentialsRequest(
'POST',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/editors',
onSuccess,
onError,
'Could not add editor to collection',
false, // wants raw response
JSON.stringify({
editor_username: editorUsername,
})
);
};
Cloud.prototype.removeEditorFromCollection = function (
collectionUsername,
collectionName,
editorUsername,
onSuccess,
onError
) {
this.withCredentialsRequest(
'DELETE',
'/users/' + encodeURIComponent(collectionUsername) +
'/collections/' + encodeURIComponent(collectionName) +
'/editors/' + encodeURIComponent(editorUsername),
onSuccess,
onError,
'Could not remove editor from collection'
);
};

Wyświetl plik

@ -75,7 +75,7 @@ isRetinaSupported, SliderMorph, Animation, BoxMorph, MediaRecorder*/
// Global stuff ////////////////////////////////////////////////////////
modules.gui = '2019-February-07';
modules.gui = '2019-February-20';
// Declarations
@ -3749,7 +3749,6 @@ IDE_Morph.prototype.editProjectNotes = function () {
var dialog = new DialogBoxMorph().withKey('projectNotes'),
frame = new ScrollFrameMorph(),
text = new TextMorph(this.projectNotes || ''),
ok = dialog.ok,
myself = this,
size = 250,
world = this.world();
@ -3776,9 +3775,14 @@ IDE_Morph.prototype.editProjectNotes = function () {
frame.addContents(text);
text.drawNew();
dialog.ok = function () {
myself.projectNotes = text.text;
ok.call(this);
dialog.getInput = function () {
return text.text;
};
dialog.target = myself;
dialog.action = function (note) {
myself.projectNotes = note;
};
dialog.justDropped = function () {

Wyświetl plik

@ -42,7 +42,7 @@
/*global modules, contains*/
modules.locale = '2019-January-28';
modules.locale = '2019-February-20';
// Global stuff
@ -160,7 +160,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org, jadga.huegle@sap.com',
'last_changed':
'2019-01-28'
'2019-02-20'
};
SnapTranslator.dict.it = {

Wyświetl plik

@ -83,7 +83,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph,
AlignmentMorph, Process, XML_Element, VectorPaintEditorMorph*/
modules.objects = '2019-February-07';
modules.objects = '2019-February-18';
var SpriteMorph;
var StageMorph;
@ -3206,7 +3206,9 @@ SpriteMorph.prototype.reportSounds = function () {
SpriteMorph.prototype.userMenu = function () {
var ide = this.parentThatIsA(IDE_Morph),
menu = new MenuMorph(this);
menu = new MenuMorph(this),
allParts,
anchors;
if (ide && ide.isAppMode) {
// menu.addItem('help', 'nop');
@ -3246,6 +3248,15 @@ SpriteMorph.prototype.userMenu = function () {
localize('detach from') + ' ' + this.anchor.name,
'detachFromAnchor'
);
} else {
allParts = this.allParts();
anchors = this.parent.children.filter(function (morph) {
return morph instanceof SpriteMorph &&
!contains(allParts, morph);
});
if (anchors.length) {
menu.addMenu('stick to', this.anchorsMenu(anchors));
}
}
if (this.parts.length) {
menu.addItem('detach all parts', 'detachAllParts');
@ -3254,6 +3265,20 @@ SpriteMorph.prototype.userMenu = function () {
return menu;
};
SpriteMorph.prototype.anchorsMenu = function (targets) {
var menu = new MenuMorph(this.attachTo, null, this);
targets.forEach(function (sprite) {
menu.addItem(
[
sprite.thumbnail(new Point(24, 24)),
sprite.name,
],
sprite
);
});
return menu;
};
SpriteMorph.prototype.exportSprite = function () {
if (this.isTemporary) {return; }
var ide = this.parentThatIsA(IDE_Morph);
@ -5987,6 +6012,10 @@ SpriteMorph.prototype.booleanMorph = function (bool) {
simulate Morphic trees
*/
SpriteMorph.prototype.attachTo = function (aSprite) {
aSprite.attachPart(this);
};
SpriteMorph.prototype.attachPart = function (aSprite) {
var v = Date.now();
if (aSprite.anchor) {

Wyświetl plik

@ -62,7 +62,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, Color,
TableFrameMorph, ColorSlotMorph, isSnapObject, Map*/
modules.threads = '2019-January-28';
modules.threads = '2019-February-19';
var ThreadManager;
var Process;
@ -2464,7 +2464,7 @@ Process.prototype.reportTypeOf = function (thing) {
if (thing instanceof List) {
return 'list';
}
if (!isNaN(+thing)) {
if (parseFloat(thing) === +thing) { // I hate this! -Jens
return 'number';
}
if (isString(thing)) {