1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)'use strict'; 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * ImageEditor is the top level object that holds together and connects 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * everything needed for image editing. 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Viewport} viewport The viewport. 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {ImageView} imageView The ImageView containing the images to edit. 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {ImageEditor.Prompt} prompt Prompt instance. 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} DOMContainers Various DOM containers required for the editor. 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Array.<ImageEditor.Mode>} modes Available editor modes. 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} displayStringFunction String formatting function. 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function()} onToolsVisibilityChanged Callback to be called, when 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * some of the UI elements have been dimmed or revealed. 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @constructor 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)function ImageEditor( 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) viewport, imageView, prompt, DOMContainers, modes, displayStringFunction, 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) onToolsVisibilityChanged) { 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.rootContainer_ = DOMContainers.root; 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.container_ = DOMContainers.image; 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.modes_ = modes; 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.displayStringFunction_ = displayStringFunction; 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.onToolsVisibilityChanged_ = onToolsVisibilityChanged; 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.removeChildren(this.container_); 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var document = this.container_.ownerDocument; 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.viewport_ = viewport; 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.viewport_.sizeByFrame(this.container_); 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.buffer_ = new ImageBuffer(); 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.viewport_.addRepaintCallback(this.buffer_.draw.bind(this.buffer_)); 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.imageView_ = imageView; 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.imageView_.addContentCallback(this.onContentUpdate_.bind(this)); 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.buffer_.addOverlay(this.imageView_); 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.panControl_ = new ImageEditor.MouseControl( 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.rootContainer_, this.container_, this.getBuffer()); 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.panControl_.setDoubleTapCallback(this.onDoubleTap_.bind(this)); 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.mainToolbar_ = new ImageEditor.Toolbar( 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DOMContainers.toolbar, displayStringFunction); 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.modeToolbar_ = new ImageEditor.Toolbar( 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DOMContainers.mode, displayStringFunction, 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.onOptionsChange.bind(this)); 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_ = prompt; 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.createToolButtons(); 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_ = null; 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {boolean} True if no user commands are to be accepted. 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.isLocked = function() { 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return !this.commandQueue_ || this.commandQueue_.isBusy(); 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {boolean} True if the command queue is busy. 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.isBusy = function() { 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return this.commandQueue_ && this.commandQueue_.isBusy(); 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Reflect the locked state of the editor in the UI. 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {boolean} on True if locked. 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.lockUI = function(on) { 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.setAttribute(this.rootContainer_, 'locked', on); 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Report the tool use to the metrics subsystem. 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name Action name. 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.recordToolUse = function(name) { 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.metrics.recordEnum( 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.getMetricName('Tool'), name, this.actionNames_); 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Content update handler. 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.onContentUpdate_ = function() { 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var i = 0; i != this.modes_.length; i++) { 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var mode = this.modes_[i]; 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.setAttribute(mode.button_, 'disabled', !mode.isApplicable()); 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Open the editing session for a new image. 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} url Image url. 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} metadata Metadata. 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} effect Transition effect object. 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function(function)} saveFunction Image save function. 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} displayCallback Display callback. 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} loadCallback Load callback. 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.openSession = function( 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) url, metadata, effect, saveFunction, displayCallback, loadCallback) { 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.commandQueue_) 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) throw new Error('Session not closed'); 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.lockUI(true); 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var self = this; 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.imageView_.load( 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) url, metadata, effect, displayCallback, function(loadType, delay, error) { 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.lockUI(false); 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.commandQueue_ = new CommandQueue( 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.container_.ownerDocument, 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.imageView_.getCanvas(), 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) saveFunction); 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.commandQueue_.attachUI( 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.getImageView(), self.getPrompt(), self.lockUI.bind(self)); 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.updateUndoRedo(); 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) loadCallback(loadType, delay, error); 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }); 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Close the current image editing session. 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} callback Callback. 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.closeSession = function(callback) { 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.getPrompt().hide(); 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.imageView_.isLoading()) { 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.commandQueue_) { 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) console.warn('Inconsistent image editor state'); 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_ = null; 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.imageView_.cancelLoad(); 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.lockUI(false); 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback(); 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.commandQueue_) { 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Session is already closed. 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback(); 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.executeWhenReady(callback); 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_.close(); 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_ = null; 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Commit the current operation and execute the action. 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} callback Callback. 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.executeWhenReady = function(callback) { 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.commandQueue_) { 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveModeGently(); 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_.executeWhenReady(callback); 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.imageView_.isLoading()) 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) console.warn('Inconsistent image editor state'); 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback(); 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {boolean} True if undo queue is not empty. 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.canUndo = function() { 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return this.commandQueue_ && this.commandQueue_.canUndo(); 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Undo the recently executed command. 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.undo = function() { 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.isLocked()) return; 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.recordToolUse('undo'); 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // First undo click should dismiss the uncommitted modifications. 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.currentMode_ && this.currentMode_.isUpdated()) { 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.reset(); 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.getPrompt().hide(); 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(false); 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_.undo(); 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateUndoRedo(); 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Redo the recently un-done command. 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.redo = function() { 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.isLocked()) return; 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.recordToolUse('redo'); 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.getPrompt().hide(); 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(false); 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_.redo(); 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateUndoRedo(); 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Update Undo/Redo buttons state. 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.updateUndoRedo = function() { 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var canUndo = this.commandQueue_ && this.commandQueue_.canUndo(); 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var canRedo = this.commandQueue_ && this.commandQueue_.canRedo(); 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.setAttribute(this.undoButton_, 'disabled', !canUndo); 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.redoButton_.hidden = !canRedo; 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {HTMLCanvasElement} The current image canvas. 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.getCanvas = function() { 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return this.getImageView().getCanvas(); 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {ImageBuffer} ImageBuffer instance. 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.getBuffer = function() { return this.buffer_ }; 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {ImageView} ImageView instance. 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.getImageView = function() { return this.imageView_ }; 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {Viewport} Viewport instance. 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.getViewport = function() { return this.viewport_ }; 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {ImageEditor.Prompt} Prompt instance. 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.getPrompt = function() { return this.prompt_ }; 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Handle the toolbar controls update. 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} options A map of options. 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.onOptionsChange = function(options) { 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.trace.resetTimer('update'); 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.currentMode_) { 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.update(options); 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.trace.reportTimer('update'); 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * ImageEditor.Mode represents a modal state dedicated to a specific operation. 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Inherits from ImageBuffer. Overlay to simplify the drawing of mode-specific 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * tools. 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name The mode name. 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} title The mode title. 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @constructor 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode = function(name, title) { 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.name = name; 279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.title = title; 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.message_ = 'GALLERY_ENTER_WHEN_DONE'; 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype = {__proto__: ImageBuffer.Overlay.prototype }; 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {Viewport} Viewport instance. 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.getViewport = function() { return this.viewport_ }; 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {ImageView} ImageView instance. 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.getImageView = function() { return this.imageView_ }; 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {string} The mode-specific message to be displayed when entering. 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.getMessage = function() { return this.message_ }; 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {boolean} True if the mode is applicable in the current context. 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.isApplicable = function() { return true }; 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Called once after creating the mode button. 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {ImageEditor} editor The editor instance. 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {HTMLElement} button The mode button. 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.bind = function(editor, button) { 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.editor_ = editor; 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.editor_.registerAction_(this.name); 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.button_ = button; 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.viewport_ = editor.getViewport(); 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.imageView_ = editor.getImageView(); 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Called before entering the mode. 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.setUp = function() { 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.editor_.getBuffer().addOverlay(this); 325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updated_ = false; 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Create mode-specific controls here. 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {ImageEditor.Toolbar} toolbar The toolbar to populate. 331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.createTools = function(toolbar) {}; 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Called before exiting the mode. 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.cleanUpUI = function() { 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.editor_.getBuffer().removeOverlay(this); 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Called after exiting the mode. 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.cleanUpCaches = function() {}; 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Called when any of the controls changed its value. 348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} options A map of options. 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.update = function(options) { 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.markUpdated(); 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Mark the editor mode as updated. 356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.markUpdated = function() { 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updated_ = true; 359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {boolean} True if the mode controls changed. 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.isUpdated = function() { return this.updated_ }; 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Resets the mode to a clean state. 368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.prototype.reset = function() { 370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.editor_.modeToolbar_.reset(); 371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updated_ = false; 372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * One-click editor tool, requires no interaction, just executes the command. 376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name The mode name. 378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} title The mode title. 379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Command} command The command to execute on click. 380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @constructor 381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.OneClick = function(name, title, command) { 383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageEditor.Mode.call(this, name, title); 384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.instant = true; 385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.command_ = command; 386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.OneClick.prototype = {__proto__: ImageEditor.Mode.prototype}; 389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {Command} command. 392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Mode.OneClick.prototype.getCommand = function() { 394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return this.command_; 395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Register the action name. Required for metrics reporting. 399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name Button name. 400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.registerAction_ = function(name) { 403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.actionNames_.push(name); 404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Populate the toolbar. 408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.createToolButtons = function() { 410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.mainToolbar_.clear(); 411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.actionNames_ = []; 412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var self = this; 414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function createButton(name, title, handler) { 415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return self.mainToolbar_.addButton(name, 416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title, 417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) handler, 418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) name /* opt_className */); 419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var i = 0; i != this.modes_.length; i++) { 422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var mode = this.modes_[i]; 423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mode.bind(this, createButton(mode.name, 424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mode.title, 425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.enterMode.bind(this, mode))); 426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.undoButton_ = createButton('undo', 429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'GALLERY_UNDO', 430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.undo.bind(this)); 431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.registerAction_('undo'); 432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.redoButton_ = createButton('redo', 434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'GALLERY_REDO', 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.redo.bind(this)); 436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.registerAction_('redo'); 437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {ImageEditor.Mode} The current mode. 441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.getMode = function() { return this.currentMode_ }; 443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * The user clicked on the mode button. 446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {ImageEditor.Mode} mode The new mode. 448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.enterMode = function(mode) { 450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.isLocked()) return; 451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.currentMode_ == mode) { 453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Currently active editor tool clicked, commit if modified. 454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(this.currentMode_.updated_); 455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.recordToolUse(mode.name); 459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveModeGently(); 461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The above call could have caused a commit which might have initiated 462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // an asynchronous command execution. Wait for it to complete, then proceed 463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // with the mode set up. 464f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_.executeWhenReady(this.setUpMode_.bind(this, mode)); 465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Set up the new editing mode. 469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {ImageEditor.Mode} mode The mode. 471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 473f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.setUpMode_ = function(mode) { 474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentTool_ = mode.button_; 475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.setAttribute(this.currentTool_, 'pressed', true); 477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_ = mode; 479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.setUp(); 480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.currentMode_.instant) { // Instant tool. 482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(true); 483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.getPrompt().show(this.currentMode_.getMessage()); 487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.modeToolbar_.clear(); 489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.createTools(this.modeToolbar_); 490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.modeToolbar_.show(true); 491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * The user clicked on 'OK' or 'Cancel' or on a different mode button. 495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {boolean} commit True if commit is required. 496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.leaveMode = function(commit) { 498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.currentMode_) return; 499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.currentMode_.instant) { 501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.getPrompt().hide(); 502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.modeToolbar_.show(false); 505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 506f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.cleanUpUI(); 507f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (commit) { 508f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var self = this; 509f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var command = this.currentMode_.getCommand(); 510f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (command) { // Could be null if the user did not do anything. 511f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.commandQueue_.execute(command); 512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateUndoRedo(); 513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.cleanUpCaches(); 516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_ = null; 517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.setAttribute(this.currentTool_, 'pressed', false); 519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentTool_ = null; 520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 522f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Leave the mode, commit only if required by the current mode. 524f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 525f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.leaveModeGently = function() { 526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(this.currentMode_ && 527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.updated_ && 528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.currentMode_.implicitCommit); 529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 532f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Enter the editor mode with the given name. 533f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 534f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name Mode name. 535f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 536f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.enterModeByName_ = function(name) { 538f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var i = 0; i != this.modes_.length; i++) { 539f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var mode = this.modes_[i]; 540f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (mode.name == name) { 541f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!mode.button_.hasAttribute('disabled')) 542f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.enterMode(mode); 543f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 544f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 545f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 546f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) console.error('Mode "' + name + '" not found.'); 547f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 548f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 549f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 550f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Key down handler. 551f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Event} event The keydown event. 552f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {boolean} True if handled. 553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.onKeyDown = function(event) { 555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) switch (util.getKeyModifiers(event) + event.keyIdentifier) { 556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'U+001B': // Escape 557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'Enter': 558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.getMode()) { 559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(event.keyIdentifier == 'Enter'); 560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 562f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 563f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 564f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'Ctrl-U+005A': // Ctrl+Z 565f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.commandQueue_.canUndo()) { 566f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.undo(); 567f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 568f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 569f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 570f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 571f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'Ctrl-U+0059': // Ctrl+Y 572f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.commandQueue_.canRedo()) { 573f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.redo(); 574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) break; 577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'U+0041': // 'a' 579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.enterModeByName_('autofix'); 580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'U+0042': // 'b' 583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.enterModeByName_('exposure'); 584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'U+0043': // 'c' 587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.enterModeByName_('crop'); 588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'U+004C': // 'l' 591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.enterModeByName_('rotate_left'); 592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) case 'U+0052': // 'r' 595f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.enterModeByName_('rotate_right'); 596f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 597f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 598f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 601f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 602f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Double tap handler. 603f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} x X coordinate of the event. 604f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} y Y coordinate of the event. 605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.onDoubleTap_ = function(x, y) { 608f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.getMode()) { 609f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var action = this.buffer_.getDoubleTapAction(x, y); 610f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (action == ImageBuffer.DoubleTapAction.COMMIT) 611f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(true); 612f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else if (action == ImageBuffer.DoubleTapAction.CANCEL) 613f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.leaveMode(false); 614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 615f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 618f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Hide the tools that overlap the given rectangular frame. 619f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 620f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Rect} frame Hide the tool that overlaps this rect. 621f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Rect} transparent But do not hide the tool that is completely inside 622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * this rect. 623f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.prototype.hideOverlappingTools = function(frame, transparent) { 625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var tools = this.rootContainer_.ownerDocument.querySelectorAll('.dimmable'); 626f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var changed = false; 627f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var i = 0; i != tools.length; i++) { 628f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var tool = tools[i]; 629f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var toolRect = tool.getBoundingClientRect(); 630f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var overlapping = 631f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (frame && frame.intersects(toolRect)) && 632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) !(transparent && transparent.contains(toolRect)); 633f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (overlapping && !tool.hasAttribute('dimmed') || 634f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) !overlapping && tool.hasAttribute('dimmed')) { 635f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.setAttribute(tool, 'dimmed', overlapping); 636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) changed = true; 637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 638f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 639f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (changed) 640f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.onToolsVisibilityChanged_(); 641f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 642f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 643f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 644f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * A helper object for panning the ImageBuffer. 645f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 646f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {HTMLElement} rootContainer The top-level container. 647f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {HTMLElement} container The container for mouse events. 648f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {ImageBuffer} buffer Image buffer. 649f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @constructor 650f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 651f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl = function(rootContainer, container, buffer) { 652f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.rootContainer_ = rootContainer; 653f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.container_ = container; 654f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.buffer_ = buffer; 655f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 656f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var handlers = { 657f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'touchstart': this.onTouchStart, 658f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'touchend': this.onTouchEnd, 659f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'touchcancel': this.onTouchCancel, 660f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'touchmove': this.onTouchMove, 661f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'mousedown': this.onMouseDown, 662f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'mouseup': this.onMouseUp 663f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 664f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 665f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var eventName in handlers) { 666f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) container.addEventListener( 667f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) eventName, handlers[eventName].bind(this), false); 668f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 669f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 670f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Mouse move handler has to be attached to the window to receive events 671f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // from outside of the window. See: http://crbug.com/155705 672f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) window.addEventListener('mousemove', this.onMouseMove.bind(this), false); 673f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 674f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 675f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 676f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Maximum movement for touch to be detected as a tap (in pixels). 677f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 678f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 679f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.MAX_MOVEMENT_FOR_TAP_ = 8; 680f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 681f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 682f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Maximum time for touch to be detected as a tap (in milliseconds). 683f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 684f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 685f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.MAX_TAP_DURATION_ = 500; 686f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 687f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 688f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Maximum distance from the first tap to the second tap to be considered 689f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * as a double tap. 690f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 691f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 692f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.MAX_DISTANCE_FOR_DOUBLE_TAP_ = 32; 693f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 694f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 695f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Maximum time for touch to be detected as a double tap (in milliseconds). 696f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 697f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 698f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.MAX_DOUBLE_TAP_DURATION_ = 1000; 699f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 700f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 701f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Returns an event's position. 702f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 703f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {MouseEvent|Touch} e Pointer position. 704f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {Object} A pair of x,y in page coordinates. 705f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 706f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 707f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.getPosition_ = function(e) { 708f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return { 709f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) x: e.pageX, 710f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) y: e.pageY 711f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 712f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 713f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 714f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 715f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Returns touch position or null if there is more than one touch position. 716f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 717f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {TouchEvent} e Event. 718f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {object?} A pair of x,y in page coordinates. 719f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 720f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 721f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.getTouchPosition_ = function(e) { 722f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (e.targetTouches.length == 1) 723f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ImageEditor.MouseControl.getPosition_(e.targetTouches[0]); 724f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else 725f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return null; 726f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 727f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 728f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 729f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Touch start handler. 730f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {TouchEvent} e Event. 731f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 732f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchStart = function(e) { 733f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var position = this.getTouchPosition_(e); 734f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (position) { 735f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.touchStartInfo_ = { 736f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) x: position.x, 737f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) y: position.y, 738f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) time: Date.now() 739f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 740f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHandler_ = this.buffer_.getDragHandler(position.x, position.y, 741f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) true /* touch */); 742f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHappened_ = false; 743f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) e.preventDefault(); 744f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 745f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 746f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 747f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 748f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Touch end handler. 749f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {TouchEvent} e Event. 750f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 751f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchEnd = function(e) { 752f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.dragHappened_ && Date.now() - this.touchStartInfo_.time <= 753f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageEditor.MouseControl.MAX_TAP_DURATION_) { 754f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.buffer_.onClick(this.touchStartInfo_.x, this.touchStartInfo_.y); 755f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.previousTouchStartInfo_ && 756f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Date.now() - this.previousTouchStartInfo_.time < 757f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageEditor.MouseControl.MAX_DOUBLE_TAP_DURATION_) { 758f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var prevTouchCircle = new Circle( 759f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.previousTouchStartInfo_.x, 760f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.previousTouchStartInfo_.y, 761f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageEditor.MouseControl.MAX_DISTANCE_FOR_DOUBLE_TAP_); 762f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (prevTouchCircle.inside(this.touchStartInfo_.x, 763f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.touchStartInfo_.y)) { 764f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.doubleTapCallback_(this.touchStartInfo_.x, this.touchStartInfo_.y); 765f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 766f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 767f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.previousTouchStartInfo_ = this.touchStartInfo_; 768f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 769f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.previousTouchStartInfo_ = null; 770f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.onTouchCancel(e); 772f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 773f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 774f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 775f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Default double tap handler. 776f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} x X coordinate of the event. 777f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} y Y coordinate of the event. 778f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 779f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 780f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.doubleTapCallback_ = function(x, y) {}; 781f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 782f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 783f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Sets callback to be called when double tap detected. 784f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function(number, number)} callback New double tap callback. 785f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 786f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.setDoubleTapCallback = function(callback) { 787f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.doubleTapCallback_ = callback; 788f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 789f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 790f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 791f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Touch cancel handler. 792f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 793f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchCancel = function() { 794f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHandler_ = null; 795f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHappened_ = false; 796f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.touchStartInfo_ = null; 797f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.lockMouse_(false); 798f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 799f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 800f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 801f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Touch move handler. 802f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {TouchEvent} e Event. 803f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 804f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchMove = function(e) { 805f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var position = this.getTouchPosition_(e); 806f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!position) 807f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; 808f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 809f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.touchStartInfo_ && !this.dragHappened_) { 810f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var tapCircle = new Circle(this.touchStartInfo_.x, this.touchStartInfo_.y, 811f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageEditor.MouseControl.MAX_MOVEMENT_FOR_TAP_); 812f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHappened_ = !tapCircle.inside(position.x, position.y); 813f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 814f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.dragHandler_ && this.dragHappened_) { 815f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHandler_(position.x, position.y); 816f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.lockMouse_(true); 817f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 818f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 819f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 820f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 821f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Mouse down handler. 822f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {MouseEvent} e Event. 823f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 824f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.onMouseDown = function(e) { 825f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var position = ImageEditor.MouseControl.getPosition_(e); 826f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 827f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHandler_ = this.buffer_.getDragHandler(position.x, position.y, 828f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) false /* mouse */); 829f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHappened_ = false; 830f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateCursor_(position); 831f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 832f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 833f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 834f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Mouse up handler. 835f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {MouseEvent} e Event. 836f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 837f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.onMouseUp = function(e) { 838f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var position = ImageEditor.MouseControl.getPosition_(e); 839f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 840f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.dragHappened_) { 841f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.buffer_.onClick(position.x, position.y); 842f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 843f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHandler_ = null; 844f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHappened_ = false; 845f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.lockMouse_(false); 846f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 847f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 848f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 849f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Mouse move handler. 850f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {MouseEvent} e Event. 851f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 852f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.onMouseMove = function(e) { 853f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var position = ImageEditor.MouseControl.getPosition_(e); 854f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 855f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.dragHandler_ && !e.which) { 856f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // mouseup must have happened while the mouse was outside our window. 857f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHandler_ = null; 858f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.lockMouse_(false); 859f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 860f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 861f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateCursor_(position); 862f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.dragHandler_) { 863f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHandler_(position.x, position.y); 864f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.dragHappened_ = true; 865f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.lockMouse_(true); 866f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 867f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 868f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 869f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 870f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Update the UI to reflect mouse drag state. 871f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {boolean} on True if dragging. 872f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 873f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 874f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.lockMouse_ = function(on) { 875f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.setAttribute(this.rootContainer_, 'mousedrag', on); 876f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 877f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 878f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 879f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Update the cursor. 880f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 881f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} position An object holding x and y properties. 882f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 883f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 884f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.MouseControl.prototype.updateCursor_ = function(position) { 885f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var oldCursor = this.container_.getAttribute('cursor'); 886f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var newCursor = this.buffer_.getCursorStyle( 887f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) position.x, position.y, !!this.dragHandler_); 888f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (newCursor != oldCursor) // Avoid flicker. 889f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.container_.setAttribute('cursor', newCursor); 890f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 891f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 892f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 893f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * A toolbar for the ImageEditor. 894f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {HTMLElement} parent The parent element. 895f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} displayStringFunction A string formatting function. 896f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} updateCallback The callback called when controls change. 897f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @constructor 898f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 899f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar = function(parent, displayStringFunction, updateCallback) { 900f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_ = parent; 901f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.displayStringFunction_ = displayStringFunction; 902f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.updateCallback_ = updateCallback; 903f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 904f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 905f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 906f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Clear the toolbar. 907f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 908f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.clear = function() { 909f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ImageUtil.removeChildren(this.wrapper_); 910f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 911f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 912f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 913f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Create a control. 914f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} tagName The element tag name. 915f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {HTMLElement} The created control element. 916f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @private 917f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 918f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.create_ = function(tagName) { 919f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return this.wrapper_.ownerDocument.createElement(tagName); 920f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 921f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 922f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 923f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Add a control. 924f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {HTMLElement} element The control to add. 925f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {HTMLElement} The added element. 926f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 927f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.add = function(element) { 928f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_.appendChild(element); 929f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return element; 930f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 931f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 932f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 933f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Add a text label. 934f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name Label name. 935f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {HTMLElement} The added label. 936f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 937f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.addLabel = function(name) { 938f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var label = this.create_('span'); 939f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) label.textContent = this.displayStringFunction_(name); 940f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return this.add(label); 941f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 942f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 943f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 944f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Add a button. 945f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 946f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name Button name. 947f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} title Button title. 948f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} handler onClick handler. 949f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string=} opt_class Extra class name. 950f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {HTMLElement} The added button. 951f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 952f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.addButton = function( 953f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) name, title, handler, opt_class) { 954f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var button = this.create_('button'); 955f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (opt_class) button.classList.add(opt_class); 956f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var label = this.create_('span'); 957f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) label.textContent = this.displayStringFunction_(title); 958f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) button.appendChild(label); 959f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) button.label = this.displayStringFunction_(title); 960f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) button.addEventListener('click', handler, false); 961f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return this.add(button); 962f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 963f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 964f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 965f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Add a range control (scalar value picker). 966f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 967f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} name An option name. 968f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} title An option title. 969f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} min Min value of the option. 970f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} value Default value of the option. 971f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} max Max value of the options. 972f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} scale A number to multiply by when setting 973f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * min/value/max in DOM. 974f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {boolean=} opt_showNumeric True if numeric value should be displayed. 975f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {HTMLElement} Range element. 976f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 977f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.addRange = function( 978f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) name, title, min, value, max, scale, opt_showNumeric) { 979f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var self = this; 980f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 981f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scale = scale || 1; 982f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 983f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var range = this.create_('input'); 984f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 985f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.className = 'range'; 986f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.type = 'range'; 987f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.name = name; 988f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.min = Math.ceil(min * scale); 989f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.max = Math.floor(max * scale); 990f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 991f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var numeric = this.create_('div'); 992f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) numeric.className = 'numeric'; 993f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function mirror() { 994f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) numeric.textContent = Math.round(range.getValue() * scale) / scale; 995f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 996f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 997f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.setValue = function(newValue) { 998f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.value = Math.round(newValue * scale); 999f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mirror(); 1000f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 1001f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1002f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.getValue = function() { 1003f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return Number(range.value) / scale; 1004f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 1005f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1006f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.reset = function() { 1007f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.setValue(value); 1008f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 1009f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1010f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.addEventListener('change', 1011f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function() { 1012f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) mirror(); 1013f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.updateCallback_(self.getOptions()); 1014f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }, 1015f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) false); 1016f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1017f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.setValue(value); 1018f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1019f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var label = this.create_('div'); 1020f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) label.textContent = this.displayStringFunction_(title); 1021f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) label.className = 'label ' + name; 1022f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.add(label); 1023f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.add(range); 1024f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1025f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (opt_showNumeric) 1026f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.add(numeric); 1027f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1028f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Swallow the left and right keys, so they are not handled by other 1029f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // listeners. 1030f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) range.addEventListener('keydown', function(e) { 1031f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (e.keyIdentifier === 'Left' || e.keyIdentifier === 'Right') 1032f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) e.stopPropagation(); 1033f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }); 1034f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1035f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return range; 1036f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1037f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1038f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1039f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @return {Object} options A map of options. 1040f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1041f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.getOptions = function() { 1042f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var values = {}; 1043f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var child = this.wrapper_.firstChild; child; child = child.nextSibling) { 1044f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (child.name) 1045f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) values[child.name] = child.getValue(); 1046f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1047f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return values; 1048f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1049f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1050f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1051f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Reset the toolbar. 1052f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1053f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.reset = function() { 1054f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var child = this.wrapper_.firstChild; child; child = child.nextSibling) { 1055f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (child.reset) child.reset(); 1056f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1057f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1058f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1059f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1060f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Show/hide the toolbar. 1061f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {boolean} on True if show. 1062f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1063f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Toolbar.prototype.show = function(on) { 1064f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.wrapper_.firstChild) 1065f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return; // Do not show empty toolbar; 1066f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1067f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_.hidden = !on; 1068f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1069f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1070f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** A prompt panel for the editor. 1071f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 1072f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {HTMLElement} container Container element. 1073f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} displayStringFunction A formatting function. 1074f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @constructor 1075f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1076f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Prompt = function(container, displayStringFunction) { 1077f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.container_ = container; 1078f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.displayStringFunction_ = displayStringFunction; 1079f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1080f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1081f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1082f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Reset the prompt. 1083f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1084f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Prompt.prototype.reset = function() { 1085f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.cancelTimer(); 1086f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.wrapper_) { 1087f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.container_.removeChild(this.wrapper_); 1088f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_ = null; 1089f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_ = null; 1090f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1091f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1092f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1093f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1094f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Cancel the delayed action. 1095f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1096f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Prompt.prototype.cancelTimer = function() { 1097f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (this.timer_) { 1098f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) clearTimeout(this.timer_); 1099f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.timer_ = null; 1100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 1101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Schedule the delayed action. 1105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} callback Callback. 1106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} timeout Timeout. 1107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Prompt.prototype.setTimer = function(callback, timeout) { 1109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.cancelTimer(); 1110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var self = this; 1111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.timer_ = setTimeout(function() { 1112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) self.timer_ = null; 1113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback(); 1114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }, timeout); 1115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Show the prompt. 1119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 1120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} text The prompt text. 1121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} timeout Timeout in ms. 1122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} formatArgs varArgs for the formatting function. 1123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Prompt.prototype.show = function(text, timeout, formatArgs) { 1125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.showAt.apply(this, 1126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ['center'].concat(Array.prototype.slice.call(arguments))); 1127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * 1131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} pos The 'pos' attribute value. 1132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string} text The prompt text. 1133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {number} timeout Timeout in ms. 1134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} formatArgs varArgs for the formatting function. 1135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Prompt.prototype.showAt = function(pos, text, timeout, formatArgs) { 1137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.reset(); 1138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!text) return; 1139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var document = this.container_.ownerDocument; 1141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_ = document.createElement('div'); 1142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_.className = 'prompt-wrapper'; 1143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_.setAttribute('pos', pos); 1144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.container_.appendChild(this.wrapper_); 1145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_ = document.createElement('div'); 1147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_.className = 'prompt'; 1148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Create an extra wrapper which opacity can be manipulated separately. 1150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var tool = document.createElement('div'); 1151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tool.className = 'dimmable'; 1152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.wrapper_.appendChild(tool); 1153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tool.appendChild(this.prompt_); 1154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var args = [text].concat(Array.prototype.slice.call(arguments, 3)); 1156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_.textContent = this.displayStringFunction_.apply(null, args); 1157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var close = document.createElement('div'); 1159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) close.className = 'close'; 1160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) close.addEventListener('click', this.hide.bind(this)); 1161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_.appendChild(close); 1162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) setTimeout( 1164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_.setAttribute.bind(this.prompt_, 'state', 'fadein'), 0); 1165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (timeout) 1167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.setTimer(this.hide.bind(this), timeout); 1168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/** 1171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Hide the prompt. 1172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */ 1173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ImageEditor.Prompt.prototype.hide = function() { 1174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!this.prompt_) return; 1175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.prompt_.setAttribute('state', 'fadeout'); 1176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Allow some time for the animation to play out. 1177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) this.setTimer(this.reset.bind(this), 500); 1178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 1179