15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)'use strict'; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ImageEditor is the top level object that holds together and connects 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * everything needed for image editing. 101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Viewport} viewport The viewport. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageView} imageView The ImageView containing the images to edit. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageEditor.Prompt} prompt Prompt instance. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Object} DOMContainers Various DOM containers required for the editor. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array.<ImageEditor.Mode>} modes Available editor modes. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} displayStringFunction String formatting function. 171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * @param {function()} onToolsVisibilityChanged Callback to be called, when 181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * some of the UI elements have been dimmed or revealed. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function ImageEditor( 221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) viewport, imageView, prompt, DOMContainers, modes, displayStringFunction, 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) onToolsVisibilityChanged) { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rootContainer_ = DOMContainers.root; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_ = DOMContainers.image; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.modes_ = modes; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.displayStringFunction_ = displayStringFunction; 281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.onToolsVisibilityChanged_ = onToolsVisibilityChanged; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.removeChildren(this.container_); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var document = this.container_.ownerDocument; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.viewport_ = viewport; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.viewport_.sizeByFrame(this.container_); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.buffer_ = new ImageBuffer(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.viewport_.addRepaintCallback(this.buffer_.draw.bind(this.buffer_)); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.imageView_ = imageView; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.imageView_.addContentCallback(this.onContentUpdate_.bind(this)); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.buffer_.addOverlay(this.imageView_); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.panControl_ = new ImageEditor.MouseControl( 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rootContainer_, this.container_, this.getBuffer()); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.panControl_.setDoubleTapCallback(this.onDoubleTap_.bind(this)); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mainToolbar_ = new ImageEditor.Toolbar( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOMContainers.toolbar, displayStringFunction); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.modeToolbar_ = new ImageEditor.Toolbar( 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DOMContainers.mode, displayStringFunction, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onOptionsChange.bind(this)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_ = prompt; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.createToolButtons(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.commandQueue_ = null; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if no user commands are to be accepted. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.isLocked = function() { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !this.commandQueue_ || this.commandQueue_.isBusy(); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if the command queue is busy. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.isBusy = function() { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.commandQueue_ && this.commandQueue_.isBusy(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reflect the locked state of the editor in the UI. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} on True if locked. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.lockUI = function(on) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setAttribute(this.rootContainer_, 'locked', on); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Report the tool use to the metrics subsystem. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Action name. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.recordToolUse = function(name) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.metrics.recordEnum( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.getMetricName('Tool'), name, this.actionNames_); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Content update handler. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.onContentUpdate_ = function() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i != this.modes_.length; i++) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mode = this.modes_[i]; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setAttribute(mode.button_, 'disabled', !mode.isApplicable()); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Open the editing session for a new image. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} url Image url. 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} metadata Metadata. 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} effect Transition effect object. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function(function)} saveFunction Image save function. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} displayCallback Display callback. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} loadCallback Load callback. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.openSession = function( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, metadata, effect, saveFunction, displayCallback, loadCallback) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.commandQueue_) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throw new Error('Session not closed'); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lockUI(true); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.imageView_.load( 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, metadata, effect, displayCallback, function(loadType, delay, error) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.lockUI(false); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.commandQueue_ = new CommandQueue( 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.container_.ownerDocument, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.imageView_.getCanvas(), 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saveFunction); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.commandQueue_.attachUI( 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.getImageView(), self.getPrompt(), self.lockUI.bind(self)); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.updateUndoRedo(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loadCallback(loadType, delay, error); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Close the current image editing session. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} callback Callback. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.closeSession = function(callback) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.getPrompt().hide(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.imageView_.isLoading()) { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.commandQueue_) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.warn('Inconsistent image editor state'); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.commandQueue_ = null; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.imageView_.cancelLoad(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lockUI(false); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback(); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!this.commandQueue_) { 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Session is already closed. 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback(); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.executeWhenReady(callback); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.commandQueue_.close(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.commandQueue_ = null; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Commit the current operation and execute the action. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} callback Callback. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.executeWhenReady = function(callback) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.commandQueue_) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveModeGently(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.commandQueue_.executeWhenReady(callback); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.imageView_.isLoading()) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.warn('Inconsistent image editor state'); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {boolean} True if undo queue is not empty. 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ImageEditor.prototype.canUndo = function() { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return this.commandQueue_ && this.commandQueue_.canUndo(); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Undo the recently executed command. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.undo = function() { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.isLocked()) return; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.recordToolUse('undo'); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First undo click should dismiss the uncommitted modifications. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.currentMode_ && this.currentMode_.isUpdated()) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.reset(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.getPrompt().hide(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(false); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.commandQueue_.undo(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateUndoRedo(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redo the recently un-done command. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.redo = function() { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.isLocked()) return; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.recordToolUse('redo'); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.getPrompt().hide(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(false); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.commandQueue_.redo(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateUndoRedo(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Update Undo/Redo buttons state. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.updateUndoRedo = function() { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var canUndo = this.commandQueue_ && this.commandQueue_.canUndo(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var canRedo = this.commandQueue_ && this.commandQueue_.canRedo(); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setAttribute(this.undoButton_, 'disabled', !canUndo); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redoButton_.hidden = !canRedo; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLCanvasElement} The current image canvas. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.getCanvas = function() { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.getImageView().getCanvas(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ImageBuffer} ImageBuffer instance. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.getBuffer = function() { return this.buffer_ }; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ImageView} ImageView instance. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.getImageView = function() { return this.imageView_ }; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Viewport} Viewport instance. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.getViewport = function() { return this.viewport_ }; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ImageEditor.Prompt} Prompt instance. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.getPrompt = function() { return this.prompt_ }; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle the toolbar controls update. 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} options A map of options. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.onOptionsChange = function(options) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.trace.resetTimer('update'); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.currentMode_) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.update(options); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.trace.reportTimer('update'); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ImageEditor.Mode represents a modal state dedicated to a specific operation. 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Inherits from ImageBuffer. Overlay to simplify the drawing of mode-specific 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * tools. 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name The mode name. 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @param {string} title The mode title. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochImageEditor.Mode = function(name, title) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.name = name; 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.title = title; 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.message_ = 'GALLERY_ENTER_WHEN_DONE'; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype = {__proto__: ImageBuffer.Overlay.prototype }; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Viewport} Viewport instance. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.getViewport = function() { return this.viewport_ }; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ImageView} ImageView instance. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.getImageView = function() { return this.imageView_ }; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} The mode-specific message to be displayed when entering. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.getMessage = function() { return this.message_ }; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if the mode is applicable in the current context. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.isApplicable = function() { return true }; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called once after creating the mode button. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageEditor} editor The editor instance. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} button The mode button. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.bind = function(editor, button) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.editor_ = editor; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.editor_.registerAction_(this.name); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.button_ = button; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.viewport_ = editor.getViewport(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.imageView_ = editor.getImageView(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called before entering the mode. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.setUp = function() { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.editor_.getBuffer().addOverlay(this); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updated_ = false; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create mode-specific controls here. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageEditor.Toolbar} toolbar The toolbar to populate. 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.createTools = function(toolbar) {}; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called before exiting the mode. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.cleanUpUI = function() { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.editor_.getBuffer().removeOverlay(this); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called after exiting the mode. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.cleanUpCaches = function() {}; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when any of the controls changed its value. 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} options A map of options. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.update = function(options) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.markUpdated(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mark the editor mode as updated. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.markUpdated = function() { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updated_ = true; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if the mode controls changed. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.isUpdated = function() { return this.updated_ }; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Resets the mode to a clean state. 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.prototype.reset = function() { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.editor_.modeToolbar_.reset(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updated_ = false; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * One-click editor tool, requires no interaction, just executes the command. 376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name The mode name. 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @param {string} title The mode title. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Command} command The command to execute on click. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochImageEditor.Mode.OneClick = function(name, title, command) { 383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ImageEditor.Mode.call(this, name, title); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.instant = true; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.command_ = command; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.OneClick.prototype = {__proto__: ImageEditor.Mode.prototype}; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {Command} command. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Mode.OneClick.prototype.getCommand = function() { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.command_; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Register the action name. Required for metrics reporting. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Button name. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.registerAction_ = function(name) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.actionNames_.push(name); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Populate the toolbar. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.createToolButtons = function() { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mainToolbar_.clear(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.actionNames_ = []; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch function createButton(name, title, handler) { 415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return self.mainToolbar_.addButton(name, 416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch title, 417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch handler, 418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch name /* opt_className */); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i != this.modes_.length; i++) { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mode = this.modes_[i]; 423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mode.bind(this, createButton(mode.name, 424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mode.title, 425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.enterMode.bind(this, mode))); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.undoButton_ = createButton('undo', 429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 'GALLERY_UNDO', 430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.undo.bind(this)); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.registerAction_('undo'); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.redoButton_ = createButton('redo', 434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 'GALLERY_REDO', 435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.redo.bind(this)); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.registerAction_('redo'); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {ImageEditor.Mode} The current mode. 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.getMode = function() { return this.currentMode_ }; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The user clicked on the mode button. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageEditor.Mode} mode The new mode. 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.enterMode = function(mode) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.isLocked()) return; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.currentMode_ == mode) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Currently active editor tool clicked, commit if modified. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(this.currentMode_.updated_); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.recordToolUse(mode.name); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveModeGently(); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The above call could have caused a commit which might have initiated 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an asynchronous command execution. Wait for it to complete, then proceed 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with the mode set up. 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.commandQueue_.executeWhenReady(this.setUpMode_.bind(this, mode)); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Set up the new editing mode. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageEditor.Mode} mode The mode. 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.setUpMode_ = function(mode) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentTool_ = mode.button_; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setAttribute(this.currentTool_, 'pressed', true); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_ = mode; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.setUp(); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.currentMode_.instant) { // Instant tool. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(true); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.getPrompt().show(this.currentMode_.getMessage()); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.modeToolbar_.clear(); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.createTools(this.modeToolbar_); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.modeToolbar_.show(true); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The user clicked on 'OK' or 'Cancel' or on a different mode button. 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} commit True if commit is required. 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.leaveMode = function(commit) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.currentMode_) return; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.currentMode_.instant) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.getPrompt().hide(); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.modeToolbar_.show(false); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.cleanUpUI(); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (commit) { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var command = this.currentMode_.getCommand(); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command) { // Could be null if the user did not do anything. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.commandQueue_.execute(command); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateUndoRedo(); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.cleanUpCaches(); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_ = null; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setAttribute(this.currentTool_, 'pressed', false); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentTool_ = null; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Leave the mode, commit only if required by the current mode. 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.leaveModeGently = function() { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(this.currentMode_ && 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.updated_ && 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentMode_.implicitCommit); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Enter the editor mode with the given name. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Mode name. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.enterModeByName_ = function(name) { 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i != this.modes_.length; i++) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var mode = this.modes_[i]; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode.name == name) { 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!mode.button_.hasAttribute('disabled')) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterMode(mode); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.error('Mode "' + name + '" not found.'); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Key down handler. 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} event The keydown event. 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if handled. 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.onKeyDown = function(event) { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (util.getKeyModifiers(event) + event.keyIdentifier) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'U+001B': // Escape 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'Enter': 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.getMode()) { 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(event.keyIdentifier == 'Enter'); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'Ctrl-U+005A': // Ctrl+Z 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.commandQueue_.canUndo()) { 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.undo(); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'Ctrl-U+0059': // Ctrl+Y 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.commandQueue_.canRedo()) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redo(); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'U+0041': // 'a' 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterModeByName_('autofix'); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'U+0042': // 'b' 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterModeByName_('exposure'); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'U+0043': // 'c' 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterModeByName_('crop'); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'U+004C': // 'l' 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterModeByName_('rotate_left'); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'U+0052': // 'r' 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.enterModeByName_('rotate_right'); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Double tap handler. 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} x X coordinate of the event. 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} y Y coordinate of the event. 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.onDoubleTap_ = function(x, y) { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.getMode()) { 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var action = this.buffer_.getDoubleTapAction(x, y); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (action == ImageBuffer.DoubleTapAction.COMMIT) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(true); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (action == ImageBuffer.DoubleTapAction.CANCEL) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.leaveMode(false); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Hide the tools that overlap the given rectangular frame. 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} frame Hide the tool that overlaps this rect. 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Rect} transparent But do not hide the tool that is completely inside 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this rect. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.prototype.hideOverlappingTools = function(frame, transparent) { 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tools = this.rootContainer_.ownerDocument.querySelectorAll('.dimmable'); 6261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) var changed = false; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i != tools.length; i++) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tool = tools[i]; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var toolRect = tool.getBoundingClientRect(); 6301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) var overlapping = 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (frame && frame.intersects(toolRect)) && 6321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) !(transparent && transparent.contains(toolRect)); 6331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (overlapping && !tool.hasAttribute('dimmed') || 6341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) !overlapping && tool.hasAttribute('dimmed')) { 6351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ImageUtil.setAttribute(tool, 'dimmed', overlapping); 6361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) changed = true; 6371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (changed) 6401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) this.onToolsVisibilityChanged_(); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A helper object for panning the ImageBuffer. 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} rootContainer The top-level container. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} container The container for mouse events. 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageBuffer} buffer Image buffer. 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl = function(rootContainer, container, buffer) { 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.rootContainer_ = rootContainer; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_ = container; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.buffer_ = buffer; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var handlers = { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'touchstart': this.onTouchStart, 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'touchend': this.onTouchEnd, 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'touchcancel': this.onTouchCancel, 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'touchmove': this.onTouchMove, 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'mousedown': this.onMouseDown, 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'mouseup': this.onMouseUp 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var eventName in handlers) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container.addEventListener( 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eventName, handlers[eventName].bind(this), false); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Mouse move handler has to be attached to the window to receive events 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from outside of the window. See: http://crbug.com/155705 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window.addEventListener('mousemove', this.onMouseMove.bind(this), false); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Maximum movement for touch to be detected as a tap (in pixels). 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.MAX_MOVEMENT_FOR_TAP_ = 8; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Maximum time for touch to be detected as a tap (in milliseconds). 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.MAX_TAP_DURATION_ = 500; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Maximum distance from the first tap to the second tap to be considered 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as a double tap. 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.MAX_DISTANCE_FOR_DOUBLE_TAP_ = 32; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Maximum time for touch to be detected as a double tap (in milliseconds). 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.MAX_DOUBLE_TAP_DURATION_ = 1000; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 70190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Returns an event's position. 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {MouseEvent|Touch} e Pointer position. 70490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * @return {Object} A pair of x,y in page coordinates. 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.getPosition_ = function(e) { 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 70990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) x: e.pageX, 71090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) y: e.pageY 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns touch position or null if there is more than one touch position. 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {TouchEvent} e Event. 71890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * @return {object?} A pair of x,y in page coordinates. 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.getTouchPosition_ = function(e) { 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.targetTouches.length == 1) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ImageEditor.MouseControl.getPosition_(e.targetTouches[0]); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Touch start handler. 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {TouchEvent} e Event. 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchStart = function(e) { 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var position = this.getTouchPosition_(e); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (position) { 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touchStartInfo_ = { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x: position.x, 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y: position.y, 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time: Date.now() 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHandler_ = this.buffer_.getDragHandler(position.x, position.y, 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* touch */); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHappened_ = false; 7430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch e.preventDefault(); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Touch end handler. 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {TouchEvent} e Event. 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchEnd = function(e) { 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.dragHappened_ && Date.now() - this.touchStartInfo_.time <= 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageEditor.MouseControl.MAX_TAP_DURATION_) { 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.buffer_.onClick(this.touchStartInfo_.x, this.touchStartInfo_.y); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.previousTouchStartInfo_ && 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Date.now() - this.previousTouchStartInfo_.time < 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageEditor.MouseControl.MAX_DOUBLE_TAP_DURATION_) { 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var prevTouchCircle = new Circle( 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.previousTouchStartInfo_.x, 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.previousTouchStartInfo_.y, 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageEditor.MouseControl.MAX_DISTANCE_FOR_DOUBLE_TAP_); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prevTouchCircle.inside(this.touchStartInfo_.x, 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touchStartInfo_.y)) { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.doubleTapCallback_(this.touchStartInfo_.x, this.touchStartInfo_.y); 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.previousTouchStartInfo_ = this.touchStartInfo_; 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.previousTouchStartInfo_ = null; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onTouchCancel(e); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Default double tap handler. 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} x X coordinate of the event. 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} y Y coordinate of the event. 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.doubleTapCallback_ = function(x, y) {}; 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sets callback to be called when double tap detected. 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function(number, number)} callback New double tap callback. 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.setDoubleTapCallback = function(callback) { 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.doubleTapCallback_ = callback; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 791f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Touch cancel handler. 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchCancel = function() { 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHandler_ = null; 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHappened_ = false; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touchStartInfo_ = null; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lockMouse_(false); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Touch move handler. 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {TouchEvent} e Event. 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.onTouchMove = function(e) { 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var position = this.getTouchPosition_(e); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!position) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.touchStartInfo_ && !this.dragHappened_) { 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tapCircle = new Circle(this.touchStartInfo_.x, this.touchStartInfo_.y, 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageEditor.MouseControl.MAX_MOVEMENT_FOR_TAP_); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHappened_ = !tapCircle.inside(position.x, position.y); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dragHandler_ && this.dragHappened_) { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHandler_(position.x, position.y); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lockMouse_(true); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mouse down handler. 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {MouseEvent} e Event. 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.onMouseDown = function(e) { 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var position = ImageEditor.MouseControl.getPosition_(e); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHandler_ = this.buffer_.getDragHandler(position.x, position.y, 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false /* mouse */); 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHappened_ = false; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateCursor_(position); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mouse up handler. 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {MouseEvent} e Event. 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.onMouseUp = function(e) { 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var position = ImageEditor.MouseControl.getPosition_(e); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.dragHappened_) { 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.buffer_.onClick(position.x, position.y); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHandler_ = null; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHappened_ = false; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lockMouse_(false); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mouse move handler. 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {MouseEvent} e Event. 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.onMouseMove = function(e) { 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var position = ImageEditor.MouseControl.getPosition_(e); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dragHandler_ && !e.which) { 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mouseup must have happened while the mouse was outside our window. 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHandler_ = null; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lockMouse_(false); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateCursor_(position); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.dragHandler_) { 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHandler_(position.x, position.y); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dragHappened_ = true; 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lockMouse_(true); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Update the UI to reflect mouse drag state. 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} on True if dragging. 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.lockMouse_ = function(on) { 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setAttribute(this.rootContainer_, 'mousedrag', on); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Update the cursor. 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {Object} position An object holding x and y properties. 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.MouseControl.prototype.updateCursor_ = function(position) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var oldCursor = this.container_.getAttribute('cursor'); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCursor = this.buffer_.getCursorStyle( 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) position.x, position.y, !!this.dragHandler_); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newCursor != oldCursor) // Avoid flicker. 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.setAttribute('cursor', newCursor); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A toolbar for the ImageEditor. 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} parent The parent element. 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} displayStringFunction A string formatting function. 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} updateCallback The callback called when controls change. 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar = function(parent, displayStringFunction, updateCallback) { 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_ = parent; 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.displayStringFunction_ = displayStringFunction; 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateCallback_ = updateCallback; 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clear the toolbar. 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.clear = function() { 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.removeChildren(this.wrapper_); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create a control. 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} tagName The element tag name. 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLElement} The created control element. 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.create_ = function(tagName) { 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.wrapper_.ownerDocument.createElement(tagName); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add a control. 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} element The control to add. 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLElement} The added element. 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.add = function(element) { 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_.appendChild(element); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return element; 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add a text label. 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Label name. 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLElement} The added label. 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.addLabel = function(name) { 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var label = this.create_('span'); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label.textContent = this.displayStringFunction_(name); 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.add(label); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add a button. 945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name Button name. 947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @param {string} title Button title. 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} handler onClick handler. 9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string=} opt_class Extra class name. 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLElement} The added button. 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.addButton = function( 953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch name, title, handler, opt_class) { 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var button = this.create_('button'); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_class) button.classList.add(opt_class); 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var label = this.create_('span'); 957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label.textContent = this.displayStringFunction_(title); 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button.appendChild(label); 959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch button.label = this.displayStringFunction_(title); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button.addEventListener('click', handler, false); 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.add(button); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add a range control (scalar value picker). 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} name An option name. 968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @param {string} title An option title. 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} min Min value of the option. 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} value Default value of the option. 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} max Max value of the options. 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} scale A number to multiply by when setting 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * min/value/max in DOM. 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {boolean=} opt_showNumeric True if numeric value should be displayed. 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {HTMLElement} Range element. 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.addRange = function( 978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch name, title, min, value, max, scale, opt_showNumeric) { 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale = scale || 1; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var range = this.create_('input'); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.className = 'range'; 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.type = 'range'; 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.name = name; 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.min = Math.ceil(min * scale); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.max = Math.floor(max * scale); 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var numeric = this.create_('div'); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) numeric.className = 'numeric'; 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function mirror() { 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) numeric.textContent = Math.round(range.getValue() * scale) / scale; 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.setValue = function(newValue) { 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.value = Math.round(newValue * scale); 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mirror(); 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.getValue = function() { 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Number(range.value) / scale; 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.reset = function() { 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.setValue(value); 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.addEventListener('change', 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function() { 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mirror(); 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.updateCallback_(self.getOptions()); 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range.setValue(value); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var label = this.create_('div'); 1020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch label.textContent = this.displayStringFunction_(title); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label.className = 'label ' + name; 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.add(label); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.add(range); 10245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 10255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (opt_showNumeric) 10265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) this.add(numeric); 10275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 10285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Swallow the left and right keys, so they are not handled by other 10295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // listeners. 10305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) range.addEventListener('keydown', function(e) { 10315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (e.keyIdentifier === 'Left' || e.keyIdentifier === 'Right') 10325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) e.stopPropagation(); 10335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return range; 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {Object} options A map of options. 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.getOptions = function() { 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var values = {}; 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var child = this.wrapper_.firstChild; child; child = child.nextSibling) { 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child.name) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values[child.name] = child.getValue(); 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return values; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reset the toolbar. 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.reset = function() { 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var child = this.wrapper_.firstChild; child; child = child.nextSibling) { 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child.reset) child.reset(); 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Show/hide the toolbar. 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} on True if show. 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Toolbar.prototype.show = function(on) { 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.wrapper_.firstChild) 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Do not show empty toolbar; 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_.hidden = !on; 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** A prompt panel for the editor. 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLElement} container Container element. 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} displayStringFunction A formatting function. 10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @constructor 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Prompt = function(container, displayStringFunction) { 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_ = container; 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.displayStringFunction_ = displayStringFunction; 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reset the prompt. 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Prompt.prototype.reset = function() { 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cancelTimer(); 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.wrapper_) { 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.removeChild(this.wrapper_); 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_ = null; 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_ = null; 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Cancel the delayed action. 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Prompt.prototype.cancelTimer = function() { 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.timer_) { 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearTimeout(this.timer_); 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timer_ = null; 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schedule the delayed action. 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} callback Callback. 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} timeout Timeout. 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Prompt.prototype.setTimer = function(callback, timeout) { 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cancelTimer(); 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = this; 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timer_ = setTimeout(function() { 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.timer_ = null; 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback(); 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, timeout); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Show the prompt. 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} text The prompt text. 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} timeout Timeout in ms. 1122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {Object} formatArgs varArgs for the formatting function. 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Prompt.prototype.show = function(text, timeout, formatArgs) { 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.showAt.apply(this, 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ['center'].concat(Array.prototype.slice.call(arguments))); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} pos The 'pos' attribute value. 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} text The prompt text. 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} timeout Timeout in ms. 11344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * @param {Object} formatArgs varArgs for the formatting function. 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Prompt.prototype.showAt = function(pos, text, timeout, formatArgs) { 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.reset(); 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!text) return; 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var document = this.container_.ownerDocument; 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_ = document.createElement('div'); 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_.className = 'prompt-wrapper'; 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_.setAttribute('pos', pos); 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.appendChild(this.wrapper_); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_ = document.createElement('div'); 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_.className = 'prompt'; 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an extra wrapper which opacity can be manipulated separately. 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var tool = document.createElement('div'); 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tool.className = 'dimmable'; 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.wrapper_.appendChild(tool); 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tool.appendChild(this.prompt_); 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var args = [text].concat(Array.prototype.slice.call(arguments, 3)); 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_.textContent = this.displayStringFunction_.apply(null, args); 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var close = document.createElement('div'); 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close.className = 'close'; 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close.addEventListener('click', this.hide.bind(this)); 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_.appendChild(close); 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout( 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_.setAttribute.bind(this.prompt_, 'state', 'fadein'), 0); 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timeout) 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setTimer(this.hide.bind(this), timeout); 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Hide the prompt. 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageEditor.Prompt.prototype.hide = function() { 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.prompt_) return; 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.prompt_.setAttribute('state', 'fadeout'); 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow some time for the animation to play out. 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setTimer(this.reset.bind(this), 500); 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1179