From d8d1810e436cba83144f4b2234fc3097a739208b Mon Sep 17 00:00:00 2001 From: Hardmath123 Date: Sun, 22 Dec 2013 16:28:11 -0800 Subject: Initial stop others block --- objects.js | 6 ++++++ threads.js | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/objects.js b/objects.js index 41b511d..614e7d7 100644 --- a/objects.js +++ b/objects.js @@ -591,6 +591,11 @@ SpriteMorph.prototype.initBlocks = function () { category: 'control', spec: 'stop all %stop' }, + doStopOthers: { + type: 'command', + category: 'control', + spec: 'stop other scripts in sprite' + }, doRun: { type: 'command', category: 'control', @@ -1649,6 +1654,7 @@ SpriteMorph.prototype.blockTemplates = function (category) { blocks.push(block('doStopBlock')); blocks.push(block('doStop')); blocks.push(block('doStopAll')); + blocks.push(block('doStopOthers')); blocks.push('-'); blocks.push(block('doRun')); blocks.push(block('fork')); diff --git a/threads.js b/threads.js index d1e57d3..25659b5 100644 --- a/threads.js +++ b/threads.js @@ -168,6 +168,17 @@ ThreadManager.prototype.stopAllForReceiver = function (rcvr) { }); }; +ThreadManager.prototype.stopAllForReceiverExcept = function (rcvr, excpt) { + this.processes.forEach(function (proc) { + if (proc.homeContext.receiver === rcvr && proc != excpt) { + proc.stop(); + if (rcvr.isClone) { + proc.isDead = true; + } + } + }); +}; + ThreadManager.prototype.stopProcess = function (block) { var active = this.findProcess(block); if (active) { @@ -1368,6 +1379,16 @@ Process.prototype.doStopAll = function () { } }; +Process.prototype.doStopOthers = function () { + var stage, ide; + if (this.homeContext.receiver) { + stage = this.homeContext.receiver.parentThatIsA(StageMorph); + if (stage) { + stage.threads.stopAllForReceiverExcept(this.homeContext.receiver, this); + } + } +}; + Process.prototype.doWarp = function (body) { // execute my contents block atomically (more or less) var outer = this.context.outerContext, // for tail call elimination -- cgit v1.3.1 From ed5173863799378c699da426c4cd41348d0bcbf8 Mon Sep 17 00:00:00 2001 From: Michael Ball Date: Sun, 29 Dec 2013 03:02:05 -0800 Subject: adding libraries to the repo --- libraries/LIBRARIES | 5 +++++ libraries/iteration-composition.xml | 1 + libraries/list-utilities.xml | 1 + libraries/stream-tools.xml | 1 + libraries/variadic-reporters.xml | 1 + libraries/word-sentence.xml | 1 + 6 files changed, 10 insertions(+) create mode 100644 libraries/LIBRARIES create mode 100644 libraries/iteration-composition.xml create mode 100644 libraries/list-utilities.xml create mode 100644 libraries/stream-tools.xml create mode 100644 libraries/variadic-reporters.xml create mode 100644 libraries/word-sentence.xml diff --git a/libraries/LIBRARIES b/libraries/LIBRARIES new file mode 100644 index 0000000..f11aa85 --- /dev/null +++ b/libraries/LIBRARIES @@ -0,0 +1,5 @@ +iteration-composition Iteration, composition +list-utilities List utilities +stream-tools Streams (lazy lists) +variadic-reporters Variadic reporters +word-sentence Words, sentences diff --git a/libraries/iteration-composition.xml b/libraries/iteration-composition.xml new file mode 100644 index 0000000..0f16bb6 --- /dev/null +++ b/libraries/iteration-composition.xml @@ -0,0 +1 @@ +Call f(f(f(...(f(x))))) n times where the three input slots are n, f, and x from left to right. The # variable can be used inside f to represent how many times f has been called.Call f(f(f(...(f(x))))) until condition is true, where the three input slots are condition, f, and x from left to right. The # variable can be used inside f or condition to indicate how many times f has been called.Returns the function f(g(x)) where f and g are the two inputs.Like the built-in REPEAT UNTIL block, except that the ending condition is not tested until the script has been run the first time. So the script is run at least once.Run the script repeatedly, as long as the given condition is true. Runs the script at least once before testing the condition.Runs the script repeatedly, as long as the condition is true. Tests the condition before the first time the script is run. Like the built in REPEAT UNTIL except that in this block the condition must be true, not false.Runs the script the specified number of times, like the built-in REPEAT block, but this one provides the # variable that can be used inside the script. Try REPEAT (200) MOVE (#) STEPS RIGHT 92 with the pen down. \ No newline at end of file diff --git a/libraries/list-utilities.xml b/libraries/list-utilities.xml new file mode 100644 index 0000000..dc7ee75 --- /dev/null +++ b/libraries/list-utilities.xml @@ -0,0 +1 @@ +Take any number of input lists, and create a new list containing the items of the input lists. So APPEND [A B] [C D] where the [,,,] are lists reports the list [A B C D] not [[A B] [C D]].
11111
Reports a new list containing the items of the input list, but in the opposite order.
1inputresult
Reports a new list whose items are the same as in the input list, except that if two or more equal items appear in the input list, only the last one is kept in the result.
1
Reports a sorted version of the list in its first input slot, using the comparison function in the second input slot. For a list of numbers, using < as the comparison function will sort from low to high; using > will sort from high to low.
1even itemsmerge11#1#2
\ No newline at end of file diff --git a/libraries/stream-tools.xml b/libraries/stream-tools.xml new file mode 100644 index 0000000..66efcec --- /dev/null +++ b/libraries/stream-tools.xml @@ -0,0 +1 @@ +
4234
1datamapmany1data lists
1001
\ No newline at end of file diff --git a/libraries/variadic-reporters.xml b/libraries/variadic-reporters.xml new file mode 100644 index 0000000..d6ae177 --- /dev/null +++ b/libraries/variadic-reporters.xml @@ -0,0 +1 @@ +Takes any number of numbers as inputs (use the left and right arrowheads to adjust the number of input slots) and reports the result of adding them all, so ISUM (4) (100) (8)) reports 112.1Takes any number of numbers as inputs (use the left and right arrowheads to adjust the number of input slots) and reports the result of multiplying them all, so (PRODUCT (4) (100) (8)) reports 3200.1Takes any number of Boolean (true/false) inputs (use the left and right arrowheads to adjust the number of input slots) and reports TRUE only if all of the inputs are TRUE, otherwise FALSE. Like AND but for multiple inputs.1Takes any number of Boolean (true/false) inputs (use the left and right arrowheads to adjust the number of input slots) and reports TRUE if at least one input is TRUE, otherwise FALSE.1 \ No newline at end of file diff --git a/libraries/word-sentence.xml b/libraries/word-sentence.xml new file mode 100644 index 0000000..ff2a1a7 --- /dev/null +++ b/libraries/word-sentence.xml @@ -0,0 +1 @@ +Takes a text string as input, and reports a new text string containing all but the first character of the input.
resulti2
Takes a text string as input, divides it into words treating one or more spaces as a word separator (only spaces count; punctuation is part of the word) and reports a text string containing all but the first word, with one space between words and no spaces at the beginning or end. (Note: consider using SENTENCE->LIST and processing the resulting list instead of doing recursion on sentences in text string form. List operations are faster.)
Takes a text string as input, and reports a new text string containing all but the last letter of the input.
resulti1
Takes a text string as input, divides it into words treating one or more spaces as a word separator (only spaces count; punctuation is part of the word) and reports a text string containing all but the last word, with one space between words and no spaces at the beginning or end. (Note: consider using SENTENCE->LIST and processing the resulting list instead of doing recursion on sentences in text string form. List operations are faster.)
1 1 11 1
Takes a text string as input, divides it into words treating one or more spaces as a word separator (only spaces count; punctuation is part of the word) and reports a text string containing only the first word, with no spaces before or after it.
Takes a text string as input, and reports the last character in the string.
Takes a text string as input, divides it into words treating one or more spaces as a word separator (only spaces count; punctuation is part of the word) and reports a text string containing only the last word of the input, with no spaces before or after it.
1 1
Takes a text string as input, and reports TRUE if the string has no characters in it of any kind, otherwise false.
Takes a text string as input, and reports TRUE if the input contains no characters other than spaces (therefore, no words when the string is considered as a sentence), otherwise FALSE.
Takes a text string as input, and reports a list in which each item is a single character from the string.
\ No newline at end of file -- cgit v1.3.1 From c947a4d5b741b783ebe6653929051ea03c34a590 Mon Sep 17 00:00:00 2001 From: blob8108 Date: Mon, 6 Jan 2014 11:17:59 +0000 Subject: Add useful headers to HTTP block --- threads.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/threads.js b/threads.js index d1e57d3..9524d66 100644 --- a/threads.js +++ b/threads.js @@ -1730,6 +1730,9 @@ Process.prototype.reportURL = function (url) { if (!this.httpRequest) { this.httpRequest = new XMLHttpRequest(); this.httpRequest.open("GET", 'http://' + url, true); + this.httpRequest.setRequestHeader("X-Requested-With", + "XMLHttpRequest"); + this.httpRequest.setRequestHeader("X-Application", "Snap! 4.0"); this.httpRequest.send(null); } else if (this.httpRequest.readyState === 4) { response = this.httpRequest.responseText; -- cgit v1.3.1 From 8646dfc35ed3d11a2e23ecd545ecef47ef53f8b2 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 8 Jan 2014 12:18:04 +0100 Subject: support for TELL and ASK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FOR reporter’s first input now also accepts blocks and scripts („rings“), and reports a copy that is bound to the sprite indicated by the second input. This lets you „zombify“ (or remote-control) sprites (and create custom TELL and ASK blocks) --- blocks.js | 3 +-- history.txt | 4 ++++ objects.js | 2 +- threads.js | 17 ++++++++++++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/blocks.js b/blocks.js index 96d8b53..619a487 100644 --- a/blocks.js +++ b/blocks.js @@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2013-November-26'; +modules.blocks = '2014-January-08'; var SyntaxElementMorph; var BlockMorph; @@ -996,7 +996,6 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { 'attributesMenu', true ); - part.isStatic = true; break; case '%fun': part = new InputSlotMorph( diff --git a/history.txt b/history.txt index 642ea7f..d205744 100755 --- a/history.txt +++ b/history.txt @@ -2044,3 +2044,7 @@ ______ ------ * Objects: stage watchers for „mouse x“ and „mouse y“ sensing reporters. Thanks, Michael! * Store: fixed saving/loading/localisation of new mouse coordinate stage watchers + +140108 +------ +* Threads, Blocks, Objects: The FOR reporter’s first input now also accepts blocks and scripts („rings“), and reports a copy that is bound to the sprite indicated by the second input. This lets you „zombify“ (or remote-control) sprites (and create custom TELL and ASK blocks) diff --git a/objects.js b/objects.js index 41b511d..67eb143 100644 --- a/objects.js +++ b/objects.js @@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2013-December-19'; +modules.objects = '2014-January-08'; var SpriteMorph; var StageMorph; diff --git a/threads.js b/threads.js index d1e57d3..19f5fd8 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2013-December-11'; +modules.threads = '2014-January-08'; var ThreadManager; var Process; @@ -2377,6 +2377,9 @@ Process.prototype.reportAttributeOf = function (attribute, name) { thatObj = this.getOtherObject(name, thisObj, stage); } if (thatObj) { + if (attribute instanceof Context) { + return this.reportContextFor(attribute, thatObj); + } if (isString(attribute)) { return thatObj.variables.getVar(attribute); } @@ -2401,6 +2404,18 @@ Process.prototype.reportAttributeOf = function (attribute, name) { return ''; }; +Process.prototype.reportContextFor = function (context, otherObj) { + // Private - return a copy of the context + // and bind it to another receiver + var result = copy(context); + result.receiver = otherObj; + if (result.outerContext) { + result.outerContext = copy(result.outerContext); + result.outerContext.receiver = otherObj; + } + return result; +}; + Process.prototype.reportMouseX = function () { var stage, world; if (this.homeContext.receiver) { -- cgit v1.3.1 From 0020aeda14d7f7aea89f88c32fc06fcb3e077d40 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 8 Jan 2014 13:24:30 +0100 Subject: initial support for „sensing“ sprite-only custom block definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commented out for now --- blocks.js | 7 +++++++ history.txt | 1 + 2 files changed, 8 insertions(+) diff --git a/blocks.js b/blocks.js index 619a487..8b6bcc2 100644 --- a/blocks.js +++ b/blocks.js @@ -6301,6 +6301,8 @@ InputSlotMorph.prototype.dropDownMenu = function () { if (Object.prototype.hasOwnProperty.call(choices, key)) { if (key[0] === '~') { menu.addLine(); + // } else if (key.indexOf('§_def') === 0) { + // menu.addItem(choices[key].blockInstance(), choices[key]); } else { menu.addItem(key, choices[key]); } @@ -6517,6 +6519,11 @@ InputSlotMorph.prototype.attributesMenu = function () { dict[name] = name; }); } + /* + obj.customBlocks.forEach(function (def, i) { + dict['§_def' + i] = def + }); + */ return dict; }; diff --git a/history.txt b/history.txt index d205744..37a90a6 100755 --- a/history.txt +++ b/history.txt @@ -2048,3 +2048,4 @@ ______ 140108 ------ * Threads, Blocks, Objects: The FOR reporter’s first input now also accepts blocks and scripts („rings“), and reports a copy that is bound to the sprite indicated by the second input. This lets you „zombify“ (or remote-control) sprites (and create custom TELL and ASK blocks) +* Blocks: initial support for „sensing“ sprite-only custom block definitions, commented out for now -- cgit v1.3.1 From b9f8ef9951f2a534556925ad7a2776281f7e18c5 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 8 Jan 2014 15:17:03 +0100 Subject: add mouseLeaveDragging() behavior to the paint editor, thanks, Kartik! All credit for fixing this goes to Kartik. This also seems to change just about every line ending for reasons known only to Xcode. Sorry Kartik, for not pulling your request because of those line endings, they are inevitable! --- history.txt | 1 + paint.js | 1434 ++++++++++++++++++++++++++++++----------------------------- 2 files changed, 720 insertions(+), 715 deletions(-) diff --git a/history.txt b/history.txt index 37a90a6..37d1d6b 100755 --- a/history.txt +++ b/history.txt @@ -2049,3 +2049,4 @@ ______ ------ * Threads, Blocks, Objects: The FOR reporter’s first input now also accepts blocks and scripts („rings“), and reports a copy that is bound to the sprite indicated by the second input. This lets you „zombify“ (or remote-control) sprites (and create custom TELL and ASK blocks) * Blocks: initial support for „sensing“ sprite-only custom block definitions, commented out for now +* Paint: Add mouseLeaveDragging() event behavior, thanks, Kartik, for this fix! diff --git a/paint.js b/paint.js index 44585b2..15b4172 100644 --- a/paint.js +++ b/paint.js @@ -1,14 +1,14 @@ -/* +/* paint.js - - a paint editor for Snap! - inspired by the Scratch paint editor. - + + a paint editor for Snap! + inspired by the Scratch paint editor. + written by Kartik Chandra - Copyright (C) 2013 by Kartik Chandra - - This file is part of Snap!. - + Copyright (C) 2013 by Kartik Chandra + + This file is part of Snap!. + Snap! is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of @@ -50,186 +50,187 @@ May 16 - flat design adjustments (Jens) July 12 - pipette tool, code formatting adjustments (Jens) September 16 - flood fill freeze fix (Kartik) + Jan 08 - mouse leave dragging fix (Kartik) + + */ - */ - -/*global Point, Rectangle, DialogBoxMorph, fontHeight, AlignmentMorph, - FrameMorph, PushButtonMorph, Color, SymbolMorph, newCanvas, Morph, TextMorph, - CostumeIconMorph, IDE_Morph, Costume, SpriteMorph, nop, Image, WardrobeMorph, - TurtleIconMorph, localize, MenuMorph, InputFieldMorph, SliderMorph, +/*global Point, Rectangle, DialogBoxMorph, fontHeight, AlignmentMorph, + FrameMorph, PushButtonMorph, Color, SymbolMorph, newCanvas, Morph, TextMorph, + CostumeIconMorph, IDE_Morph, Costume, SpriteMorph, nop, Image, WardrobeMorph, + TurtleIconMorph, localize, MenuMorph, InputFieldMorph, SliderMorph, ToggleMorph, ToggleButtonMorph, BoxMorph, modules, radians, - MorphicPreferences, getDocumentPositionOf - */ - + MorphicPreferences, getDocumentPositionOf + */ + // Global stuff //////////////////////////////////////////////////////// -modules.paint = '2013-September-16'; +modules.paint = '2014-January-08'; // Declarations -var PaintEditorMorph; -var PaintCanvasMorph; -var PaintColorPickerMorph; - -// PaintEditorMorph ////////////////////////// - -// A complete paint editor - -PaintEditorMorph.prototype = new DialogBoxMorph(); -PaintEditorMorph.prototype.constructor = PaintEditorMorph; -PaintEditorMorph.uber = DialogBoxMorph.prototype; - -PaintEditorMorph.prototype.padding = 10; - -function PaintEditorMorph() { - this.init(); -} - -PaintEditorMorph.prototype.init = function () { - // additional properties: +var PaintEditorMorph; +var PaintCanvasMorph; +var PaintColorPickerMorph; + +// PaintEditorMorph ////////////////////////// + +// A complete paint editor + +PaintEditorMorph.prototype = new DialogBoxMorph(); +PaintEditorMorph.prototype.constructor = PaintEditorMorph; +PaintEditorMorph.uber = DialogBoxMorph.prototype; + +PaintEditorMorph.prototype.padding = 10; + +function PaintEditorMorph() { + this.init(); +} + +PaintEditorMorph.prototype.init = function () { + // additional properties: this.paper = null; // paint canvas - this.oncancel = null; - - // initialize inherited properties: - PaintEditorMorph.uber.init.call(this); - - // override inherited properties: - this.labelString = "Paint Editor"; - this.createLabel(); - - // build contents: - this.buildContents(); -}; - -PaintEditorMorph.prototype.buildContents = function () { - var myself = this; - + this.oncancel = null; + + // initialize inherited properties: + PaintEditorMorph.uber.init.call(this); + + // override inherited properties: + this.labelString = "Paint Editor"; + this.createLabel(); + + // build contents: + this.buildContents(); +}; + +PaintEditorMorph.prototype.buildContents = function () { + var myself = this; + this.paper = new PaintCanvasMorph(function () {return myself.shift; }); - this.paper.setExtent(new Point(480, 360)); - - this.addBody(new AlignmentMorph('row', this.padding)); - this.controls = new AlignmentMorph('column', this.padding); - this.controls.alignment = 'left'; - - this.edits = new AlignmentMorph('row', this.padding); - this.buildEdits(); - this.controls.add(this.edits); - - this.body.color = this.color; - - this.body.add(this.controls); - this.body.add(this.paper); - - this.toolbox = new BoxMorph(); - this.toolbox.color = SpriteMorph.prototype.paletteColor.lighter(8); + this.paper.setExtent(new Point(480, 360)); + + this.addBody(new AlignmentMorph('row', this.padding)); + this.controls = new AlignmentMorph('column', this.padding); + this.controls.alignment = 'left'; + + this.edits = new AlignmentMorph('row', this.padding); + this.buildEdits(); + this.controls.add(this.edits); + + this.body.color = this.color; + + this.body.add(this.controls); + this.body.add(this.paper); + + this.toolbox = new BoxMorph(); + this.toolbox.color = SpriteMorph.prototype.paletteColor.lighter(8); this.toolbox.borderColor = this.toolbox.color.lighter(40); if (MorphicPreferences.isFlat) { this.toolbox.edge = 0; - } - - this.buildToolbox(); - this.controls.add(this.toolbox); - - this.propertiesControls = { - colorpicker: null, - penSizeSlider: null, - penSizeField: null, - primaryColorButton: null, - primaryColorViewer: null, - constrain: null - }; - this.populatePropertiesMenu(); - - this.addButton("ok", "OK"); - this.addButton("cancel", "Cancel"); - - this.refreshToolButtons(); - this.fixLayout(); - this.drawNew(); -}; - -PaintEditorMorph.prototype.buildToolbox = function () { - var tools = { - brush: - "Paintbrush tool\n(free draw)", - rectangle: - "Stroked Rectangle\n(shift: square)", - circle: - "Stroked Ellipse\n(shift: circle)", - eraser: - "Eraser tool", - crosshairs: - "Set the rotation center", - - line: - "Line tool\n(shift: vertical/horizontal)", - rectangleSolid: - "Filled Rectangle\n(shift: square)", - circleSolid: - "Filled Ellipse\n(shift: circle)", - paintbucket: - "Fill a region", + } + + this.buildToolbox(); + this.controls.add(this.toolbox); + + this.propertiesControls = { + colorpicker: null, + penSizeSlider: null, + penSizeField: null, + primaryColorButton: null, + primaryColorViewer: null, + constrain: null + }; + this.populatePropertiesMenu(); + + this.addButton("ok", "OK"); + this.addButton("cancel", "Cancel"); + + this.refreshToolButtons(); + this.fixLayout(); + this.drawNew(); +}; + +PaintEditorMorph.prototype.buildToolbox = function () { + var tools = { + brush: + "Paintbrush tool\n(free draw)", + rectangle: + "Stroked Rectangle\n(shift: square)", + circle: + "Stroked Ellipse\n(shift: circle)", + eraser: + "Eraser tool", + crosshairs: + "Set the rotation center", + + line: + "Line tool\n(shift: vertical/horizontal)", + rectangleSolid: + "Filled Rectangle\n(shift: square)", + circleSolid: + "Filled Ellipse\n(shift: circle)", + paintbucket: + "Fill a region", pipette: "Pipette tool\n(pick a color anywhere)" - }, - myself = this, - left = this.toolbox.left(), - top = this.toolbox.top(), - padding = 2, - inset = 5, - x = 0, - y = 0; - - Object.keys(tools).forEach(function (tool) { - var btn = myself.toolButton(tool, tools[tool]); - btn.setPosition(new Point( - left + x, - top + y - )); - x += btn.width() + padding; - if (tool === "crosshairs") { - x = 0; - y += btn.height() + padding; - myself.paper.drawcrosshair(); - } - myself.toolbox[tool] = btn; - myself.toolbox.add(btn); - }); - - this.toolbox.bounds = this.toolbox.fullBounds().expandBy(inset * 2); - this.toolbox.drawNew(); -}; - -PaintEditorMorph.prototype.buildEdits = function () { - var paper = this.paper; - - this.edits.add(this.pushButton( - "undo", - function () {paper.undo(); } - )); - - this.edits.add(this.pushButton( - "clear", - function () {paper.clearCanvas(); } - )); - this.edits.fixLayout(); -}; - -PaintEditorMorph.prototype.openIn = function (world, oldim, oldrc, callback) { + }, + myself = this, + left = this.toolbox.left(), + top = this.toolbox.top(), + padding = 2, + inset = 5, + x = 0, + y = 0; + + Object.keys(tools).forEach(function (tool) { + var btn = myself.toolButton(tool, tools[tool]); + btn.setPosition(new Point( + left + x, + top + y + )); + x += btn.width() + padding; + if (tool === "crosshairs") { + x = 0; + y += btn.height() + padding; + myself.paper.drawcrosshair(); + } + myself.toolbox[tool] = btn; + myself.toolbox.add(btn); + }); + + this.toolbox.bounds = this.toolbox.fullBounds().expandBy(inset * 2); + this.toolbox.drawNew(); +}; + +PaintEditorMorph.prototype.buildEdits = function () { + var paper = this.paper; + + this.edits.add(this.pushButton( + "undo", + function () {paper.undo(); } + )); + + this.edits.add(this.pushButton( + "clear", + function () {paper.clearCanvas(); } + )); + this.edits.fixLayout(); +}; + +PaintEditorMorph.prototype.openIn = function (world, oldim, oldrc, callback) { // Open the editor in a world with an optional image to edit - this.oldim = oldim; - this.oldrc = oldrc.copy(); - this.callback = callback || nop; + this.oldim = oldim; + this.oldrc = oldrc.copy(); + this.callback = callback || nop; - this.processKeyUp = function () { - this.shift = false; - this.propertiesControls.constrain.refresh(); - }; + this.processKeyUp = function () { + this.shift = false; + this.propertiesControls.constrain.refresh(); + }; - this.processKeyDown = function () { - this.shift = this.world().currentKey === 16; - this.propertiesControls.constrain.refresh(); - }; + this.processKeyDown = function () { + this.shift = this.world().currentKey === 16; + this.propertiesControls.constrain.refresh(); + }; //merge oldim: if (this.oldim) { @@ -244,170 +245,170 @@ PaintEditorMorph.prototype.openIn = function (world, oldim, oldrc, callback) { this.paper.drawNew(); } - this.key = 'paint'; - this.popUp(world); -}; - + this.key = 'paint'; + this.popUp(world); +}; + PaintEditorMorph.prototype.fixLayout = function () { var oldFlag = Morph.prototype.trackChanges; - + this.changed(); oldFlag = Morph.prototype.trackChanges; Morph.prototype.trackChanges = false; if (this.paper) { this.paper.buildContents(); - this.paper.drawNew(); - } - if (this.controls) {this.controls.fixLayout(); } - if (this.body) {this.body.fixLayout(); } - PaintEditorMorph.uber.fixLayout.call(this); + this.paper.drawNew(); + } + if (this.controls) {this.controls.fixLayout(); } + if (this.body) {this.body.fixLayout(); } + PaintEditorMorph.uber.fixLayout.call(this); Morph.prototype.trackChanges = oldFlag; this.changed(); -}; - -PaintEditorMorph.prototype.refreshToolButtons = function () { - this.toolbox.children.forEach(function (toggle) { - toggle.refresh(); - }); -}; - -PaintEditorMorph.prototype.ok = function () { - this.callback( - this.paper.paper, - this.paper.rotationCenter - ); - this.destroy(); -}; +}; + +PaintEditorMorph.prototype.refreshToolButtons = function () { + this.toolbox.children.forEach(function (toggle) { + toggle.refresh(); + }); +}; + +PaintEditorMorph.prototype.ok = function () { + this.callback( + this.paper.paper, + this.paper.rotationCenter + ); + this.destroy(); +}; PaintEditorMorph.prototype.cancel = function () { if (this.oncancel) {this.oncancel(); } this.destroy(); }; - -PaintEditorMorph.prototype.populatePropertiesMenu = function () { - var c = this.controls, - myself = this, - pc = this.propertiesControls, - alpen = new AlignmentMorph("row", this.padding); - - pc.primaryColorViewer = new Morph(); - pc.primaryColorViewer.setExtent(new Point(180, 50)); - pc.primaryColorViewer.color = new Color(0, 0, 0); - pc.colorpicker = new PaintColorPickerMorph( - new Point(180, 100), - function (color) { - var ni = newCanvas(pc.primaryColorViewer.extent()), - ctx = ni.getContext("2d"), - i, - j; - myself.paper.settings.primarycolor = color; - if (color === "transparent") { - for (i = 0; i < 180; i += 5) { - for (j = 0; j < 15; j += 5) { - ctx.fillStyle = - ((j + i) / 5) % 2 === 0 ? - "rgba(0, 0, 0, 0.2)" : - "rgba(0, 0, 0, 0.5)"; - ctx.fillRect(i, j, 5, 5); - - } - } - } else { - ctx.fillStyle = color.toString(); - ctx.fillRect(0, 0, 180, 15); - } - ctx.strokeStyle = "black"; - ctx.lineWidth = Math.min(myself.paper.settings.linewidth, 20); - ctx.beginPath(); - ctx.lineCap = "round"; - ctx.moveTo(20, 30); - ctx.lineTo(160, 30); - ctx.stroke(); - pc.primaryColorViewer.image = ni; - pc.primaryColorViewer.changed(); - } - ); - pc.colorpicker.action(new Color(0, 0, 0)); - - pc.penSizeSlider = new SliderMorph(0, 20, 5, 5); - pc.penSizeSlider.orientation = "horizontal"; - pc.penSizeSlider.setHeight(15); - pc.penSizeSlider.setWidth(150); - pc.penSizeSlider.action = function (num) { - if (pc.penSizeField) { - pc.penSizeField.setContents(num); - } - myself.paper.settings.linewidth = num; - pc.colorpicker.action(myself.paper.settings.primarycolor); - }; - pc.penSizeField = new InputFieldMorph("5", true, null, false); - pc.penSizeField.contents().minWidth = 20; - pc.penSizeField.setWidth(25); - pc.penSizeField.accept = function () { - var val = parseFloat(pc.penSizeField.getValue()); - pc.penSizeSlider.value = val; - pc.penSizeSlider.drawNew(); - pc.penSizeSlider.updateValue(); - this.setContents(val); - myself.paper.settings.linewidth = val; - this.world().keyboardReceiver = myself; - pc.colorpicker.action(myself.paper.settings.primarycolor); - }; - alpen.add(pc.penSizeSlider); - alpen.add(pc.penSizeField); - alpen.color = myself.color; - alpen.fixLayout(); - pc.penSizeField.drawNew(); - pc.constrain = new ToggleMorph( - "checkbox", - this, - function () {myself.shift = !myself.shift; }, - "Constrain proportions of shapes?\n(you can also hold shift)", - function () {return myself.shift; } - ); - c.add(pc.colorpicker); - //c.add(pc.primaryColorButton); - c.add(pc.primaryColorViewer); - c.add(new TextMorph("Brush size")); - c.add(alpen); - c.add(pc.constrain); -}; - -PaintEditorMorph.prototype.toolButton = function (icon, hint) { - var button, myself = this; - - button = new ToggleButtonMorph( - null, + +PaintEditorMorph.prototype.populatePropertiesMenu = function () { + var c = this.controls, + myself = this, + pc = this.propertiesControls, + alpen = new AlignmentMorph("row", this.padding); + + pc.primaryColorViewer = new Morph(); + pc.primaryColorViewer.setExtent(new Point(180, 50)); + pc.primaryColorViewer.color = new Color(0, 0, 0); + pc.colorpicker = new PaintColorPickerMorph( + new Point(180, 100), + function (color) { + var ni = newCanvas(pc.primaryColorViewer.extent()), + ctx = ni.getContext("2d"), + i, + j; + myself.paper.settings.primarycolor = color; + if (color === "transparent") { + for (i = 0; i < 180; i += 5) { + for (j = 0; j < 15; j += 5) { + ctx.fillStyle = + ((j + i) / 5) % 2 === 0 ? + "rgba(0, 0, 0, 0.2)" : + "rgba(0, 0, 0, 0.5)"; + ctx.fillRect(i, j, 5, 5); + + } + } + } else { + ctx.fillStyle = color.toString(); + ctx.fillRect(0, 0, 180, 15); + } + ctx.strokeStyle = "black"; + ctx.lineWidth = Math.min(myself.paper.settings.linewidth, 20); + ctx.beginPath(); + ctx.lineCap = "round"; + ctx.moveTo(20, 30); + ctx.lineTo(160, 30); + ctx.stroke(); + pc.primaryColorViewer.image = ni; + pc.primaryColorViewer.changed(); + } + ); + pc.colorpicker.action(new Color(0, 0, 0)); + + pc.penSizeSlider = new SliderMorph(0, 20, 5, 5); + pc.penSizeSlider.orientation = "horizontal"; + pc.penSizeSlider.setHeight(15); + pc.penSizeSlider.setWidth(150); + pc.penSizeSlider.action = function (num) { + if (pc.penSizeField) { + pc.penSizeField.setContents(num); + } + myself.paper.settings.linewidth = num; + pc.colorpicker.action(myself.paper.settings.primarycolor); + }; + pc.penSizeField = new InputFieldMorph("5", true, null, false); + pc.penSizeField.contents().minWidth = 20; + pc.penSizeField.setWidth(25); + pc.penSizeField.accept = function () { + var val = parseFloat(pc.penSizeField.getValue()); + pc.penSizeSlider.value = val; + pc.penSizeSlider.drawNew(); + pc.penSizeSlider.updateValue(); + this.setContents(val); + myself.paper.settings.linewidth = val; + this.world().keyboardReceiver = myself; + pc.colorpicker.action(myself.paper.settings.primarycolor); + }; + alpen.add(pc.penSizeSlider); + alpen.add(pc.penSizeField); + alpen.color = myself.color; + alpen.fixLayout(); + pc.penSizeField.drawNew(); + pc.constrain = new ToggleMorph( + "checkbox", + this, + function () {myself.shift = !myself.shift; }, + "Constrain proportions of shapes?\n(you can also hold shift)", + function () {return myself.shift; } + ); + c.add(pc.colorpicker); + //c.add(pc.primaryColorButton); + c.add(pc.primaryColorViewer); + c.add(new TextMorph("Brush size")); + c.add(alpen); + c.add(pc.constrain); +}; + +PaintEditorMorph.prototype.toolButton = function (icon, hint) { + var button, myself = this; + + button = new ToggleButtonMorph( + null, this, function () { // action - myself.paper.currentTool = icon; - myself.paper.toolChanged(icon); + myself.paper.currentTool = icon; + myself.paper.toolChanged(icon); myself.refreshToolButtons(); if (icon === 'pipette') { myself.getUserColor(); - } - }, - new SymbolMorph(icon, 18), - function () {return myself.paper.currentTool === icon; } - ); - - button.hint = hint; - button.drawNew(); - button.fixLayout(); - return button; -}; - -PaintEditorMorph.prototype.pushButton = function (title, action, hint) { - return new PushButtonMorph( - this, - action, - title, - null, - hint - ); -}; + } + }, + new SymbolMorph(icon, 18), + function () {return myself.paper.currentTool === icon; } + ); + + button.hint = hint; + button.drawNew(); + button.fixLayout(); + return button; +}; + +PaintEditorMorph.prototype.pushButton = function (title, action, hint) { + return new PushButtonMorph( + this, + action, + title, + null, + hint + ); +}; PaintEditorMorph.prototype.getUserColor = function () { var myself = this, @@ -440,167 +441,167 @@ PaintEditorMorph.prototype.getUserColor = function () { hand.processMouseUp = mouseUpBak; }; }; - -// AdvancedColorPickerMorph ////////////////// - -// A large hsl color picker - -PaintColorPickerMorph.prototype = new Morph(); -PaintColorPickerMorph.prototype.constructor = PaintColorPickerMorph; -PaintColorPickerMorph.uber = Morph.prototype; - -function PaintColorPickerMorph(extent, action) { - this.init(extent, action); -} - -PaintColorPickerMorph.prototype.init = function (extent, action) { - this.setExtent(extent || new Point(200, 100)); - this.action = action || nop; - this.drawNew(); -}; - -PaintColorPickerMorph.prototype.drawNew = function () { - var x = 0, - y = 0, - can = newCanvas(this.extent()), - ctx = can.getContext("2d"), - colorselection, - r; - for (x = 0; x < this.width(); x += 1) { - for (y = 0; y < this.height() - 20; y += 1) { - ctx.fillStyle = "hsl(" + - (360 * x / this.width()) + - "," + - "100%," + - (y * 100 / (this.height() - 20)) + - "%)"; - ctx.fillRect(x, y, 1, 1); - } - } - for (x = 0; x < this.width(); x += 1) { - r = Math.floor(255 * x / this.width()); - ctx.fillStyle = "rgb(" + r + ", " + r + ", " + r + ")"; - ctx.fillRect(x, this.height() - 20, 1, 10); - } - colorselection = ["black", "white", "gray"]; - for (x = 0; x < colorselection.length; x += 1) { - ctx.fillStyle = colorselection[x]; - ctx.fillRect( - x * this.width() / colorselection.length, - this.height() - 10, - this.width() / colorselection.length, - 10 - ); - } - for (x = this.width() * 2 / 3; x < this.width(); x += 2) { - for (y = this.height() - 10; y < this.height(); y += 2) { - if ((x + y) / 2 % 2 === 0) { - ctx.fillStyle = "#DDD"; - ctx.fillRect(x, y, 2, 2); - } - } - } - this.image = can; -}; - -PaintColorPickerMorph.prototype.mouseDownLeft = function (pos) { - if ((pos.subtract(this.position()).x > this.width() * 2 / 3) && - (pos.subtract(this.position()).y > this.height() - 10)) { - this.action("transparent"); - } else { - this.action(this.getPixelColor(pos)); - } -}; - -PaintColorPickerMorph.prototype.mouseMove = + +// AdvancedColorPickerMorph ////////////////// + +// A large hsl color picker + +PaintColorPickerMorph.prototype = new Morph(); +PaintColorPickerMorph.prototype.constructor = PaintColorPickerMorph; +PaintColorPickerMorph.uber = Morph.prototype; + +function PaintColorPickerMorph(extent, action) { + this.init(extent, action); +} + +PaintColorPickerMorph.prototype.init = function (extent, action) { + this.setExtent(extent || new Point(200, 100)); + this.action = action || nop; + this.drawNew(); +}; + +PaintColorPickerMorph.prototype.drawNew = function () { + var x = 0, + y = 0, + can = newCanvas(this.extent()), + ctx = can.getContext("2d"), + colorselection, + r; + for (x = 0; x < this.width(); x += 1) { + for (y = 0; y < this.height() - 20; y += 1) { + ctx.fillStyle = "hsl(" + + (360 * x / this.width()) + + "," + + "100%," + + (y * 100 / (this.height() - 20)) + + "%)"; + ctx.fillRect(x, y, 1, 1); + } + } + for (x = 0; x < this.width(); x += 1) { + r = Math.floor(255 * x / this.width()); + ctx.fillStyle = "rgb(" + r + ", " + r + ", " + r + ")"; + ctx.fillRect(x, this.height() - 20, 1, 10); + } + colorselection = ["black", "white", "gray"]; + for (x = 0; x < colorselection.length; x += 1) { + ctx.fillStyle = colorselection[x]; + ctx.fillRect( + x * this.width() / colorselection.length, + this.height() - 10, + this.width() / colorselection.length, + 10 + ); + } + for (x = this.width() * 2 / 3; x < this.width(); x += 2) { + for (y = this.height() - 10; y < this.height(); y += 2) { + if ((x + y) / 2 % 2 === 0) { + ctx.fillStyle = "#DDD"; + ctx.fillRect(x, y, 2, 2); + } + } + } + this.image = can; +}; + +PaintColorPickerMorph.prototype.mouseDownLeft = function (pos) { + if ((pos.subtract(this.position()).x > this.width() * 2 / 3) && + (pos.subtract(this.position()).y > this.height() - 10)) { + this.action("transparent"); + } else { + this.action(this.getPixelColor(pos)); + } +}; + +PaintColorPickerMorph.prototype.mouseMove = PaintColorPickerMorph.prototype.mouseDownLeft; - + // PaintCanvasMorph /////////////////////////// /* - A canvas which reacts to drag events to + A canvas which reacts to drag events to modify its image, based on a 'tool' property. */ - -PaintCanvasMorph.prototype = new Morph(); -PaintCanvasMorph.prototype.constructor = PaintCanvasMorph; -PaintCanvasMorph.uber = Morph.prototype; - -function PaintCanvasMorph(shift) { - this.init(shift); -} - -PaintCanvasMorph.prototype.init = function (shift) { - this.rotationCenter = new Point(240, 180); - this.dragRect = null; - this.previousDragPoint = null; - this.currentTool = "brush"; - this.dragRect = new Rectangle(); - // rectangle with origin being the starting drag position and + +PaintCanvasMorph.prototype = new Morph(); +PaintCanvasMorph.prototype.constructor = PaintCanvasMorph; +PaintCanvasMorph.uber = Morph.prototype; + +function PaintCanvasMorph(shift) { + this.init(shift); +} + +PaintCanvasMorph.prototype.init = function (shift) { + this.rotationCenter = new Point(240, 180); + this.dragRect = null; + this.previousDragPoint = null; + this.currentTool = "brush"; + this.dragRect = new Rectangle(); + // rectangle with origin being the starting drag position and // corner being the current drag position - this.mask = newCanvas(this.extent()); // Temporary canvas - this.paper = newCanvas(this.extent()); // Actual canvas - this.erasermask = newCanvas(this.extent()); // eraser memory - this.background = newCanvas(this.extent()); // checkers - this.settings = { - "primarycolor": new Color(0, 0, 0, 255), // usually fill color - "secondarycolor": new Color(0, 0, 0, 255), // (unused) - "linewidth": 3 // stroke width - }; - this.brushBuffer = []; - this.undoBuffer = []; - this.isShiftPressed = shift || function () { - var key = this.world().currentKey; - return (key === 16); + this.mask = newCanvas(this.extent()); // Temporary canvas + this.paper = newCanvas(this.extent()); // Actual canvas + this.erasermask = newCanvas(this.extent()); // eraser memory + this.background = newCanvas(this.extent()); // checkers + this.settings = { + "primarycolor": new Color(0, 0, 0, 255), // usually fill color + "secondarycolor": new Color(0, 0, 0, 255), // (unused) + "linewidth": 3 // stroke width }; - this.buildContents(); -}; - -PaintCanvasMorph.prototype.cacheUndo = function () { - var cachecan = newCanvas(this.extent()); - this.merge(this.paper, cachecan); - this.undoBuffer.push(cachecan); -}; - -PaintCanvasMorph.prototype.undo = function () { - if (this.undoBuffer.length > 0) { - this.paper = newCanvas(this.extent()); - this.mask.width = this.mask.width + 1 - 1; - this.merge(this.undoBuffer.pop(), this.paper); - this.drawNew(); - this.changed(); - } -}; - -PaintCanvasMorph.prototype.merge = function (a, b) { - b.getContext("2d").drawImage(a, 0, 0); + this.brushBuffer = []; + this.undoBuffer = []; + this.isShiftPressed = shift || function () { + var key = this.world().currentKey; + return (key === 16); + }; + this.buildContents(); +}; + +PaintCanvasMorph.prototype.cacheUndo = function () { + var cachecan = newCanvas(this.extent()); + this.merge(this.paper, cachecan); + this.undoBuffer.push(cachecan); +}; + +PaintCanvasMorph.prototype.undo = function () { + if (this.undoBuffer.length > 0) { + this.paper = newCanvas(this.extent()); + this.mask.width = this.mask.width + 1 - 1; + this.merge(this.undoBuffer.pop(), this.paper); + this.drawNew(); + this.changed(); + } +}; + +PaintCanvasMorph.prototype.merge = function (a, b) { + b.getContext("2d").drawImage(a, 0, 0); }; - -PaintCanvasMorph.prototype.centermerge = function (a, b) { - b.getContext("2d").drawImage( - a, - (b.width - a.width) / 2, - (b.height - a.height) / 2 - ); -}; - + +PaintCanvasMorph.prototype.centermerge = function (a, b) { + b.getContext("2d").drawImage( + a, + (b.width - a.width) / 2, + (b.height - a.height) / 2 + ); +}; + PaintCanvasMorph.prototype.clearCanvas = function () { - this.buildContents(); - this.drawNew(); - this.changed(); -}; - -PaintCanvasMorph.prototype.toolChanged = function (tool) { - this.mask = newCanvas(this.extent()); - if (tool === "crosshairs") { - this.drawcrosshair(); - } - this.drawNew(); - this.changed(); -}; - -PaintCanvasMorph.prototype.drawcrosshair = function (context) { - var ctx = context || this.mask.getContext("2d"), - rp = this.rotationCenter; + this.buildContents(); + this.drawNew(); + this.changed(); +}; + +PaintCanvasMorph.prototype.toolChanged = function (tool) { + this.mask = newCanvas(this.extent()); + if (tool === "crosshairs") { + this.drawcrosshair(); + } + this.drawNew(); + this.changed(); +}; + +PaintCanvasMorph.prototype.drawcrosshair = function (context) { + var ctx = context || this.mask.getContext("2d"), + rp = this.rotationCenter; ctx.lineWidth = 1; ctx.strokeStyle = 'black'; @@ -646,32 +647,32 @@ PaintCanvasMorph.prototype.drawcrosshair = function (context) { ctx.moveTo(rp.x, 0); ctx.lineTo(rp.x, this.mask.height); ctx.stroke(); - - this.drawNew(); - this.changed(); -}; - + + this.drawNew(); + this.changed(); +}; + PaintCanvasMorph.prototype.floodfill = function (sourcepoint) { - var width = this.paper.width, - height = this.paper.height, - ctx = this.paper.getContext("2d"), - img = ctx.getImageData(0, 0, width, height), - data = img.data, - stack = [Math.round(sourcepoint.y) * width + sourcepoint.x], - currentpoint, - read, - sourcecolor, - checkpoint; - read = function (p) { - var d = p * 4; - return [data[d], data[d + 1], data[d + 2], data[d + 3]]; - }; - sourcecolor = read(stack[0]); - checkpoint = function (p) { - return p[0] === sourcecolor[0] && - p[1] === sourcecolor[1] && - p[2] === sourcecolor[2] && - p[3] === sourcecolor[3]; + var width = this.paper.width, + height = this.paper.height, + ctx = this.paper.getContext("2d"), + img = ctx.getImageData(0, 0, width, height), + data = img.data, + stack = [Math.round(sourcepoint.y) * width + sourcepoint.x], + currentpoint, + read, + sourcecolor, + checkpoint; + read = function (p) { + var d = p * 4; + return [data[d], data[d + 1], data[d + 2], data[d + 3]]; + }; + sourcecolor = read(stack[0]); + checkpoint = function (p) { + return p[0] === sourcecolor[0] && + p[1] === sourcecolor[1] && + p[2] === sourcecolor[2] && + p[3] === sourcecolor[3]; }; // if already filled, abort @@ -690,201 +691,204 @@ PaintCanvasMorph.prototype.floodfill = function (sourcepoint) { } while (stack.length > 0) { - currentpoint = stack.pop(); - if (checkpoint(read(currentpoint))) { - if (currentpoint % 480 > 1) { - stack.push(currentpoint + 1); - stack.push(currentpoint - 1); - } - if (currentpoint > 0 && currentpoint < 360 * 480) { - stack.push(currentpoint + width); - stack.push(currentpoint - width); - } - } - if (this.settings.primarycolor === "transparent") { - data[currentpoint * 4 + 3] = 0; - } else { - data[currentpoint * 4] = this.settings.primarycolor.r; - data[currentpoint * 4 + 1] = this.settings.primarycolor.g; - data[currentpoint * 4 + 2] = this.settings.primarycolor.b; - data[currentpoint * 4 + 3] = this.settings.primarycolor.a; - } - } + currentpoint = stack.pop(); + if (checkpoint(read(currentpoint))) { + if (currentpoint % 480 > 1) { + stack.push(currentpoint + 1); + stack.push(currentpoint - 1); + } + if (currentpoint > 0 && currentpoint < 360 * 480) { + stack.push(currentpoint + width); + stack.push(currentpoint - width); + } + } + if (this.settings.primarycolor === "transparent") { + data[currentpoint * 4 + 3] = 0; + } else { + data[currentpoint * 4] = this.settings.primarycolor.r; + data[currentpoint * 4 + 1] = this.settings.primarycolor.g; + data[currentpoint * 4 + 2] = this.settings.primarycolor.b; + data[currentpoint * 4 + 3] = this.settings.primarycolor.a; + } + } ctx.putImageData(img, 0, 0); this.drawNew(); this.changed(); -}; - -PaintCanvasMorph.prototype.mouseDownLeft = function (pos) { - this.cacheUndo(); - this.dragRect.origin = pos.subtract(this.bounds.origin); - this.dragRect.corner = pos.subtract(this.bounds.origin); - this.previousDragPoint = this.dragRect.corner.copy(); +}; + +PaintCanvasMorph.prototype.mouseDownLeft = function (pos) { + this.cacheUndo(); + this.dragRect.origin = pos.subtract(this.bounds.origin); + this.dragRect.corner = pos.subtract(this.bounds.origin); + this.previousDragPoint = this.dragRect.corner.copy(); if (this.currentTool === 'crosshairs') { this.rotationCenter = pos.subtract(this.bounds.origin); this.drawcrosshair(); return; } - if (this.currentTool === "paintbucket") { - return this.floodfill(pos.subtract(this.bounds.origin)); - } - if (this.settings.primarycolor === "transparent" && - this.currentTool !== "crosshairs") { - this.erasermask = newCanvas(this.extent()); - this.merge(this.paper, this.erasermask); - } -}; - + if (this.currentTool === "paintbucket") { + return this.floodfill(pos.subtract(this.bounds.origin)); + } + if (this.settings.primarycolor === "transparent" && + this.currentTool !== "crosshairs") { + this.erasermask = newCanvas(this.extent()); + this.merge(this.paper, this.erasermask); + } +}; + PaintCanvasMorph.prototype.mouseMove = function (pos) { if (this.currentTool === "paintbucket") { return; } - - var relpos = pos.subtract(this.bounds.origin), - mctx = this.mask.getContext("2d"), - pctx = this.paper.getContext("2d"), - x = this.dragRect.origin.x, // original drag X - y = this.dragRect.origin.y, // original drag y - p = relpos.x, // current drag x - q = relpos.y, // current drag y - w = (p - x) / 2, // half the rect width - h = (q - y) / 2, // half the rect height - i; // iterator number - mctx.save(); - function newW() { - return Math.max(Math.abs(w), Math.abs(h)) * (w / Math.abs(w)); - } - function newH() { - return Math.max(Math.abs(w), Math.abs(h)) * (h / Math.abs(h)); - } - this.brushBuffer.push([p, q]); - mctx.lineWidth = this.settings.linewidth; - mctx.clearRect(0, 0, this.bounds.width(), this.bounds.height()); // mask - - this.dragRect.corner = relpos.subtract(this.dragRect.origin); // reset crn - - if (this.settings.primarycolor === "transparent" && - this.currentTool !== "crosshairs") { - this.merge(this.erasermask, this.mask); - pctx.clearRect(0, 0, this.bounds.width(), this.bounds.height()); - mctx.globalCompositeOperation = "destination-out"; - } else { - mctx.fillStyle = this.settings.primarycolor.toString(); - mctx.strokeStyle = this.settings.primarycolor.toString(); - } - switch (this.currentTool) { - case "rectangle": - if (this.isShiftPressed()) { - mctx.strokeRect(x, y, newW() * 2, newH() * 2); - } else { - mctx.strokeRect(x, y, w * 2, h * 2); - } - break; - case "rectangleSolid": - if (this.isShiftPressed()) { - mctx.fillRect(x, y, newW() * 2, newH() * 2); - } else { - mctx.fillRect(x, y, w * 2, h * 2); - } - break; - case "brush": - mctx.lineCap = "round"; - mctx.lineJoin = "round"; - mctx.beginPath(); - mctx.moveTo(this.brushBuffer[0][0], this.brushBuffer[0][1]); - for (i = 0; i < this.brushBuffer.length; i += 1) { - mctx.lineTo(this.brushBuffer[i][0], this.brushBuffer[i][1]); - } - mctx.stroke(); - break; - case "line": - mctx.beginPath(); - mctx.moveTo(x, y); - if (this.isShiftPressed()) { - if (Math.abs(h) > Math.abs(w)) { - mctx.lineTo(x, q); - } else { - mctx.lineTo(p, y); - } - } else { - mctx.lineTo(p, q); - } - mctx.stroke(); - break; - case "circle": - case "circleSolid": - mctx.beginPath(); - if (this.isShiftPressed()) { - mctx.arc( - x, - y, - new Point(x, y).distanceTo(new Point(p, q)), - 0, - Math.PI * 2, - false - ); - } else { - for (i = 0; i < 480; i += 1) { - mctx.lineTo( - i, - (2 * h) * Math.sqrt(2 - Math.pow( - (i - x) / (2 * w), - 2 - )) + y - ); - } - for (i = 480; i > 0; i -= 1) { - mctx.lineTo( - i, - -1 * (2 * h) * Math.sqrt(2 - Math.pow( - (i - x) / (2 * w), - 2 - )) + y - ); - } - } - mctx.closePath(); - if (this.currentTool === "circleSolid") { - mctx.fill(); - } else { - if (this.currentTool === "circle") { - mctx.stroke(); - } - } - break; + + var relpos = pos.subtract(this.bounds.origin), + mctx = this.mask.getContext("2d"), + pctx = this.paper.getContext("2d"), + x = this.dragRect.origin.x, // original drag X + y = this.dragRect.origin.y, // original drag y + p = relpos.x, // current drag x + q = relpos.y, // current drag y + w = (p - x) / 2, // half the rect width + h = (q - y) / 2, // half the rect height + i; // iterator number + mctx.save(); + function newW() { + return Math.max(Math.abs(w), Math.abs(h)) * (w / Math.abs(w)); + } + function newH() { + return Math.max(Math.abs(w), Math.abs(h)) * (h / Math.abs(h)); + } + this.brushBuffer.push([p, q]); + mctx.lineWidth = this.settings.linewidth; + mctx.clearRect(0, 0, this.bounds.width(), this.bounds.height()); // mask + + this.dragRect.corner = relpos.subtract(this.dragRect.origin); // reset crn + + if (this.settings.primarycolor === "transparent" && + this.currentTool !== "crosshairs") { + this.merge(this.erasermask, this.mask); + pctx.clearRect(0, 0, this.bounds.width(), this.bounds.height()); + mctx.globalCompositeOperation = "destination-out"; + } else { + mctx.fillStyle = this.settings.primarycolor.toString(); + mctx.strokeStyle = this.settings.primarycolor.toString(); + } + switch (this.currentTool) { + case "rectangle": + if (this.isShiftPressed()) { + mctx.strokeRect(x, y, newW() * 2, newH() * 2); + } else { + mctx.strokeRect(x, y, w * 2, h * 2); + } + break; + case "rectangleSolid": + if (this.isShiftPressed()) { + mctx.fillRect(x, y, newW() * 2, newH() * 2); + } else { + mctx.fillRect(x, y, w * 2, h * 2); + } + break; + case "brush": + mctx.lineCap = "round"; + mctx.lineJoin = "round"; + mctx.beginPath(); + mctx.moveTo(this.brushBuffer[0][0], this.brushBuffer[0][1]); + for (i = 0; i < this.brushBuffer.length; i += 1) { + mctx.lineTo(this.brushBuffer[i][0], this.brushBuffer[i][1]); + } + mctx.stroke(); + break; + case "line": + mctx.beginPath(); + mctx.moveTo(x, y); + if (this.isShiftPressed()) { + if (Math.abs(h) > Math.abs(w)) { + mctx.lineTo(x, q); + } else { + mctx.lineTo(p, y); + } + } else { + mctx.lineTo(p, q); + } + mctx.stroke(); + break; + case "circle": + case "circleSolid": + mctx.beginPath(); + if (this.isShiftPressed()) { + mctx.arc( + x, + y, + new Point(x, y).distanceTo(new Point(p, q)), + 0, + Math.PI * 2, + false + ); + } else { + for (i = 0; i < 480; i += 1) { + mctx.lineTo( + i, + (2 * h) * Math.sqrt(2 - Math.pow( + (i - x) / (2 * w), + 2 + )) + y + ); + } + for (i = 480; i > 0; i -= 1) { + mctx.lineTo( + i, + -1 * (2 * h) * Math.sqrt(2 - Math.pow( + (i - x) / (2 * w), + 2 + )) + y + ); + } + } + mctx.closePath(); + if (this.currentTool === "circleSolid") { + mctx.fill(); + } else { + if (this.currentTool === "circle") { + mctx.stroke(); + } + } + break; case "crosshairs": this.rotationCenter = relpos.copy(); this.drawcrosshair(mctx); - break; - case "eraser": - this.merge(this.paper, this.mask); - mctx.save(); - mctx.globalCompositeOperation = "destination-out"; - mctx.beginPath(); - mctx.moveTo(this.brushBuffer[0][0], this.brushBuffer[0][1]); - for (i = 0; i < this.brushBuffer.length; i += 1) { - mctx.lineTo(this.brushBuffer[i][0], this.brushBuffer[i][1]); - } - mctx.stroke(); - mctx.restore(); - this.paper = newCanvas(this.extent()); - this.merge(this.mask, this.paper); - break; - default: - nop(); - } - this.previousDragPoint = relpos; - this.drawNew(); - this.changed(); - mctx.restore(); -}; - + break; + case "eraser": + this.merge(this.paper, this.mask); + mctx.save(); + mctx.globalCompositeOperation = "destination-out"; + mctx.beginPath(); + mctx.moveTo(this.brushBuffer[0][0], this.brushBuffer[0][1]); + for (i = 0; i < this.brushBuffer.length; i += 1) { + mctx.lineTo(this.brushBuffer[i][0], this.brushBuffer[i][1]); + } + mctx.stroke(); + mctx.restore(); + this.paper = newCanvas(this.extent()); + this.merge(this.mask, this.paper); + break; + default: + nop(); + } + this.previousDragPoint = relpos; + this.drawNew(); + this.changed(); + mctx.restore(); +}; + PaintCanvasMorph.prototype.mouseClickLeft = function () { - if (this.currentTool !== "crosshairs") { - this.merge(this.mask, this.paper); - } - this.brushBuffer = []; -}; + if (this.currentTool !== "crosshairs") { + this.merge(this.mask, this.paper); + } + this.brushBuffer = []; +}; + +PaintCanvasMorph.prototype.mouseLeaveDragging + = PaintCanvasMorph.prototype.mouseClickLeft; PaintCanvasMorph.prototype.buildContents = function () { this.background = newCanvas(this.extent()); @@ -903,47 +907,47 @@ PaintCanvasMorph.prototype.buildContents = function () { } } }; - -PaintCanvasMorph.prototype.drawNew = function () { - var can = newCanvas(this.extent()); - this.merge(this.background, can); - this.merge(this.paper, can); - this.merge(this.mask, can); - this.image = can; - this.drawFrame(); -}; - -PaintCanvasMorph.prototype.drawFrame = function () { - var context, borderColor; - - context = this.image.getContext('2d'); - if (this.parent) { - this.color = this.parent.color.lighter(this.contrast * 0.75); - borderColor = this.parent.color; - } else { - borderColor = new Color(120, 120, 120); - } - context.fillStyle = this.color.toString(); - - // cache my border colors - this.cachedClr = borderColor.toString(); - this.cachedClrBright = borderColor.lighter(this.contrast) - .toString(); - this.cachedClrDark = borderColor.darker(this.contrast).toString(); - this.drawRectBorder(context); -}; - -PaintCanvasMorph.prototype.drawRectBorder - = InputFieldMorph.prototype.drawRectBorder; - -PaintCanvasMorph.prototype.edge - = InputFieldMorph.prototype.edge; - -PaintCanvasMorph.prototype.fontSize - = InputFieldMorph.prototype.fontSize; - -PaintCanvasMorph.prototype.typeInPadding - = InputFieldMorph.prototype.typeInPadding; - -PaintCanvasMorph.prototype.contrast - = InputFieldMorph.prototype.contrast; + +PaintCanvasMorph.prototype.drawNew = function () { + var can = newCanvas(this.extent()); + this.merge(this.background, can); + this.merge(this.paper, can); + this.merge(this.mask, can); + this.image = can; + this.drawFrame(); +}; + +PaintCanvasMorph.prototype.drawFrame = function () { + var context, borderColor; + + context = this.image.getContext('2d'); + if (this.parent) { + this.color = this.parent.color.lighter(this.contrast * 0.75); + borderColor = this.parent.color; + } else { + borderColor = new Color(120, 120, 120); + } + context.fillStyle = this.color.toString(); + + // cache my border colors + this.cachedClr = borderColor.toString(); + this.cachedClrBright = borderColor.lighter(this.contrast) + .toString(); + this.cachedClrDark = borderColor.darker(this.contrast).toString(); + this.drawRectBorder(context); +}; + +PaintCanvasMorph.prototype.drawRectBorder + = InputFieldMorph.prototype.drawRectBorder; + +PaintCanvasMorph.prototype.edge + = InputFieldMorph.prototype.edge; + +PaintCanvasMorph.prototype.fontSize + = InputFieldMorph.prototype.fontSize; + +PaintCanvasMorph.prototype.typeInPadding + = InputFieldMorph.prototype.typeInPadding; + +PaintCanvasMorph.prototype.contrast + = InputFieldMorph.prototype.contrast; -- cgit v1.3.1 From 71c458e7e895d2f434cd2cb2401da882558b923a Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 8 Jan 2014 15:23:09 +0100 Subject: Only shrink-wrap sprite costumes thanks, Kartik, for this fix! --- history.txt | 1 + objects.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/history.txt b/history.txt index 37d1d6b..168b255 100755 --- a/history.txt +++ b/history.txt @@ -2050,3 +2050,4 @@ ______ * Threads, Blocks, Objects: The FOR reporter’s first input now also accepts blocks and scripts („rings“), and reports a copy that is bound to the sprite indicated by the second input. This lets you „zombify“ (or remote-control) sprites (and create custom TELL and ASK blocks) * Blocks: initial support for „sensing“ sprite-only custom block definitions, commented out for now * Paint: Add mouseLeaveDragging() event behavior, thanks, Kartik, for this fix! +* Objects: Only shrink-wrap sprite costumes, thanks, Kartik, for this fix! diff --git a/objects.js b/objects.js index 67eb143..e8a934e 100644 --- a/objects.js +++ b/objects.js @@ -5263,7 +5263,10 @@ Costume.prototype.edit = function (aWorld, anIDE, isnew, oncancel, onsubmit) { function (img, rc) { myself.contents = img; myself.rotationCenter = rc; - myself.shrinkWrap(); + if (anIDE.currentSprite instanceof SpriteMorph) { + // don't shrinkwrap stage costumes + myself.shrinkWrap(); + } myself.version = Date.now(); aWorld.changed(); if (anIDE) { -- cgit v1.3.1 From 1e959b8891df838b18c3bae40ba941c5f74df5cb Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 8 Jan 2014 17:51:34 +0100 Subject: fixed StopOthers blocks and added another option also updated the German translation --- blocks.js | 13 +++++++++++++ lang-de.js | 8 +++++++- locale.js | 4 ++-- objects.js | 3 ++- threads.js | 44 ++++++++++++++++++++++++++------------------ 5 files changed, 50 insertions(+), 22 deletions(-) diff --git a/blocks.js b/blocks.js index 8b6bcc2..1ad2239 100644 --- a/blocks.js +++ b/blocks.js @@ -1037,6 +1037,19 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { ); part.setContents(['encode URI']); break; + case '%stopOthersChoices': + part = new InputSlotMorph( + null, + false, + { + 'all but this script' : ['all but this script'], + 'other scripts in sprite' : ['other scripts in sprite'] + }, + true + ); + part.setContents(['all but this script']); + part.isStatic = true; + break; case '%typ': part = new InputSlotMorph( null, diff --git a/lang-de.js b/lang-de.js index dec6092..1ed3f4f 100644 --- a/lang-de.js +++ b/lang-de.js @@ -185,7 +185,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', // optional 'last_changed': - '2013-10-04', // this, too, will appear in the Translators tab + '2018-01-08', // this, too, will appear in the Translators tab // GUI // control bar: @@ -453,6 +453,12 @@ SnapTranslator.dict.de = { 'stoppe dieses Skript', 'stop all %stop': 'stoppe alles %stop', + 'stop %stopOthersChoices': + 'stoppe %stopOthersChoices', + 'all but this script': + 'alles au\u00dfer diesem Skript', + 'other scripts in sprite': + 'andere Skripte in diesem Objekt', 'pause all %pause': 'pausiere alles %pause', 'run %cmdRing %inputs': diff --git a/locale.js b/locale.js index f894050..fd12371 100644 --- a/locale.js +++ b/locale.js @@ -42,7 +42,7 @@ /*global modules, contains*/ -modules.locale = '2013-December-04'; +modules.locale = '2014-January-08'; // Global stuff @@ -149,7 +149,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', 'last_changed': - '2013-10-04' + '2014-01-08' }; SnapTranslator.dict.it = { diff --git a/objects.js b/objects.js index fa9be12..9f892d4 100644 --- a/objects.js +++ b/objects.js @@ -594,7 +594,7 @@ SpriteMorph.prototype.initBlocks = function () { doStopOthers: { type: 'command', category: 'control', - spec: 'stop other scripts in sprite' + spec: 'stop %stopOthersChoices' }, doRun: { type: 'command', @@ -4361,6 +4361,7 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push(block('doStopBlock')); blocks.push(block('doStop')); blocks.push(block('doStopAll')); + blocks.push(block('doStopOthers')); blocks.push('-'); blocks.push(block('doRun')); blocks.push(block('fork')); diff --git a/threads.js b/threads.js index 7d7b50a..8c3eb25 100644 --- a/threads.js +++ b/threads.js @@ -151,26 +151,19 @@ ThreadManager.prototype.startProcess = function (block, isThreadSafe) { return newProc; }; -ThreadManager.prototype.stopAll = function () { +ThreadManager.prototype.stopAll = function (excpt) { + // excpt is optional this.processes.forEach(function (proc) { - proc.stop(); - }); -}; - -ThreadManager.prototype.stopAllForReceiver = function (rcvr) { - this.processes.forEach(function (proc) { - if (proc.homeContext.receiver === rcvr) { + if (proc !== excpt) { proc.stop(); - if (rcvr.isClone) { - proc.isDead = true; - } } }); }; -ThreadManager.prototype.stopAllForReceiverExcept = function (rcvr, excpt) { +ThreadManager.prototype.stopAllForReceiver = function (rcvr, excpt) { + // excpt is optional this.processes.forEach(function (proc) { - if (proc.homeContext.receiver === rcvr && proc != excpt) { + if (proc.homeContext.receiver === rcvr && proc !== excpt) { proc.stop(); if (rcvr.isClone) { proc.isDead = true; @@ -1379,12 +1372,25 @@ Process.prototype.doStopAll = function () { } }; -Process.prototype.doStopOthers = function () { - var stage, ide; +Process.prototype.doStopOthers = function (choice) { + var stage; if (this.homeContext.receiver) { stage = this.homeContext.receiver.parentThatIsA(StageMorph); if (stage) { - stage.threads.stopAllForReceiverExcept(this.homeContext.receiver, this); + + switch (this.inputOption(choice)) { + case 'all but this script': + stage.threads.stopAll(this); + break; + case 'other scripts in sprite': + stage.threads.stopAllForReceiver( + this.homeContext.receiver, + this + ); + break; + default: + nop(); + } } } }; @@ -1751,8 +1757,10 @@ Process.prototype.reportURL = function (url) { if (!this.httpRequest) { this.httpRequest = new XMLHttpRequest(); this.httpRequest.open("GET", 'http://' + url, true); - this.httpRequest.setRequestHeader("X-Requested-With", - "XMLHttpRequest"); + this.httpRequest.setRequestHeader( + "X-Requested-With", + "XMLHttpRequest" + ); this.httpRequest.setRequestHeader("X-Application", "Snap! 4.0"); this.httpRequest.send(null); } else if (this.httpRequest.readyState === 4) { -- cgit v1.3.1 From af4561069270085319375b3c6ff548cae82cafd2 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 8 Jan 2014 17:58:11 +0100 Subject: updated history --- history.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/history.txt b/history.txt index 168b255..a82204d 100755 --- a/history.txt +++ b/history.txt @@ -2051,3 +2051,7 @@ ______ * Blocks: initial support for „sensing“ sprite-only custom block definitions, commented out for now * Paint: Add mouseLeaveDragging() event behavior, thanks, Kartik, for this fix! * Objects: Only shrink-wrap sprite costumes, thanks, Kartik, for this fix! +* Threads: Added xhr-headers to HTTP block, thanks, Tim! +* Threads, Blocks, Objects: Added StopOthers primitive, thanks, Kartik! +* Added „all but this option“ to StopOthers primitive, fixed the implementation +* Updated German translation with new strings -- cgit v1.3.1 From 8a1ca3116b834625e6f71c6376c115975d4f9d75 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 9 Jan 2014 15:34:12 +0100 Subject: Collapse STOP primitives into a single block with a dropdown of options --- blocks.js | 17 ++++++++++++++++- history.txt | 5 +++++ objects.js | 55 ++++++++++++++++++++++++++++++++++++++++++++++--------- threads.js | 19 +++++++++++++++++-- 4 files changed, 84 insertions(+), 12 deletions(-) diff --git a/blocks.js b/blocks.js index 1ad2239..9997d70 100644 --- a/blocks.js +++ b/blocks.js @@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2014-January-08'; +modules.blocks = '2014-January-09'; var SyntaxElementMorph; var BlockMorph; @@ -1037,6 +1037,20 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { ); part.setContents(['encode URI']); break; + case '%stopChoices': + part = new InputSlotMorph( + null, + false, + { + 'all' : ['all'], + 'this script' : ['this script'], + 'this block' : ['this block'] + }, + true + ); + part.setContents(['all']); + part.isStatic = true; + break; case '%stopOthersChoices': part = new InputSlotMorph( null, @@ -3279,6 +3293,7 @@ CommandBlockMorph.prototype.snap = function () { CommandBlockMorph.prototype.isStop = function () { return ([ + 'doStopThis', 'doStop', 'doStopBlock', 'doStopAll', diff --git a/history.txt b/history.txt index a82204d..70c57bc 100755 --- a/history.txt +++ b/history.txt @@ -2055,3 +2055,8 @@ ______ * Threads, Blocks, Objects: Added StopOthers primitive, thanks, Kartik! * Added „all but this option“ to StopOthers primitive, fixed the implementation * Updated German translation with new strings + +140109 +------ +* Objects: Mechanism for migrating blocks in existing projects to newer versions +* Blocks, Objects, Threads: Collapse old STOP primitives into a single one with a dropdown of options diff --git a/objects.js b/objects.js index 9f892d4..3f3df76 100644 --- a/objects.js +++ b/objects.js @@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-January-08'; +modules.objects = '2014-January-09'; var SpriteMorph; var StageMorph; @@ -581,6 +581,9 @@ SpriteMorph.prototype.initBlocks = function () { category: 'control', spec: 'if %b %c else %c' }, + + /* migrated to a newer block version: + doStop: { type: 'command', category: 'control', @@ -591,6 +594,13 @@ SpriteMorph.prototype.initBlocks = function () { category: 'control', spec: 'stop all %stop' }, + */ + + doStopThis: { + type: 'command', + category: 'control', + spec: 'stop %stopChoices' + }, doStopOthers: { type: 'command', category: 'control', @@ -635,11 +645,13 @@ SpriteMorph.prototype.initBlocks = function () { category: 'control', spec: 'report %s' }, - doStopBlock: { + /* + doStopBlock: { // migrated to a newer block version type: 'command', category: 'control', spec: 'stop block' }, + */ doCallCC: { type: 'command', category: 'control', @@ -1084,6 +1096,25 @@ SpriteMorph.prototype.initBlocks = function () { SpriteMorph.prototype.initBlocks(); +SpriteMorph.prototype.initBlockMigrations = function () { + SpriteMorph.prototype.blockMigrations = { + doStopAll: { + selector: 'doStopThis', + inputs: [['all']] + }, + doStop: { + selector: 'doStopThis', + inputs: [['this script']] + }, + doStopBlock: { + selector: 'doStopThis', + inputs: [['this block']] + } + }; +}; + +SpriteMorph.prototype.initBlockMigrations(); + SpriteMorph.prototype.blockAlternatives = { // motion: turn: ['turnLeft'], @@ -1130,9 +1161,6 @@ SpriteMorph.prototype.blockAlternatives = { receiveClick: ['receiveGo'], doBroadcast: ['doBroadcastAndWait'], doBroadcastAndWait: ['doBroadcast'], - doStopBlock: ['doStop', 'doStopAll'], - doStop: ['doStopBlock', 'doStopAll'], - doStopAll: ['doStopBlock', 'doStop'], // sensing: getLastAnswer: ['getTimer'], @@ -1412,8 +1440,9 @@ SpriteMorph.prototype.colorFiltered = function (aColor) { // SpriteMorph block instantiation SpriteMorph.prototype.blockForSelector = function (selector, setDefaults) { - var info, block, defaults, inputs, i; - info = this.blocks[selector]; + var migration, info, block, defaults, inputs, i; + migration = this.blockMigrations[selector]; + info = this.blocks[migration ? migration.selector : selector]; if (!info) {return null; } block = info.type === 'command' ? new CommandBlockMorph() : info.type === 'hat' ? new HatBlockMorph() @@ -1426,8 +1455,8 @@ SpriteMorph.prototype.blockForSelector = function (selector, setDefaults) { block.isStatic = true; } block.setSpec(localize(info.spec)); - if (setDefaults && info.defaults) { - defaults = info.defaults; + if ((setDefaults && info.defaults) || (migration && migration.inputs)) { + defaults = migration ? migration.inputs : info.defaults; block.defaults = defaults; inputs = block.inputs(); if (inputs[0] instanceof MultiArgMorph) { @@ -1651,9 +1680,13 @@ SpriteMorph.prototype.blockTemplates = function (category) { blocks.push('-'); blocks.push(block('doReport')); blocks.push('-'); + /* + // old STOP variants, migrated to a newer version, now redundant blocks.push(block('doStopBlock')); blocks.push(block('doStop')); blocks.push(block('doStopAll')); + */ + blocks.push(block('doStopThis')); blocks.push(block('doStopOthers')); blocks.push('-'); blocks.push(block('doRun')); @@ -4358,9 +4391,13 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push('-'); blocks.push(block('doReport')); blocks.push('-'); + /* + // old STOP variants, migrated to a newer version, now redundant blocks.push(block('doStopBlock')); blocks.push(block('doStop')); blocks.push(block('doStopAll')); + */ + blocks.push(block('doStopThis')); blocks.push(block('doStopOthers')); blocks.push('-'); blocks.push(block('doRun')); diff --git a/threads.js b/threads.js index 8c3eb25..79af3b9 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2014-January-08'; +modules.threads = '2014-January-09'; var ThreadManager; var Process; @@ -1372,12 +1372,27 @@ Process.prototype.doStopAll = function () { } }; +Process.prototype.doStopThis = function (choice) { + switch (this.inputOption(choice)) { + case 'all': + this.doStopAll(); + break; + case 'this script': + this.doStop(); + break; + case 'this block': + this.doStopBlock(); + break; + default: + nop(); + } +}; + Process.prototype.doStopOthers = function (choice) { var stage; if (this.homeContext.receiver) { stage = this.homeContext.receiver.parentThatIsA(StageMorph); if (stage) { - switch (this.inputOption(choice)) { case 'all but this script': stage.threads.stopAll(this); -- cgit v1.3.1 From 5cb8003542499f7e9fb7f590b05628c59ae4df39 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 9 Jan 2014 15:36:00 +0100 Subject: German translation update for new (migrated) STOP block --- history.txt | 1 + lang-de.js | 18 +++++++++--------- locale.js | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/history.txt b/history.txt index 70c57bc..63935ec 100755 --- a/history.txt +++ b/history.txt @@ -2060,3 +2060,4 @@ ______ ------ * Objects: Mechanism for migrating blocks in existing projects to newer versions * Blocks, Objects, Threads: Collapse old STOP primitives into a single one with a dropdown of options +* German translation update for new (migrated) STOP block diff --git a/lang-de.js b/lang-de.js index 1ed3f4f..2013833 100644 --- a/lang-de.js +++ b/lang-de.js @@ -185,7 +185,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', // optional 'last_changed': - '2018-01-08', // this, too, will appear in the Translators tab + '2014-01-09', // this, too, will appear in the Translators tab // GUI // control bar: @@ -447,12 +447,14 @@ SnapTranslator.dict.de = { 'falls %b %c sonst %c', 'report %s': 'berichte %s', - 'stop block': - 'stoppe diesen Block', - 'stop script': - 'stoppe dieses Skript', - 'stop all %stop': - 'stoppe alles %stop', + 'stop %stopChoices': + 'stoppe %stopChoices', + 'all': + 'alles', + 'this script': + 'dieses Skript', + 'this block': + 'diesen Block', 'stop %stopOthersChoices': 'stoppe %stopOthersChoices', 'all but this script': @@ -956,8 +958,6 @@ SnapTranslator.dict.de = { 'in diesem Projekt gibt es noch keine\nglobalen Bl\u00f6cke', 'select': 'ausw\u00e4hlen', - 'all': - 'alles', 'none': 'nichts', diff --git a/locale.js b/locale.js index fd12371..eb79862 100644 --- a/locale.js +++ b/locale.js @@ -42,7 +42,7 @@ /*global modules, contains*/ -modules.locale = '2014-January-08'; +modules.locale = '2014-January-09'; // Global stuff @@ -149,7 +149,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', 'last_changed': - '2014-01-08' + '2014-01-09' }; SnapTranslator.dict.it = { -- cgit v1.3.1 From 4a60bfba18c3ff7bd929402737d208b53f4d7229 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 9 Jan 2014 17:49:44 +0100 Subject: Fixed Morphic updateReferences() how could this go undetected so long? :-) --- history.txt | 1 + morphic.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/history.txt b/history.txt index 63935ec..20b4f65 100755 --- a/history.txt +++ b/history.txt @@ -2061,3 +2061,4 @@ ______ * Objects: Mechanism for migrating blocks in existing projects to newer versions * Blocks, Objects, Threads: Collapse old STOP primitives into a single one with a dropdown of options * German translation update for new (migrated) STOP block +* Morphic: Fixed updateReferences() (how could nobody notice so long?!) diff --git a/morphic.js b/morphic.js index b3c9769..c5aa561 100644 --- a/morphic.js +++ b/morphic.js @@ -8,7 +8,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. @@ -1035,7 +1035,7 @@ /*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio, FileList, getBlurredShadowSupport*/ -var morphicVersion = '2013-December-12'; +var morphicVersion = '2014-January-09'; var modules = {}; // keep track of additional loaded modules var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug @@ -3068,7 +3068,7 @@ Morph.prototype.updateReferences = function (dict) { */ var property; for (property in this) { - if (property.isMorph && dict[property]) { + if (this[property] && this[property].isMorph && dict[property]) { this[property] = dict[property]; } } -- cgit v1.3.1 From 3345081d73106b471c39ba41b85b823152dbe797 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 9 Jan 2014 18:42:03 +0100 Subject: XML.js: resolved unexpected assignment expressions conform to the latest JSLint quibbles --- history.txt | 1 + xml.js | 36 ++++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/history.txt b/history.txt index 20b4f65..2411d8f 100755 --- a/history.txt +++ b/history.txt @@ -2062,3 +2062,4 @@ ______ * Blocks, Objects, Threads: Collapse old STOP primitives into a single one with a dropdown of options * German translation update for new (migrated) STOP block * Morphic: Fixed updateReferences() (how could nobody notice so long?!) +* Store: resolved unexpected assignment expressions (conform to the latest JSLint quibbles) diff --git a/xml.js b/xml.js index cc3c609..fb612ce 100644 --- a/xml.js +++ b/xml.js @@ -7,7 +7,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. @@ -65,7 +65,7 @@ // Global stuff //////////////////////////////////////////////////////// -modules.xml = '2013-April-19'; +modules.xml = '2014-January-09'; // Declarations @@ -90,13 +90,15 @@ ReadStream.prototype.space = /[\s]/; // ReadStream accessing: ReadStream.prototype.next = function (count) { - var element; + var element, start; if (count === undefined) { element = this.contents[this.index]; this.index += 1; return element; } - return this.contents.slice(this.index, this.index += count); + start = this.index; + this.index += count; + return this.contents.slice(start, this.index); }; ReadStream.prototype.peek = function () { @@ -114,12 +116,15 @@ ReadStream.prototype.atEnd = function () { // ReadStream accessing String contents: ReadStream.prototype.upTo = function (regex) { + var i, start; if (!isString(this.contents)) {return ''; } - var i = this.contents.substr(this.index).search(regex); + i = this.contents.substr(this.index).search(regex); if (i === -1) { return ''; } - return this.contents.substring(this.index, this.index += i); + start = this.index; + this.index += i; + return this.contents.substring(start, this.index); }; ReadStream.prototype.peekUpTo = function (regex) { @@ -133,19 +138,23 @@ ReadStream.prototype.peekUpTo = function (regex) { ReadStream.prototype.skipSpace = function () { if (!isString(this.contents)) {return ''; } - var ch; - while (this.space.test(ch = this.peek()) && ch !== '') { + var ch = this.peek(); + while (this.space.test(ch) && ch !== '') { this.skip(); + ch = this.peek(); } }; ReadStream.prototype.word = function () { + var i, start; if (!isString(this.contents)) {return ''; } - var i = this.contents.substr(this.index).search(/[\s\>\/\=]|$/); + i = this.contents.substr(this.index).search(/[\s\>\/\=]|$/); if (i === -1) { return ''; } - return this.contents.substring(this.index, this.index += i); + start = this.index; + this.index += i; + return this.contents.substring(start, this.index); }; // XML_Element /////////////////////////////////////////////////////////// @@ -376,14 +385,16 @@ XML_Element.prototype.parseStream = function (stream) { stream.skipSpace(); // attributes: - while ((ch = stream.peek()) !== '>' && ch !== '/') { + ch = stream.peek(); + while (ch !== '>' && ch !== '/') { key = stream.word(); stream.skipSpace(); if (stream.next() !== '=') { throw new Error('Expected "=" after attribute name'); } stream.skipSpace(); - if ((ch = stream.next()) !== '"' && ch !== "'") { + ch = stream.next(); + if (ch !== '"' && ch !== "'") { throw new Error( 'Expected single- or double-quoted attribute value' ); @@ -392,6 +403,7 @@ XML_Element.prototype.parseStream = function (stream) { stream.skip(1); stream.skipSpace(); this.attributes[key] = this.unescape(value); + ch = stream.peek(); } // empty tag: -- cgit v1.3.1 From fa88fdc761faa224d307e833f74163df48cedb0c Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 9 Jan 2014 18:50:38 +0100 Subject: validated all source files against the latest JSLint version and pushed to this date --- README.md | 2 +- blocks.js | 2 +- byob.js | 4 ++-- cloud.js | 7 ++----- gui.js | 6 +++--- history.txt | 3 ++- lang-de.js | 2 +- lists.js | 4 ++-- locale.js | 2 +- objects.js | 2 +- paint.js | 4 ++-- store.js | 4 ++-- threads.js | 2 +- widgets.js | 4 ++-- 14 files changed, 23 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 8564d27..cf17e18 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ inspired by Scratch written by Jens Mönig and Brian Harvey jens@moenig.org, bh@cs.berkeley.edu -Copyright (C) 2013 by Jens Mönig and Brian Harvey +Copyright (C) 2014 by Jens Mönig and Brian Harvey Snap! is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/blocks.js b/blocks.js index 9997d70..0ce1478 100644 --- a/blocks.js +++ b/blocks.js @@ -9,7 +9,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. diff --git a/byob.js b/byob.js index 8093266..aff32ad 100644 --- a/byob.js +++ b/byob.js @@ -9,7 +9,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. @@ -106,7 +106,7 @@ SymbolMorph, isNil*/ // Global stuff //////////////////////////////////////////////////////// -modules.byob = '2013-November-26'; +modules.byob = '2014-January-09'; // Declarations diff --git a/cloud.js b/cloud.js index 5ff2f77..17fc76b 100644 --- a/cloud.js +++ b/cloud.js @@ -6,7 +6,7 @@ written by Jens Mönig - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. @@ -29,7 +29,7 @@ /*global modules, IDE_Morph, SnapSerializer, hex_sha512, alert, nop*/ -modules.cloud = '2013-November-26'; +modules.cloud = '2014-January-09'; // Global stuff @@ -37,9 +37,6 @@ var Cloud; var SnapCloud = new Cloud( 'https://snapcloud.miosoft.com/miocon/app/login?_app=SnapCloud' - //'192.168.2.110:8087/miocon/app/login?_app=SnapCloud' - //'192.168.186.146:8087/miocon/app/login?_app=SnapCloud' - // 'localhost/miocon/app/login?_app=SnapCloud' ); // Cloud ///////////////////////////////////////////////////////////// diff --git a/gui.js b/gui.js index d7f562e..0adc325 100644 --- a/gui.js +++ b/gui.js @@ -9,7 +9,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. @@ -68,7 +68,7 @@ sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.gui = '2013-November-07'; +modules.gui = '2014-January-09'; // Declarations @@ -2391,7 +2391,7 @@ IDE_Morph.prototype.aboutSnap = function () { world = this.world(); aboutTxt = 'Snap! 4.0\nBuild Your Own Blocks\n\n--- beta ---\n\n' - + 'Copyright \u24B8 2013 Jens M\u00F6nig and ' + + 'Copyright \u24B8 2014 Jens M\u00F6nig and ' + 'Brian Harvey\n' + 'jens@moenig.org, bh@cs.berkeley.edu\n\n' diff --git a/history.txt b/history.txt index 2411d8f..f0569ff 100755 --- a/history.txt +++ b/history.txt @@ -2062,4 +2062,5 @@ ______ * Blocks, Objects, Threads: Collapse old STOP primitives into a single one with a dropdown of options * German translation update for new (migrated) STOP block * Morphic: Fixed updateReferences() (how could nobody notice so long?!) -* Store: resolved unexpected assignment expressions (conform to the latest JSLint quibbles) +* XML: resolved unexpected assignment expressions (conform to the latest JSLint quibbles) +* validated all source files against the latest JSLint version diff --git a/lang-de.js b/lang-de.js index 2013833..0b438b5 100644 --- a/lang-de.js +++ b/lang-de.js @@ -6,7 +6,7 @@ written by Jens Mönig - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. diff --git a/lists.js b/lists.js index 60cd7e3..3166bf1 100644 --- a/lists.js +++ b/lists.js @@ -7,7 +7,7 @@ written by Jens Mönig and Brian Harvey jens@moenig.org, bh@cs.berkeley.edu - Copyright (C) 2013 by Jens Mönig and Brian Harvey + Copyright (C) 2014 by Jens Mönig and Brian Harvey This file is part of Snap!. @@ -61,7 +61,7 @@ PushButtonMorph, SyntaxElementMorph, Color, Point, WatcherMorph, StringMorph, SpriteMorph, ScrollFrameMorph, CellMorph, ArrowMorph, MenuMorph, snapEquals, Morph, isNil, localize, MorphicPreferences*/ -modules.lists = '2013-December-04'; +modules.lists = '2014-January-09'; var List; var ListWatcherMorph; diff --git a/locale.js b/locale.js index eb79862..3b65ec9 100644 --- a/locale.js +++ b/locale.js @@ -6,7 +6,7 @@ written by Jens Mönig - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. diff --git a/objects.js b/objects.js index 3f3df76..af482b1 100644 --- a/objects.js +++ b/objects.js @@ -9,7 +9,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. diff --git a/paint.js b/paint.js index 15b4172..1929f95 100644 --- a/paint.js +++ b/paint.js @@ -5,7 +5,7 @@ inspired by the Scratch paint editor. written by Kartik Chandra - Copyright (C) 2013 by Kartik Chandra + Copyright (C) 2014 by Kartik Chandra This file is part of Snap!. @@ -64,7 +64,7 @@ // Global stuff //////////////////////////////////////////////////////// -modules.paint = '2014-January-08'; +modules.paint = '2014-January-09'; // Declarations diff --git a/store.js b/store.js index 640f2d1..343dca6 100644 --- a/store.js +++ b/store.js @@ -7,7 +7,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. @@ -61,7 +61,7 @@ SyntaxElementMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2013-December-19'; +modules.store = '2014-January-09'; // XML_Serializer /////////////////////////////////////////////////////// diff --git a/threads.js b/threads.js index 79af3b9..722ce6b 100644 --- a/threads.js +++ b/threads.js @@ -9,7 +9,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. diff --git a/widgets.js b/widgets.js index 566d60c..c8dbd03 100644 --- a/widgets.js +++ b/widgets.js @@ -7,7 +7,7 @@ written by Jens Mönig jens@moenig.org - Copyright (C) 2013 by Jens Mönig + Copyright (C) 2014 by Jens Mönig This file is part of Snap!. @@ -74,7 +74,7 @@ HTMLCanvasElement, fontHeight, SymbolMorph, localize, SpeechBubbleMorph, ArrowMorph, MenuMorph, isString, isNil, SliderMorph, MorphicPreferences, ScrollFrameMorph*/ -modules.widgets = '2013-November-26'; +modules.widgets = '2014-January-09'; var PushButtonMorph; var ToggleButtonMorph; -- cgit v1.3.1 From 3c4e27899c52d32acba275beb90744b35dde74c0 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 10 Jan 2014 11:37:04 +0100 Subject: Revert pull request #295 (xhr-headers) breaks existing installations --- history.txt | 4 ++++ threads.js | 7 +------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/history.txt b/history.txt index f0569ff..d536252 100755 --- a/history.txt +++ b/history.txt @@ -2064,3 +2064,7 @@ ______ * Morphic: Fixed updateReferences() (how could nobody notice so long?!) * XML: resolved unexpected assignment expressions (conform to the latest JSLint quibbles) * validated all source files against the latest JSLint version + +140110 +------ +* Threads: Revert pull request #295 (xhr-headers), breaks existing installations diff --git a/threads.js b/threads.js index 722ce6b..d4a6732 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2014-January-09'; +modules.threads = '2014-January-10'; var ThreadManager; var Process; @@ -1772,11 +1772,6 @@ Process.prototype.reportURL = function (url) { if (!this.httpRequest) { this.httpRequest = new XMLHttpRequest(); this.httpRequest.open("GET", 'http://' + url, true); - this.httpRequest.setRequestHeader( - "X-Requested-With", - "XMLHttpRequest" - ); - this.httpRequest.setRequestHeader("X-Application", "Snap! 4.0"); this.httpRequest.send(null); } else if (this.httpRequest.readyState === 4) { response = this.httpRequest.responseText; -- cgit v1.3.1 From fba838735947f755b9b23173d744b7dbcb670a70 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 10 Jan 2014 12:18:24 +0100 Subject: Fixed #292 (pulldowns loose lines when exported as library) --- byob.js | 6 +++--- history.txt | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/byob.js b/byob.js index aff32ad..2ff40ab 100644 --- a/byob.js +++ b/byob.js @@ -106,7 +106,7 @@ SymbolMorph, isNil*/ // Global stuff //////////////////////////////////////////////////////// -modules.byob = '2014-January-09'; +modules.byob = '2014-January-10'; // Declarations @@ -3189,13 +3189,13 @@ BlockExportDialogMorph.prototype.selectNone = function () { BlockExportDialogMorph.prototype.exportBlocks = function () { var str = this.serializer.serialize(this.blocks); if (this.blocks.length > 0) { - window.open('data:text/xml,' + str - + ''); + + '')); } else { new DialogBoxMorph().inform( 'Export blocks', diff --git a/history.txt b/history.txt index d536252..2b58162 100755 --- a/history.txt +++ b/history.txt @@ -2068,3 +2068,4 @@ ______ 140110 ------ * Threads: Revert pull request #295 (xhr-headers), breaks existing installations +* BYOB: Fixed #292 (pulldowns loose lines when exported as library) -- cgit v1.3.1 From 9d63d129a68713a092a39c37025f896ec4edf00f Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 10 Jan 2014 12:43:22 +0100 Subject: Fixed #291 (readonly custom menus become non-readonly when block is edited) --- byob.js | 2 +- history.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/byob.js b/byob.js index 2ff40ab..4b581e1 100644 --- a/byob.js +++ b/byob.js @@ -194,7 +194,7 @@ CustomBlockDefinition.prototype.prototypeInstance = function () { part.fragment.type = slot[0]; part.fragment.defaultValue = slot[1]; part.fragment.options = slot[2]; - part.fragment.isReadonly = slot[3] || false; + part.fragment.isReadOnly = slot[3] || false; } } }); diff --git a/history.txt b/history.txt index 2b58162..d2ffc1d 100755 --- a/history.txt +++ b/history.txt @@ -2069,3 +2069,4 @@ ______ ------ * Threads: Revert pull request #295 (xhr-headers), breaks existing installations * BYOB: Fixed #292 (pulldowns loose lines when exported as library) +* BYOB: Fixed #291 (readonly custom menus become non-readonly when block is edited) -- cgit v1.3.1 From 06f47b5c1d5a51d14ada887d0606f14f6c14aae1 Mon Sep 17 00:00:00 2001 From: Manuel Menezes de Sequeira Date: Mon, 13 Jan 2014 15:57:43 +0000 Subject: Translate new stop commands. --- lang-pt.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lang-pt.js b/lang-pt.js index 9360638..36ae99d 100755 --- a/lang-pt.js +++ b/lang-pt.js @@ -185,7 +185,7 @@ SnapTranslator.dict.pt = { 'translator_e-mail': 'mmsequeira@gmail.com', 'last_changed': - '2013-11-22', + '2014-01-12', // GUI // control bar: @@ -447,12 +447,20 @@ SnapTranslator.dict.pt = { 'se %b , então %c senão, %c', 'report %s': 'reporta %s', - 'stop block': - 'pára este guião de bloco', - 'stop script': - 'pára este guião de objecto', - 'stop all %stop': - 'pára tudo %stop', + 'stop %stopChoices': + 'pára %stopChoices', + 'all': + 'tudo', + 'this script': + 'este guião de objecto', + 'this block': + 'este guião de bloco', + 'stop %stopOthersChoices': + 'pára %stopOthersChoices', + 'all but this script': + 'todos os guiões de objecto excepto este', + 'other scripts in sprite': + 'os outros guiões deste objecto', 'pause all %pause': 'faz pausa em tudo %pause', 'run %cmdRing %inputs': @@ -950,8 +958,6 @@ SnapTranslator.dict.pt = { 'Este projecto ainda não tem\nnenhum bloco personalizado global.', 'select': 'seleccionar', - 'all': - 'todos', 'none': 'nenhum', @@ -1215,7 +1221,7 @@ SnapTranslator.dict.pt = { 'e^': 'a exponencial', - // delimiters + // delimitadores 'whitespace': 'espaços em branco', 'line': -- cgit v1.3.1 From b4eb1d1864df81692d40a059336b070c4006e209 Mon Sep 17 00:00:00 2001 From: Dean Brettle Date: Sat, 25 Jan 2014 22:17:12 -0800 Subject: Fixes issue #310 - play note block fails on Firefox due to use of deprecated WebAudio names. The fix uses the correct names and monkey-patches browsers that use the old ones. --- objects.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/objects.js b/objects.js index af482b1..a0adada 100644 --- a/objects.js +++ b/objects.js @@ -5647,17 +5647,20 @@ Note.prototype.setupContext = function () { if (this.audioContext) { return; } var AudioContext = (function () { // cross browser some day? - return window.AudioContext || + var ctx = window.AudioContext || window.mozAudioContext || window.msAudioContext || window.oAudioContext || window.webkitAudioContext; + if (!ctx.prototype.hasOwnProperty('createGain')) + ctx.prototype.createGain = ctx.prototype.createGainNode; + return ctx; }()); if (!AudioContext) { throw new Error('Web Audio API is not supported\nin this browser'); } Note.prototype.audioContext = new AudioContext(); - Note.prototype.gainNode = Note.prototype.audioContext.createGainNode(); + Note.prototype.gainNode = Note.prototype.audioContext.createGain(); Note.prototype.gainNode.gain.value = 0.25; // reduce volume by 1/4 }; @@ -5665,17 +5668,21 @@ Note.prototype.setupContext = function () { Note.prototype.play = function () { this.oscillator = this.audioContext.createOscillator(); + if (!this.oscillator.start) + this.oscillator.start = this.oscillator.noteOn; + if (!this.oscillator.stop) + this.oscillator.stop = this.oscillator.noteOff; this.oscillator.type = 0; this.oscillator.frequency.value = Math.pow(2, (this.pitch - 69) / 12) * 440; this.oscillator.connect(this.gainNode); this.gainNode.connect(this.audioContext.destination); - this.oscillator.noteOn(0); // deprecated, renamed to start() + this.oscillator.start(0); }; Note.prototype.stop = function () { if (this.oscillator) { - this.oscillator.noteOff(0); // deprecated, renamed to stop() + this.oscillator.stop(0); this.oscillator = null; } }; -- cgit v1.3.1 From 58d0cf034f6fcb10b89bde14e5b05f64ab1ca11c Mon Sep 17 00:00:00 2001 From: gego51 Date: Sun, 26 Jan 2014 17:00:41 +0100 Subject: Update lang-fr.js add the french translation of the block "pause all" --- lang-fr.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lang-fr.js b/lang-fr.js index 8fd9cc7..1672077 100644 --- a/lang-fr.js +++ b/lang-fr.js @@ -469,7 +469,9 @@ SnapTranslator.dict.fr = { 'moi-m\u00EAme', 'delete this clone': 'supprime ce clone', - + 'pause all': + 'mettre en pause', + // sensing: 'touching %col ?': ' %col touch\u00E9?', -- cgit v1.3.1 From 3fede790e437df776366789626b96bfd07f3cefa Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 3 Feb 2014 17:11:46 +0100 Subject: Fixed #313 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit “Block OF sprite” now works for interpolated (“timed”) blocks and for reporters (i.e. SAY FOR, THINK FOR, GLIDE, ASK etc.) --- history.txt | 4 ++++ threads.js | 35 ++++++++++++++++++++--------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/history.txt b/history.txt index d2ffc1d..8ff5a12 100755 --- a/history.txt +++ b/history.txt @@ -2070,3 +2070,7 @@ ______ * Threads: Revert pull request #295 (xhr-headers), breaks existing installations * BYOB: Fixed #292 (pulldowns loose lines when exported as library) * BYOB: Fixed #291 (readonly custom menus become non-readonly when block is edited) + +140203 +------ +* Threads: Fixed #313. “Block of sprite” now works for interpolated (“timed”) blocks and for reporters (i.e. SAY FOR, THINK FOR, GLIDE, ASK etc.) diff --git a/threads.js b/threads.js index d4a6732..93931c1 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2014-January-10'; +modules.threads = '2014-Feb-03'; var ThreadManager; var Process; @@ -1643,15 +1643,15 @@ Process.prototype.doGlide = function (secs, endX, endY) { if (!this.context.startTime) { this.context.startTime = Date.now(); this.context.startValue = new Point( - this.homeContext.receiver.xPosition(), - this.homeContext.receiver.yPosition() + this.blockReceiver().xPosition(), + this.blockReceiver().yPosition() ); } if ((Date.now() - this.context.startTime) >= (secs * 1000)) { - this.homeContext.receiver.gotoXY(endX, endY); + this.blockReceiver().gotoXY(endX, endY); return null; } - this.homeContext.receiver.glide( + this.blockReceiver().glide( secs * 1000, endX, endY, @@ -1666,10 +1666,10 @@ Process.prototype.doGlide = function (secs, endX, endY) { Process.prototype.doSayFor = function (data, secs) { if (!this.context.startTime) { this.context.startTime = Date.now(); - this.homeContext.receiver.bubble(data); + this.blockReceiver().bubble(data); } if ((Date.now() - this.context.startTime) >= (secs * 1000)) { - this.homeContext.receiver.stopTalking(); + this.blockReceiver().stopTalking(); return null; } this.pushContext('doYield'); @@ -1679,16 +1679,21 @@ Process.prototype.doSayFor = function (data, secs) { Process.prototype.doThinkFor = function (data, secs) { if (!this.context.startTime) { this.context.startTime = Date.now(); - this.homeContext.receiver.doThink(data); + this.blockReceiver().doThink(data); } if ((Date.now() - this.context.startTime) >= (secs * 1000)) { - this.homeContext.receiver.stopTalking(); + this.blockReceiver().stopTalking(); return null; } this.pushContext('doYield'); this.pushContext(); }; +Process.prototype.blockReceiver = function () { + return this.context ? this.context.receiver || this.homeContext.receiver + : this.homeContext.receiver; +}; + // Process sound primitives (interpolated) Process.prototype.doPlaySoundUntilDone = function (name) { @@ -1723,7 +1728,7 @@ Process.prototype.doStopAllSounds = function () { Process.prototype.doAsk = function (data) { var stage = this.homeContext.receiver.parentThatIsA(StageMorph), - isStage = this.homeContext.receiver instanceof StageMorph, + isStage = this.blockReceiver() instanceof StageMorph, activePrompter; if (!this.prompter) { @@ -1733,7 +1738,7 @@ Process.prototype.doAsk = function (data) { ); if (!activePrompter) { if (!isStage) { - this.homeContext.receiver.bubble(data, false, true); + this.blockReceiver().bubble(data, false, true); } this.prompter = new StagePrompterMorph(isStage ? data : null); if (stage.scale < 1) { @@ -1753,7 +1758,7 @@ Process.prototype.doAsk = function (data) { stage.lastAnswer = this.prompter.inputField.getValue(); this.prompter.destroy(); this.prompter = null; - if (!isStage) {this.homeContext.receiver.stopTalking(); } + if (!isStage) {this.blockReceiver().stopTalking(); } return null; } } @@ -2288,7 +2293,7 @@ Process.prototype.createClone = function (name) { // Process sensing primitives Process.prototype.reportTouchingObject = function (name) { - var thisObj = this.homeContext.receiver; + var thisObj = this.blockReceiver(); if (thisObj) { return this.objectTouchingObject(thisObj, name); @@ -2384,7 +2389,7 @@ Process.prototype.reportColorIsTouchingColor = function (color1, color2) { }; Process.prototype.reportDistanceTo = function (name) { - var thisObj = this.homeContext.receiver, + var thisObj = this.blockReceiver(), thatObj, stage, rc, @@ -2407,7 +2412,7 @@ Process.prototype.reportDistanceTo = function (name) { }; Process.prototype.reportAttributeOf = function (attribute, name) { - var thisObj = this.homeContext.receiver, + var thisObj = this.blockReceiver(), thatObj, stage; -- cgit v1.3.1 From 8654d9c3fc084fee3a460f8d64e53cfb58370936 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 3 Feb 2014 17:30:31 +0100 Subject: Morphic: Replaced deprecated DOM “body” references with “documentElement” MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- history.txt | 1 + morphic.js | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/history.txt b/history.txt index 8ff5a12..8486b1a 100755 --- a/history.txt +++ b/history.txt @@ -2074,3 +2074,4 @@ ______ 140203 ------ * Threads: Fixed #313. “Block of sprite” now works for interpolated (“timed”) blocks and for reporters (i.e. SAY FOR, THINK FOR, GLIDE, ASK etc.) +* Morphic: replace deprecated DOM “body” references with “documentElement” diff --git a/morphic.js b/morphic.js index c5aa561..b55b180 100644 --- a/morphic.js +++ b/morphic.js @@ -1035,7 +1035,7 @@ /*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio, FileList, getBlurredShadowSupport*/ -var morphicVersion = '2014-January-09'; +var morphicVersion = '2014-February-03'; var modules = {}; // keep track of additional loaded modules var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug @@ -10029,13 +10029,14 @@ WorldMorph.prototype.fillPage = function () { this.worldCanvas.style.top = "0px"; pos.y = 0; } - if (document.body.scrollTop) { // scrolled down b/c of viewport scaling + if (document.documentElement.scrollTop) { + // scrolled down b/c of viewport scaling clientHeight = document.documentElement.clientHeight; } - if (document.body.scrollLeft) { // scrolled left b/c of viewport scaling + if (document.documentElement.scrollLeft) { + // scrolled left b/c of viewport scaling clientWidth = document.documentElement.clientWidth; } - if (this.worldCanvas.width !== clientWidth) { this.worldCanvas.width = clientWidth; this.setWidth(clientWidth); -- cgit v1.3.1 From 1d8862c7af97408679aa431431a369197b2e47d1 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 4 Feb 2014 14:29:32 +0100 Subject: Import costumes and backgrounds from the project menu thanks, Brian, for the changeset! --- gui.js | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- history.txt | 4 ++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/gui.js b/gui.js index 0adc325..1943636 100644 --- a/gui.js +++ b/gui.js @@ -68,7 +68,7 @@ sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.gui = '2014-January-09'; +modules.gui = '2014-February-04'; // Declarations @@ -2233,6 +2233,8 @@ IDE_Morph.prototype.projectMenu = function () { 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); @@ -2380,9 +2382,68 @@ IDE_Morph.prototype.projectMenu = function () { 'Select categories of additional blocks to add to this project.' ); + menu.addItem( + localize(graphicsName) + '...', + function () { + var dir = graphicsName, + names = myself.getCostumesList(dir), + libMenu = new MenuMorph( + myself, + localize('Import') + ' ' + localize(dir) + ); + + function loadCostume(name) { + var url = dir + '/' + name, + img = new Image(); + img.onload = function () { + var canvas = newCanvas(new Point(img.width, img.height)); + canvas.getContext('2d').drawImage(img, 0, 0); + myself.droppedImage(canvas, name); + }; + img.src = url; + } + + names.forEach(function (line) { + if (line.length > 0) { + libMenu.addItem( + line, + function () {loadCostume(line); } + ); + } + }); + libMenu.popup(world, pos); + }, + 'Select a costume from the media library' + ); + menu.popup(world, pos); }; +IDE_Morph.prototype.getCostumesList = function (dirname) { + var dir, + costumes = []; + + dir = this.getURL(dirname); + dir.split('\n').forEach( + function (line) { + var startIdx = line.search(new RegExp('href="[^./?].*"')), + endIdx, + name; + + if (startIdx > 0) { + name = line.substring(startIdx + 6); + endIdx = name.search(new RegExp('"')); + name = name.substring(0, endIdx); + costumes.push(name); + } + } + ); + costumes.sort(function (x, y) { + return x < y ? -1 : 1; + }); + return costumes; +}; + // IDE_Morph menu actions IDE_Morph.prototype.aboutSnap = function () { diff --git a/history.txt b/history.txt index 8486b1a..d1fea7e 100755 --- a/history.txt +++ b/history.txt @@ -2075,3 +2075,7 @@ ______ ------ * Threads: Fixed #313. “Block of sprite” now works for interpolated (“timed”) blocks and for reporters (i.e. SAY FOR, THINK FOR, GLIDE, ASK etc.) * Morphic: replace deprecated DOM “body” references with “documentElement” + +140204 +------ +* GUI: Import costumes and background from the project menu, thanks, Brian, for the changeset! -- cgit v1.3.1 From 9be9d3da11461f218108eb3375875e6363208a7b Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 4 Feb 2014 14:45:15 +0100 Subject: Import sounds from the project menu Thanks, Brian, for the changeset! --- gui.js | 28 +++++++++++++++++++++++++++- history.txt | 3 ++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/gui.js b/gui.js index 1943636..96903a0 100644 --- a/gui.js +++ b/gui.js @@ -64,7 +64,7 @@ standardSettings, Sound, BlockMorph, ToggleMorph, InputSlotDialogMorph, ScriptsMorph, isNil, SymbolMorph, BlockExportDialogMorph, BlockImportDialogMorph, SnapTranslator, localize, List, InputSlotMorph, SnapCloud, Uint8Array, HandleMorph, SVG_Costume, fontHeight, hex_sha512, -sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph*/ +sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph, Audio*/ // Global stuff //////////////////////////////////////////////////////// @@ -2415,6 +2415,32 @@ IDE_Morph.prototype.projectMenu = function () { }, 'Select a costume from the media library' ); + menu.addItem( + localize('Sounds') + '...', + function () { + var names = this.getCostumesList('Sounds'), + libMenu = new MenuMorph(this, 'Import sound'); + + function loadSound(name) { + var url = 'Sounds/' + name, + audio = new Audio(); + audio.src = url; + audio.load(); + myself.droppedAudio(audio, name); + } + + names.forEach(function (line) { + if (line.length > 0) { + libMenu.addItem( + line, + function () {loadSound(line); } + ); + } + }); + libMenu.popup(world, pos); + }, + 'Select a sound from the media library' + ); menu.popup(world, pos); }; diff --git a/history.txt b/history.txt index d1fea7e..577e17a 100755 --- a/history.txt +++ b/history.txt @@ -2078,4 +2078,5 @@ ______ 140204 ------ -* GUI: Import costumes and background from the project menu, thanks, Brian, for the changeset! +* GUI: Import costumes and backgrounds from the project menu, thanks, Brian, for the changeset! +* GUI: Import sounds from the project menu, thanks, Brian, for the changeset! -- cgit v1.3.1 From 1fb0b7799834280a759eb238b8d138b60223b1c2 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 4 Feb 2014 15:29:14 +0100 Subject: Flat line end option in the settings menu, saved with the project --- gui.js | 11 +++++++++++ history.txt | 1 + objects.js | 12 +++++++++--- store.js | 6 +++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/gui.js b/gui.js index 96903a0..7640393 100644 --- a/gui.js +++ b/gui.js @@ -2211,6 +2211,16 @@ IDE_Morph.prototype.settingsMenu = function () { 'uncheck for greater speed\nat variable frame rates', 'check for smooth, predictable\nanimations across computers' ); + addPreference( + 'Flat line ends', + function () { + SpriteMorph.prototype.useFlatLineEnds = + !SpriteMorph.prototype.useFlatLineEnds; + }, + SpriteMorph.prototype.useFlatLineEnds, + 'uncheck for round ends of lines', + 'check for flat ends of lines' + ); addPreference( 'Codification support', function () { @@ -2689,6 +2699,7 @@ IDE_Morph.prototype.newProject = function () { StageMorph.prototype.codeMappings = {}; StageMorph.prototype.codeHeaders = {}; StageMorph.prototype.enableCodeMapping = false; + SpriteMorph.prototype.useFlatLineEnds = false; this.setProjectName(''); this.projectNotes = ''; this.createStage(); diff --git a/history.txt b/history.txt index 577e17a..e44e138 100755 --- a/history.txt +++ b/history.txt @@ -2080,3 +2080,4 @@ ______ ------ * GUI: Import costumes and backgrounds from the project menu, thanks, Brian, for the changeset! * GUI: Import sounds from the project menu, thanks, Brian, for the changeset! +* Objects, Store, GUI: Flat line end option in the settings menu, saved with the project diff --git a/objects.js b/objects.js index af482b1..1c9a166 100644 --- a/objects.js +++ b/objects.js @@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-January-09'; +modules.objects = '2014-February-04'; var SpriteMorph; var StageMorph; @@ -186,6 +186,7 @@ SpriteMorph.prototype.sliderColor SpriteMorph.prototype.isCachingPrimitives = true; SpriteMorph.prototype.enableNesting = true; +SpriteMorph.prototype.useFlatLineEnds = false; SpriteMorph.prototype.highlightColor = new Color(250, 200, 130); SpriteMorph.prototype.highlightBorder = 8; @@ -2717,8 +2718,13 @@ SpriteMorph.prototype.drawLine = function (start, dest) { if (this.isDown) { context.lineWidth = this.size; context.strokeStyle = this.color.toString(); - context.lineCap = 'round'; - context.lineJoin = 'round'; + if (this.useFlatLineEnds) { + context.lineCap = 'butt'; + context.lineJoin = 'miter'; + } else { + context.lineCap = 'round'; + context.lineJoin = 'round'; + } context.beginPath(); context.moveTo(from.x, from.y); context.lineTo(to.x, to.y); diff --git a/store.js b/store.js index 343dca6..ae9a5d1 100644 --- a/store.js +++ b/store.js @@ -61,7 +61,7 @@ SyntaxElementMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2014-January-09'; +modules.store = '2014-February-04'; // XML_Serializer /////////////////////////////////////////////////////// @@ -378,6 +378,8 @@ SnapSerializer.prototype.loadProjectModel = function (xmlNode) { } project.stage.setTempo(model.stage.attributes.tempo); project.stage.setExtent(StageMorph.prototype.dimensions); + SpriteMorph.prototype.useFlatLineEnds = + model.stage.attributes.lines === 'flat'; project.stage.isThreadSafe = model.stage.attributes.threadsafe === 'true'; StageMorph.prototype.enableCodeMapping = @@ -1340,6 +1342,7 @@ StageMorph.prototype.toXML = function (serializer) { '$' + '$' + '' + '$' + @@ -1364,6 +1367,7 @@ StageMorph.prototype.toXML = function (serializer) { this.getCostumeIdx(), this.getTempo(), this.isThreadSafe, + SpriteMorph.prototype.useFlatLineEnds ? 'flat' : 'round', this.enableCodeMapping, StageMorph.prototype.frameRate !== 0, this.trailsCanvas.toDataURL('image/png'), -- cgit v1.3.1 From 590ce704fcc7a805caad79149231edb5f3fcadae Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 4 Feb 2014 15:40:53 +0100 Subject: German translation update --- history.txt | 1 + lang-de.js | 8 +++++++- locale.js | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/history.txt b/history.txt index e44e138..7746ef4 100755 --- a/history.txt +++ b/history.txt @@ -2081,3 +2081,4 @@ ______ * GUI: Import costumes and backgrounds from the project menu, thanks, Brian, for the changeset! * GUI: Import sounds from the project menu, thanks, Brian, for the changeset! * Objects, Store, GUI: Flat line end option in the settings menu, saved with the project +* German translation update diff --git a/lang-de.js b/lang-de.js index 0b438b5..8b71902 100644 --- a/lang-de.js +++ b/lang-de.js @@ -185,7 +185,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', // optional 'last_changed': - '2014-01-09', // this, too, will appear in the Translators tab + '2014-02-04', // this, too, will appear in the Translators tab // GUI // control bar: @@ -767,6 +767,12 @@ SnapTranslator.dict.de = { 'ausschalten, um Animationen \ndynamischer auszuf\u00fchren', 'check for smooth, predictable\nanimations across computers': 'einschalten, damit Animationen\n\u00fcberall gleich laufen', + 'Flat line ends': + 'Flache Pinselstriche', + 'check for flat ends of lines': + 'einschalten f\u00fcr flache\nPinselstrichenden', + 'uncheck for round ends of lines': + 'auschalten f\u00fcr runde\nPinselstrichenden', // inputs 'with inputs': diff --git a/locale.js b/locale.js index 3b65ec9..d0b7a49 100644 --- a/locale.js +++ b/locale.js @@ -42,7 +42,7 @@ /*global modules, contains*/ -modules.locale = '2014-January-09'; +modules.locale = '2014-February-04'; // Global stuff @@ -149,7 +149,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', 'last_changed': - '2014-01-09' + '2014-02-04' }; SnapTranslator.dict.it = { -- cgit v1.3.1 From 0322b6e3db13355e8bf37db7ab6df7d88875d4b4 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 4 Feb 2014 16:14:16 +0100 Subject: integrate Dean's sound fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit so JSLint doesn’t complain (no functionality changes). Thanks, Dean! --- history.txt | 1 + objects.js | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/history.txt b/history.txt index 7746ef4..054387a 100755 --- a/history.txt +++ b/history.txt @@ -2082,3 +2082,4 @@ ______ * GUI: Import sounds from the project menu, thanks, Brian, for the changeset! * Objects, Store, GUI: Flat line end option in the settings menu, saved with the project * German translation update +* Objects: Enable playing sounds and notes on Firefox, thanks, Dean Brettle, for this fix!! diff --git a/objects.js b/objects.js index fd19bd6..52126e2 100644 --- a/objects.js +++ b/objects.js @@ -5658,8 +5658,9 @@ Note.prototype.setupContext = function () { window.msAudioContext || window.oAudioContext || window.webkitAudioContext; - if (!ctx.prototype.hasOwnProperty('createGain')) + if (!ctx.prototype.hasOwnProperty('createGain')) { ctx.prototype.createGain = ctx.prototype.createGainNode; + } return ctx; }()); if (!AudioContext) { @@ -5674,10 +5675,12 @@ Note.prototype.setupContext = function () { Note.prototype.play = function () { this.oscillator = this.audioContext.createOscillator(); - if (!this.oscillator.start) + if (!this.oscillator.start) { this.oscillator.start = this.oscillator.noteOn; - if (!this.oscillator.stop) + } + if (!this.oscillator.stop) { this.oscillator.stop = this.oscillator.noteOff; + } this.oscillator.type = 0; this.oscillator.frequency.value = Math.pow(2, (this.pitch - 69) / 12) * 440; -- cgit v1.3.1 From 8b5fa2ff9bd81ad9227b2593f9ccd6fdb8d32444 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 4 Feb 2014 16:36:59 +0100 Subject: Integrate Portuguese and French translation updates --- history.txt | 2 ++ lang-fr.js | 2 +- locale.js | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/history.txt b/history.txt index 054387a..77c2e9d 100755 --- a/history.txt +++ b/history.txt @@ -2083,3 +2083,5 @@ ______ * Objects, Store, GUI: Flat line end option in the settings menu, saved with the project * German translation update * Objects: Enable playing sounds and notes on Firefox, thanks, Dean Brettle, for this fix!! +* Update Portuguese translation, thanks, Manuel! +* Update French translation, thanks, grego! diff --git a/lang-fr.js b/lang-fr.js index 1672077..4198bf7 100644 --- a/lang-fr.js +++ b/lang-fr.js @@ -185,7 +185,7 @@ SnapTranslator.dict.fr = { 'translator_e-mail': 'i.scool@mac.com', // optional 'last_changed': - '2013-12-04', // this, too, will appear in the Translators tab + '2014-02-04', // this, too, will appear in the Translators tab // GUI // control bar: diff --git a/locale.js b/locale.js index d0b7a49..164d8e7 100644 --- a/locale.js +++ b/locale.js @@ -209,7 +209,7 @@ SnapTranslator.dict.pt = { 'translator_e-mail': 'mmsequeira@gmail.com', 'last_changed': - '2013-11-22' + '2014-01-12' }; SnapTranslator.dict.cs = { @@ -257,7 +257,7 @@ SnapTranslator.dict.fr = { 'translator_e-mail': 'i.scool@mac.com', 'last_changed': - '2013-12-04' + '2014-02-04' }; SnapTranslator.dict.si = { -- cgit v1.3.1