Paint Editor: Pipette tool

and code formatting adjustments for JSLint
pull/3/merge
jmoenig 2013-07-12 11:28:55 +02:00
rodzic 7eba03eaf1
commit 1a8b2658db
2 zmienionych plików z 88 dodań i 45 usunięć

Wyświetl plik

@ -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: 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: 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 * Blocks, Threads: new floor() function in monadic math reporter's drop-down
130712
------
* Blocks: Pipette symbol
* Paint: Pipette tool

122
paint.js
Wyświetl plik

@ -46,8 +46,9 @@
revision history revision history
---------------- ----------------
May 10 - first full release (Kartik) 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) 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, CostumeIconMorph, IDE_Morph, Costume, SpriteMorph, nop, Image, WardrobeMorph,
TurtleIconMorph, localize, MenuMorph, InputFieldMorph, SliderMorph, TurtleIconMorph, localize, MenuMorph, InputFieldMorph, SliderMorph,
ToggleMorph, ToggleButtonMorph, BoxMorph, modules, radians, ToggleMorph, ToggleButtonMorph, BoxMorph, modules, radians,
MorphicPreferences MorphicPreferences, getDocumentPositionOf
*/ */
// Global stuff //////////////////////////////////////////////////////// // Global stuff ////////////////////////////////////////////////////////
modules.paint = '2013-May-16'; modules.paint = '2013-July-12';
// Declarations // Declarations
@ -83,7 +84,7 @@ function PaintEditorMorph() {
this.init(); this.init();
} }
PaintEditorMorph.prototype.init = function() { PaintEditorMorph.prototype.init = function () {
// additional properties: // additional properties:
this.paper = null; // paint canvas this.paper = null; // paint canvas
this.oncancel = null; this.oncancel = null;
@ -102,7 +103,7 @@ PaintEditorMorph.prototype.init = function() {
PaintEditorMorph.prototype.buildContents = function () { PaintEditorMorph.prototype.buildContents = function () {
var myself = this; 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.paper.setExtent(new Point(480, 360));
this.addBody(new AlignmentMorph('row', this.padding)); this.addBody(new AlignmentMorph('row', this.padding));
@ -146,7 +147,7 @@ PaintEditorMorph.prototype.buildContents = function () {
this.drawNew(); this.drawNew();
}; };
PaintEditorMorph.prototype.buildToolbox = function() { PaintEditorMorph.prototype.buildToolbox = function () {
var tools = { var tools = {
brush: brush:
"Paintbrush tool\n(free draw)", "Paintbrush tool\n(free draw)",
@ -166,7 +167,9 @@ PaintEditorMorph.prototype.buildToolbox = function() {
circleSolid: circleSolid:
"Filled Ellipse\n(shift: circle)", "Filled Ellipse\n(shift: circle)",
paintbucket: paintbucket:
"Fill a region" "Fill a region",
pipette:
"Pipette tool\n(pick a color anywhere)"
}, },
myself = this, myself = this,
left = this.toolbox.left(), left = this.toolbox.left(),
@ -176,7 +179,7 @@ PaintEditorMorph.prototype.buildToolbox = function() {
x = 0, x = 0,
y = 0; y = 0;
Object.keys(tools).forEach(function(tool) { Object.keys(tools).forEach(function (tool) {
var btn = myself.toolButton(tool, tools[tool]); var btn = myself.toolButton(tool, tools[tool]);
btn.setPosition(new Point( btn.setPosition(new Point(
left + x, left + x,
@ -196,7 +199,7 @@ PaintEditorMorph.prototype.buildToolbox = function() {
this.toolbox.drawNew(); this.toolbox.drawNew();
}; };
PaintEditorMorph.prototype.buildEdits = function() { PaintEditorMorph.prototype.buildEdits = function () {
var paper = this.paper; var paper = this.paper;
this.edits.add(this.pushButton( this.edits.add(this.pushButton(
@ -211,18 +214,18 @@ PaintEditorMorph.prototype.buildEdits = function() {
this.edits.fixLayout(); 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 // Open the editor in a world with an optional image to edit
this.oldim = oldim; this.oldim = oldim;
this.oldrc = oldrc.copy(); this.oldrc = oldrc.copy();
this.callback = callback || nop; this.callback = callback || nop;
this.processKeyUp = function() { this.processKeyUp = function () {
this.shift = false; this.shift = false;
this.propertiesControls.constrain.refresh(); this.propertiesControls.constrain.refresh();
}; };
this.processKeyDown = function() { this.processKeyDown = function () {
this.shift = this.world().currentKey === 16; this.shift = this.world().currentKey === 16;
this.propertiesControls.constrain.refresh(); this.propertiesControls.constrain.refresh();
}; };
@ -244,7 +247,7 @@ PaintEditorMorph.prototype.openIn = function(world, oldim, oldrc, callback) {
this.popUp(world); this.popUp(world);
}; };
PaintEditorMorph.prototype.fixLayout = function() { PaintEditorMorph.prototype.fixLayout = function () {
var oldFlag = Morph.prototype.trackChanges; var oldFlag = Morph.prototype.trackChanges;
this.changed(); this.changed();
@ -263,13 +266,13 @@ PaintEditorMorph.prototype.fixLayout = function() {
this.changed(); this.changed();
}; };
PaintEditorMorph.prototype.refreshToolButtons = function() { PaintEditorMorph.prototype.refreshToolButtons = function () {
this.toolbox.children.forEach(function (toggle) { this.toolbox.children.forEach(function (toggle) {
toggle.refresh(); toggle.refresh();
}); });
}; };
PaintEditorMorph.prototype.ok = function() { PaintEditorMorph.prototype.ok = function () {
this.callback( this.callback(
this.paper.paper, this.paper.paper,
this.paper.rotationCenter this.paper.rotationCenter
@ -282,7 +285,7 @@ PaintEditorMorph.prototype.cancel = function () {
this.destroy(); this.destroy();
}; };
PaintEditorMorph.prototype.populatePropertiesMenu = function() { PaintEditorMorph.prototype.populatePropertiesMenu = function () {
var c = this.controls, var c = this.controls,
myself = this, myself = this,
pc = this.propertiesControls, pc = this.propertiesControls,
@ -293,7 +296,7 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() {
pc.primaryColorViewer.color = new Color(0, 0, 0); pc.primaryColorViewer.color = new Color(0, 0, 0);
pc.colorpicker = new PaintColorPickerMorph( pc.colorpicker = new PaintColorPickerMorph(
new Point(180, 100), new Point(180, 100),
function(color) { function (color) {
var ni = newCanvas(pc.primaryColorViewer.extent()), var ni = newCanvas(pc.primaryColorViewer.extent()),
ctx = ni.getContext("2d"), ctx = ni.getContext("2d"),
i, i,
@ -331,7 +334,7 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() {
pc.penSizeSlider.orientation = "horizontal"; pc.penSizeSlider.orientation = "horizontal";
pc.penSizeSlider.setHeight(15); pc.penSizeSlider.setHeight(15);
pc.penSizeSlider.setWidth(150); pc.penSizeSlider.setWidth(150);
pc.penSizeSlider.action = function(num) { pc.penSizeSlider.action = function (num) {
if (pc.penSizeField) { if (pc.penSizeField) {
pc.penSizeField.setContents(num); pc.penSizeField.setContents(num);
} }
@ -341,7 +344,7 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() {
pc.penSizeField = new InputFieldMorph("5", true, null, false); pc.penSizeField = new InputFieldMorph("5", true, null, false);
pc.penSizeField.contents().minWidth = 20; pc.penSizeField.contents().minWidth = 20;
pc.penSizeField.setWidth(25); pc.penSizeField.setWidth(25);
pc.penSizeField.accept = function() { pc.penSizeField.accept = function () {
var val = parseFloat(pc.penSizeField.getValue()); var val = parseFloat(pc.penSizeField.getValue());
pc.penSizeSlider.value = val; pc.penSizeSlider.value = val;
pc.penSizeSlider.drawNew(); pc.penSizeSlider.drawNew();
@ -359,9 +362,9 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() {
pc.constrain = new ToggleMorph( pc.constrain = new ToggleMorph(
"checkbox", "checkbox",
this, this,
function() {myself.shift = !myself.shift; }, function () {myself.shift = !myself.shift; },
"Constrain proportions of shapes?\n(you can also hold 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.colorpicker);
//c.add(pc.primaryColorButton); //c.add(pc.primaryColorButton);
@ -371,7 +374,7 @@ PaintEditorMorph.prototype.populatePropertiesMenu = function() {
c.add(pc.constrain); c.add(pc.constrain);
}; };
PaintEditorMorph.prototype.toolButton = function(icon, hint) { PaintEditorMorph.prototype.toolButton = function (icon, hint) {
var button, myself = this; var button, myself = this;
button = new ToggleButtonMorph( button = new ToggleButtonMorph(
@ -381,6 +384,9 @@ PaintEditorMorph.prototype.toolButton = function(icon, hint) {
myself.paper.currentTool = icon; myself.paper.currentTool = icon;
myself.paper.toolChanged(icon); myself.paper.toolChanged(icon);
myself.refreshToolButtons(); myself.refreshToolButtons();
if (icon === 'pipette') {
myself.getUserColor();
}
}, },
new SymbolMorph(icon, 18), new SymbolMorph(icon, 18),
function () {return myself.paper.currentTool === icon; } function () {return myself.paper.currentTool === icon; }
@ -392,7 +398,7 @@ PaintEditorMorph.prototype.toolButton = function(icon, hint) {
return button; return button;
}; };
PaintEditorMorph.prototype.pushButton = function(title, action, hint) { PaintEditorMorph.prototype.pushButton = function (title, action, hint) {
return new PushButtonMorph( return new PushButtonMorph(
this, this,
action, action,
@ -402,6 +408,38 @@ PaintEditorMorph.prototype.pushButton = function(title, action, 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 ////////////////// // AdvancedColorPickerMorph //////////////////
// A large hsl color picker // A large hsl color picker
@ -414,13 +452,13 @@ function PaintColorPickerMorph(extent, action) {
this.init(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.setExtent(extent || new Point(200, 100));
this.action = action || nop; this.action = action || nop;
this.drawNew(); this.drawNew();
}; };
PaintColorPickerMorph.prototype.drawNew = function() { PaintColorPickerMorph.prototype.drawNew = function () {
var x = 0, var x = 0,
y = 0, y = 0,
can = newCanvas(this.extent()), can = newCanvas(this.extent()),
@ -464,7 +502,7 @@ PaintColorPickerMorph.prototype.drawNew = function() {
this.image = can; this.image = can;
}; };
PaintColorPickerMorph.prototype.mouseDownLeft = function(pos) { PaintColorPickerMorph.prototype.mouseDownLeft = function (pos) {
if ((pos.subtract(this.position()).x > this.width() * 2 / 3) && if ((pos.subtract(this.position()).x > this.width() * 2 / 3) &&
(pos.subtract(this.position()).y > this.height() - 10)) { (pos.subtract(this.position()).y > this.height() - 10)) {
this.action("transparent"); this.action("transparent");
@ -490,7 +528,7 @@ function PaintCanvasMorph(shift) {
this.init(shift); this.init(shift);
} }
PaintCanvasMorph.prototype.init = function(shift) { PaintCanvasMorph.prototype.init = function (shift) {
this.rotationCenter = new Point(240, 180); this.rotationCenter = new Point(240, 180);
this.dragRect = null; this.dragRect = null;
this.previousDragPoint = null; this.previousDragPoint = null;
@ -509,20 +547,20 @@ PaintCanvasMorph.prototype.init = function(shift) {
}; };
this.brushBuffer = []; this.brushBuffer = [];
this.undoBuffer = []; this.undoBuffer = [];
this.isShiftPressed = shift || function() { this.isShiftPressed = shift || function () {
var key = this.world().currentKey; var key = this.world().currentKey;
return (key === 16); return (key === 16);
}; };
this.buildContents(); this.buildContents();
}; };
PaintCanvasMorph.prototype.cacheUndo = function() { PaintCanvasMorph.prototype.cacheUndo = function () {
var cachecan = newCanvas(this.extent()); var cachecan = newCanvas(this.extent());
this.merge(this.paper, cachecan); this.merge(this.paper, cachecan);
this.undoBuffer.push(cachecan); this.undoBuffer.push(cachecan);
}; };
PaintCanvasMorph.prototype.undo = function() { PaintCanvasMorph.prototype.undo = function () {
if (this.undoBuffer.length > 0) { if (this.undoBuffer.length > 0) {
this.paper = newCanvas(this.extent()); this.paper = newCanvas(this.extent());
this.mask.width = this.mask.width + 1 - 1; 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); b.getContext("2d").drawImage(a, 0, 0);
}; };
PaintCanvasMorph.prototype.centermerge = function(a, b) { PaintCanvasMorph.prototype.centermerge = function (a, b) {
b.getContext("2d").drawImage( b.getContext("2d").drawImage(
a, a,
(b.width - a.width) / 2, (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.buildContents();
this.drawNew(); this.drawNew();
this.changed(); this.changed();
}; };
PaintCanvasMorph.prototype.toolChanged = function(tool) { PaintCanvasMorph.prototype.toolChanged = function (tool) {
this.mask = newCanvas(this.extent()); this.mask = newCanvas(this.extent());
if (tool === "crosshairs") { if (tool === "crosshairs") {
this.drawcrosshair(); this.drawcrosshair();
@ -559,7 +597,7 @@ PaintCanvasMorph.prototype.toolChanged = function(tool) {
this.changed(); this.changed();
}; };
PaintCanvasMorph.prototype.drawcrosshair = function(context) { PaintCanvasMorph.prototype.drawcrosshair = function (context) {
var ctx = context || this.mask.getContext("2d"), var ctx = context || this.mask.getContext("2d"),
rp = this.rotationCenter; rp = this.rotationCenter;
@ -612,7 +650,7 @@ PaintCanvasMorph.prototype.drawcrosshair = function(context) {
this.changed(); this.changed();
}; };
PaintCanvasMorph.prototype.floodfill = function(sourcepoint) { PaintCanvasMorph.prototype.floodfill = function (sourcepoint) {
var width = this.paper.width, var width = this.paper.width,
height = this.paper.height, height = this.paper.height,
ctx = this.paper.getContext("2d"), 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]]; return [data[d], data[d + 1], data[d + 2], data[d + 3]];
}; };
sourcecolor = read(stack[0]); sourcecolor = read(stack[0]);
checkpoint = function(p) { checkpoint = function (p) {
return p[0] === sourcecolor[0] && return p[0] === sourcecolor[0] &&
p[1] === sourcecolor[1] && p[1] === sourcecolor[1] &&
p[2] === sourcecolor[2] && p[2] === sourcecolor[2] &&
@ -660,7 +698,7 @@ PaintCanvasMorph.prototype.floodfill = function(sourcepoint) {
this.changed(); this.changed();
}; };
PaintCanvasMorph.prototype.mouseDownLeft = function(pos) { PaintCanvasMorph.prototype.mouseDownLeft = function (pos) {
this.cacheUndo(); this.cacheUndo();
this.dragRect.origin = pos.subtract(this.bounds.origin); this.dragRect.origin = pos.subtract(this.bounds.origin);
this.dragRect.corner = 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") { if (this.currentTool === "paintbucket") {
return; return;
} }
@ -824,14 +862,14 @@ PaintCanvasMorph.prototype.mouseMove = function(pos) {
mctx.restore(); mctx.restore();
}; };
PaintCanvasMorph.prototype.mouseClickLeft = function() { PaintCanvasMorph.prototype.mouseClickLeft = function () {
if (this.currentTool !== "crosshairs") { if (this.currentTool !== "crosshairs") {
this.merge(this.mask, this.paper); this.merge(this.mask, this.paper);
} }
this.brushBuffer = []; this.brushBuffer = [];
}; };
PaintCanvasMorph.prototype.buildContents = function() { PaintCanvasMorph.prototype.buildContents = function () {
this.background = newCanvas(this.extent()); this.background = newCanvas(this.extent());
this.paper = newCanvas(this.extent()); this.paper = newCanvas(this.extent());
this.mask = 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()); var can = newCanvas(this.extent());
this.merge(this.background, can); this.merge(this.background, can);
this.merge(this.paper, can); this.merge(this.paper, can);