diff --git a/history.txt b/history.txt index 1e04b7e9..f9b8da1d 100755 --- a/history.txt +++ b/history.txt @@ -1805,3 +1805,8 @@ ______ * Blocks: fixed occasional flickering in scripting areas (caused by deleted feedback morphs, a bug that surfaced in Chrome 28 on OSX and may be due to a possible Chrome GC issue) * Blocks: preserve nested blocks in the scripting area when replacing a variadic input list with another input ("kick out" the nested blocks instead of "swallowing" them) * Blocks, Threads: new floor() function in monadic math reporter's drop-down + +130712 +------ +* Blocks: Pipette symbol +* Paint: Pipette tool diff --git a/paint.js b/paint.js index 80e6295c..97236afa 100644 --- a/paint.js +++ b/paint.js @@ -46,8 +46,9 @@ revision history ---------------- May 10 - first full release (Kartik) - May 14 - bugfixes (bugfixes, Snap integration (Jens) + May 14 - bugfixes, Snap integration (Jens) May 16 - flat design adjustments (Jens) + July 12 - pipette tool, code formatting adjustments (Jens) */ @@ -56,12 +57,12 @@ CostumeIconMorph, IDE_Morph, Costume, SpriteMorph, nop, Image, WardrobeMorph, TurtleIconMorph, localize, MenuMorph, InputFieldMorph, SliderMorph, ToggleMorph, ToggleButtonMorph, BoxMorph, modules, radians, - MorphicPreferences + MorphicPreferences, getDocumentPositionOf */ // Global stuff //////////////////////////////////////////////////////// -modules.paint = '2013-May-16'; +modules.paint = '2013-July-12'; // Declarations @@ -83,7 +84,7 @@ function PaintEditorMorph() { this.init(); } -PaintEditorMorph.prototype.init = function() { +PaintEditorMorph.prototype.init = function () { // additional properties: this.paper = null; // paint canvas this.oncancel = null; @@ -102,7 +103,7 @@ PaintEditorMorph.prototype.init = function() { PaintEditorMorph.prototype.buildContents = function () { var myself = this; - this.paper = new PaintCanvasMorph(function() {return myself.shift; }); + this.paper = new PaintCanvasMorph(function () {return myself.shift; }); this.paper.setExtent(new Point(480, 360)); this.addBody(new AlignmentMorph('row', this.padding)); @@ -146,7 +147,7 @@ PaintEditorMorph.prototype.buildContents = function () { this.drawNew(); }; -PaintEditorMorph.prototype.buildToolbox = function() { +PaintEditorMorph.prototype.buildToolbox = function () { var tools = { brush: "Paintbrush tool\n(free draw)", @@ -166,7 +167,9 @@ PaintEditorMorph.prototype.buildToolbox = function() { circleSolid: "Filled Ellipse\n(shift: circle)", paintbucket: - "Fill a region" + "Fill a region", + pipette: + "Pipette tool\n(pick a color anywhere)" }, myself = this, left = this.toolbox.left(), @@ -176,7 +179,7 @@ PaintEditorMorph.prototype.buildToolbox = function() { x = 0, y = 0; - Object.keys(tools).forEach(function(tool) { + Object.keys(tools).forEach(function (tool) { var btn = myself.toolButton(tool, tools[tool]); btn.setPosition(new Point( left + x, @@ -196,7 +199,7 @@ PaintEditorMorph.prototype.buildToolbox = function() { this.toolbox.drawNew(); }; -PaintEditorMorph.prototype.buildEdits = function() { +PaintEditorMorph.prototype.buildEdits = function () { var paper = this.paper; this.edits.add(this.pushButton( @@ -211,18 +214,18 @@ PaintEditorMorph.prototype.buildEdits = function() { this.edits.fixLayout(); }; -PaintEditorMorph.prototype.openIn = function(world, oldim, oldrc, callback) { +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.processKeyUp = function() { + this.processKeyUp = function () { this.shift = false; this.propertiesControls.constrain.refresh(); }; - this.processKeyDown = function() { + this.processKeyDown = function () { this.shift = this.world().currentKey === 16; this.propertiesControls.constrain.refresh(); }; @@ -244,7 +247,7 @@ PaintEditorMorph.prototype.openIn = function(world, oldim, oldrc, callback) { this.popUp(world); }; -PaintEditorMorph.prototype.fixLayout = function() { +PaintEditorMorph.prototype.fixLayout = function () { var oldFlag = Morph.prototype.trackChanges; this.changed(); @@ -263,13 +266,13 @@ PaintEditorMorph.prototype.fixLayout = function() { this.changed(); }; -PaintEditorMorph.prototype.refreshToolButtons = function() { +PaintEditorMorph.prototype.refreshToolButtons = function () { this.toolbox.children.forEach(function (toggle) { toggle.refresh(); }); }; -PaintEditorMorph.prototype.ok = function() { +PaintEditorMorph.prototype.ok = function () { this.callback( this.paper.paper, this.paper.rotationCenter @@ -282,7 +285,7 @@ PaintEditorMorph.prototype.cancel = function () { this.destroy(); }; -PaintEditorMorph.prototype.populatePropertiesMenu = function() { +PaintEditorMorph.prototype.populatePropertiesMenu = function () { var c = this.controls, myself = this, pc = this.propertiesControls, @@ -293,7 +296,7 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() { pc.primaryColorViewer.color = new Color(0, 0, 0); pc.colorpicker = new PaintColorPickerMorph( new Point(180, 100), - function(color) { + function (color) { var ni = newCanvas(pc.primaryColorViewer.extent()), ctx = ni.getContext("2d"), i, @@ -331,7 +334,7 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() { pc.penSizeSlider.orientation = "horizontal"; pc.penSizeSlider.setHeight(15); pc.penSizeSlider.setWidth(150); - pc.penSizeSlider.action = function(num) { + pc.penSizeSlider.action = function (num) { if (pc.penSizeField) { pc.penSizeField.setContents(num); } @@ -341,7 +344,7 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() { pc.penSizeField = new InputFieldMorph("5", true, null, false); pc.penSizeField.contents().minWidth = 20; pc.penSizeField.setWidth(25); - pc.penSizeField.accept = function() { + pc.penSizeField.accept = function () { var val = parseFloat(pc.penSizeField.getValue()); pc.penSizeSlider.value = val; pc.penSizeSlider.drawNew(); @@ -359,9 +362,9 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() { pc.constrain = new ToggleMorph( "checkbox", this, - function() {myself.shift = !myself.shift; }, + function () {myself.shift = !myself.shift; }, "Constrain proportions of shapes?\n(you can also hold shift)", - function() {return myself.shift; } + function () {return myself.shift; } ); c.add(pc.colorpicker); //c.add(pc.primaryColorButton); @@ -371,16 +374,19 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() { c.add(pc.constrain); }; -PaintEditorMorph.prototype.toolButton = function(icon, hint) { +PaintEditorMorph.prototype.toolButton = function (icon, hint) { var button, myself = this; button = new ToggleButtonMorph( null, - this, - function () { // action + this, + function () { // action myself.paper.currentTool = icon; myself.paper.toolChanged(icon); - myself.refreshToolButtons(); + myself.refreshToolButtons(); + if (icon === 'pipette') { + myself.getUserColor(); + } }, new SymbolMorph(icon, 18), function () {return myself.paper.currentTool === icon; } @@ -392,7 +398,7 @@ PaintEditorMorph.prototype.toolButton = function(icon, hint) { return button; }; -PaintEditorMorph.prototype.pushButton = function(title, action, hint) { +PaintEditorMorph.prototype.pushButton = function (title, action, hint) { return new PushButtonMorph( this, action, @@ -401,6 +407,38 @@ PaintEditorMorph.prototype.pushButton = function(title, action, hint) { hint ); }; + +PaintEditorMorph.prototype.getUserColor = function () { + var myself = this, + world = this.world(), + hand = world.hand, + posInDocument = getDocumentPositionOf(world.worldCanvas), + mouseMoveBak = hand.processMouseMove, + mouseDownBak = hand.processMouseDown, + mouseUpBak = hand.processMouseUp; + + hand.processMouseMove = function (event) { + var color; + hand.setPosition(new Point( + event.pageX - posInDocument.x, + event.pageY - posInDocument.y + )); + color = world.getGlobalPixelColor(hand.position()); + myself.propertiesControls.colorpicker.action(color); + myself.paper.settings.primarycolor = color; + }; + + hand.processMouseDown = nop; + + hand.processMouseUp = function () { + myself.paper.currentTool = 'brush'; + myself.paper.toolChanged('brush'); + myself.refreshToolButtons(); + hand.processMouseMove = mouseMoveBak; + hand.processMouseDown = mouseDownBak; + hand.processMouseUp = mouseUpBak; + }; +}; // AdvancedColorPickerMorph ////////////////// @@ -414,13 +452,13 @@ function PaintColorPickerMorph(extent, action) { this.init(extent, action); } -PaintColorPickerMorph.prototype.init = function(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() { +PaintColorPickerMorph.prototype.drawNew = function () { var x = 0, y = 0, can = newCanvas(this.extent()), @@ -464,7 +502,7 @@ PaintColorPickerMorph.prototype.drawNew = function() { this.image = can; }; -PaintColorPickerMorph.prototype.mouseDownLeft = function(pos) { +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"); @@ -490,7 +528,7 @@ function PaintCanvasMorph(shift) { this.init(shift); } -PaintCanvasMorph.prototype.init = function(shift) { +PaintCanvasMorph.prototype.init = function (shift) { this.rotationCenter = new Point(240, 180); this.dragRect = null; this.previousDragPoint = null; @@ -509,20 +547,20 @@ PaintCanvasMorph.prototype.init = function(shift) { }; this.brushBuffer = []; this.undoBuffer = []; - this.isShiftPressed = shift || function() { + this.isShiftPressed = shift || function () { var key = this.world().currentKey; return (key === 16); }; this.buildContents(); }; -PaintCanvasMorph.prototype.cacheUndo = function() { +PaintCanvasMorph.prototype.cacheUndo = function () { var cachecan = newCanvas(this.extent()); this.merge(this.paper, cachecan); this.undoBuffer.push(cachecan); }; -PaintCanvasMorph.prototype.undo = function() { +PaintCanvasMorph.prototype.undo = function () { if (this.undoBuffer.length > 0) { this.paper = newCanvas(this.extent()); this.mask.width = this.mask.width + 1 - 1; @@ -532,11 +570,11 @@ PaintCanvasMorph.prototype.undo = function() { } }; -PaintCanvasMorph.prototype.merge = function(a, b) { +PaintCanvasMorph.prototype.merge = function (a, b) { b.getContext("2d").drawImage(a, 0, 0); }; -PaintCanvasMorph.prototype.centermerge = function(a, b) { +PaintCanvasMorph.prototype.centermerge = function (a, b) { b.getContext("2d").drawImage( a, (b.width - a.width) / 2, @@ -544,13 +582,13 @@ PaintCanvasMorph.prototype.centermerge = function(a, b) { ); }; -PaintCanvasMorph.prototype.clearCanvas = function() { +PaintCanvasMorph.prototype.clearCanvas = function () { this.buildContents(); this.drawNew(); this.changed(); }; -PaintCanvasMorph.prototype.toolChanged = function(tool) { +PaintCanvasMorph.prototype.toolChanged = function (tool) { this.mask = newCanvas(this.extent()); if (tool === "crosshairs") { this.drawcrosshair(); @@ -559,7 +597,7 @@ PaintCanvasMorph.prototype.toolChanged = function(tool) { this.changed(); }; -PaintCanvasMorph.prototype.drawcrosshair = function(context) { +PaintCanvasMorph.prototype.drawcrosshair = function (context) { var ctx = context || this.mask.getContext("2d"), rp = this.rotationCenter; @@ -612,7 +650,7 @@ PaintCanvasMorph.prototype.drawcrosshair = function(context) { this.changed(); }; -PaintCanvasMorph.prototype.floodfill = function(sourcepoint) { +PaintCanvasMorph.prototype.floodfill = function (sourcepoint) { var width = this.paper.width, height = this.paper.height, ctx = this.paper.getContext("2d"), @@ -628,7 +666,7 @@ PaintCanvasMorph.prototype.floodfill = function(sourcepoint) { return [data[d], data[d + 1], data[d + 2], data[d + 3]]; }; sourcecolor = read(stack[0]); - checkpoint = function(p) { + checkpoint = function (p) { return p[0] === sourcecolor[0] && p[1] === sourcecolor[1] && p[2] === sourcecolor[2] && @@ -660,7 +698,7 @@ PaintCanvasMorph.prototype.floodfill = function(sourcepoint) { this.changed(); }; -PaintCanvasMorph.prototype.mouseDownLeft = function(pos) { +PaintCanvasMorph.prototype.mouseDownLeft = function (pos) { this.cacheUndo(); this.dragRect.origin = pos.subtract(this.bounds.origin); this.dragRect.corner = pos.subtract(this.bounds.origin); @@ -680,7 +718,7 @@ PaintCanvasMorph.prototype.mouseDownLeft = function(pos) { } }; -PaintCanvasMorph.prototype.mouseMove = function(pos) { +PaintCanvasMorph.prototype.mouseMove = function (pos) { if (this.currentTool === "paintbucket") { return; } @@ -824,14 +862,14 @@ PaintCanvasMorph.prototype.mouseMove = function(pos) { mctx.restore(); }; -PaintCanvasMorph.prototype.mouseClickLeft = function() { +PaintCanvasMorph.prototype.mouseClickLeft = function () { if (this.currentTool !== "crosshairs") { this.merge(this.mask, this.paper); } this.brushBuffer = []; }; -PaintCanvasMorph.prototype.buildContents = function() { +PaintCanvasMorph.prototype.buildContents = function () { this.background = newCanvas(this.extent()); this.paper = newCanvas(this.extent()); this.mask = newCanvas(this.extent()); @@ -849,7 +887,7 @@ PaintCanvasMorph.prototype.buildContents = function() { } }; -PaintCanvasMorph.prototype.drawNew = function() { +PaintCanvasMorph.prototype.drawNew = function () { var can = newCanvas(this.extent()); this.merge(this.background, can); this.merge(this.paper, can);