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) --- history.txt | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'history.txt') 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) -- 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(+) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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 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(+) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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(-) (limited to 'history.txt') 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