Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: chrome/browser/resources/file_manager/js/image_editor/commands.js

Issue 10399047: [Photo Editor] Save edited images immediately. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * Command queue is the only way to modify images. 6 * Command queue is the only way to modify images.
7 * Supports undo/redo. 7 * Supports undo/redo.
8 * Command execution is asynchronous (callback-based). 8 * Command execution is asynchronous (callback-based).
9 *
10 * @param {Document} document Document to create canvases in.
11 * @param {HTMLCanvasElement} canvas The canvas with the original image.
12 * @param {function(callback)} saveFunction Function to save the image.
9 */ 13 */
10 function CommandQueue(document, canvas) { 14 function CommandQueue(document, canvas, saveFunction) {
11 this.document_ = document; 15 this.document_ = document;
12 this.undo_ = []; 16 this.undo_ = [];
13 this.redo_ = []; 17 this.redo_ = [];
14 this.subscribers_ = []; 18 this.subscribers_ = [];
15 19
16 this.baselineImage_ = canvas; 20 this.baselineImage_ = canvas;
17 this.currentImage_ = canvas; 21 this.currentImage_ = canvas;
18 this.previousImage_ = null; 22 this.previousImage_ = null;
19 23
24 this.saveFunction_ = saveFunction;
25
20 this.busy_ = false; 26 this.busy_ = false;
21 27
22 this.UIContext_ = {}; 28 this.UIContext_ = {};
23 } 29 }
24 30
25 /** 31 /**
26 * Attach the UI elements to the command queue. 32 * Attach the UI elements to the command queue.
27 * Once the UI is attached the results of image manipulations are displayed. 33 * Once the UI is attached the results of image manipulations are displayed.
28 * 34 *
29 * @param {ImageView} imageView The ImageView object to display the results 35 * @param {ImageView} imageView The ImageView object to display the results
30 * @param {ImageEditor.Prompt} prompt 36 * @param {ImageEditor.Prompt} prompt
31 * @param {function(boolean)} lock Function to enable/disable buttons etc. 37 * @param {function(boolean)} lock Function to enable/disable buttons etc.
32 */ 38 */
33 CommandQueue.prototype.attachUI = function(imageView, prompt, lock) { 39 CommandQueue.prototype.attachUI = function(imageView, prompt, lock) {
34 this.UIContext_ = { 40 this.UIContext_ = {
35 imageView: imageView, 41 imageView: imageView,
36 prompt: prompt, 42 prompt: prompt,
37 lock: lock 43 lock: lock
38 }; 44 };
39 }; 45 };
40 46
41 /** 47 /**
42 * Detach the UI. Further image modifications will not be displayed. 48 * Execute the action when the queue is not busy.
49 * @param {function} callback Callback.
43 */ 50 */
44 CommandQueue.prototype.detachUI = function() { 51 CommandQueue.prototype.executeWhenReady = function(callback) {
45 // The current this.UIContext_ object might be used by the command currently 52 if (this.isBusy())
46 // being executed. Null out its fields so that the command continues silently.
47 this.UIContext_.imageView = null;
48 this.UIContext_.prompt = null;
49 this.UIContext_.lock = null;
50
51 // Now replace the object to guarantee that we do not interfere with the
52 // current command.
53 this.UIContext_ = {};
54 };
55
56 /**
57 * Asynchronous getter. Does not return the image while the queue is busy.
58 */
59 CommandQueue.prototype.requestCurrentImage = function(callback) {
60 if (this.isBusy()) {
61 this.subscribers_.push(callback); 53 this.subscribers_.push(callback);
62 } else { 54 else
63 var self = this; 55 setTimeout(callback, 0);
64 setTimeout(function() { callback(self.currentImage_) }, 0);
65 }
66 }; 56 };
67 57
68 CommandQueue.prototype.isBusy = function() { return this.busy_ }; 58 CommandQueue.prototype.isBusy = function() { return this.busy_ };
69 59
70 CommandQueue.prototype.setBusy_ = function(on) { 60 CommandQueue.prototype.setBusy_ = function(on) {
71 if (this.busy_ == on) 61 if (this.busy_ == on)
72 throw new Error('Inconsistent CommandQueue lock state'); 62 throw new Error('Inconsistent CommandQueue lock state');
73 63
74 this.busy_ = on; 64 this.busy_ = on;
75 65
76 if (!on) { 66 if (!on) {
77 // Notify the subscribers that requested the image while the queue was busy. 67 // Execute the actions requested while the queue was busy.
78 while (this.subscribers_.length) { 68 while (this.subscribers_.length)
79 this.subscribers_.pop()(this.currentImage_); 69 this.subscribers_.shift()();
80 }
81 } 70 }
82 71
83 if (this.UIContext_.lock) 72 if (this.UIContext_.lock)
84 this.UIContext_.lock(on); 73 this.UIContext_.lock(on);
85 74
86 if (on) { 75 if (on)
87 ImageUtil.trace.resetTimer('command-busy'); 76 ImageUtil.trace.resetTimer('command-busy');
88 } else { 77 else
89 ImageUtil.trace.reportTimer('command-busy'); 78 ImageUtil.trace.reportTimer('command-busy');
90 } 79 };
80
81 CommandQueue.prototype.save_ = function() {
dgozman 2012/05/16 16:05:40 It's hard to understand the difference between |th
Vladislav Kaznacheev 2012/05/17 09:04:40 renamed to commit_ and added a JSDoc On 2012/05/1
82 setTimeout(
83 this.saveFunction_,
84 ImageView.ANIMATION_WAIT_INTERVAL,
85 this.setBusy_.bind(this, false));
dgozman 2012/05/16 16:05:40 Is this setBusy a parameter to saveFunction? Add a
Vladislav Kaznacheev 2012/05/17 09:04:40 Rewrote for clarity. And yes, this assumes isBusy=
91 }; 86 };
92 87
93 CommandQueue.prototype.doExecute_ = function(command, uiContext, callback) { 88 CommandQueue.prototype.doExecute_ = function(command, uiContext, callback) {
94 if (!this.currentImage_) 89 if (!this.currentImage_)
95 throw new Error('Cannot operate on null image'); 90 throw new Error('Cannot operate on null image');
96 91
97 // Remember one previous image so that the first undo is as fast as possible. 92 // Remember one previous image so that the first undo is as fast as possible.
98 this.previousImage_ = this.currentImage_; 93 this.previousImage_ = this.currentImage_;
99 var self = this; 94 var self = this;
100 command.execute( 95 command.execute(
(...skipping 13 matching lines...) Expand all
114 * @param {boolean} opt_keep_redo true if redo stack should not be cleared. 109 * @param {boolean} opt_keep_redo true if redo stack should not be cleared.
115 */ 110 */
116 CommandQueue.prototype.execute = function(command, opt_keep_redo) { 111 CommandQueue.prototype.execute = function(command, opt_keep_redo) {
117 this.setBusy_(true); 112 this.setBusy_(true);
118 113
119 if (!opt_keep_redo) 114 if (!opt_keep_redo)
120 this.redo_ = []; 115 this.redo_ = [];
121 116
122 this.undo_.push(command); 117 this.undo_.push(command);
123 118
124 this.doExecute_(command, this.UIContext_, this.setBusy_.bind(this, false)); 119 this.doExecute_(command, this.UIContext_, this.save_.bind(this));
125 }; 120 };
126 121
127 CommandQueue.prototype.canUndo = function() { 122 CommandQueue.prototype.canUndo = function() {
128 return this.undo_.length != 0; 123 return this.undo_.length != 0;
129 }; 124 };
130 125
131 CommandQueue.prototype.undo = function() { 126 CommandQueue.prototype.undo = function() {
132 if (!this.canUndo()) 127 if (!this.canUndo())
133 throw new Error('Cannot undo'); 128 throw new Error('Cannot undo');
134 129
135 this.setBusy_(true); 130 this.setBusy_(true);
136 131
137 var command = this.undo_.pop(); 132 var command = this.undo_.pop();
138 this.redo_.push(command); 133 this.redo_.push(command);
139 134
140 var self = this; 135 var self = this;
141 136
142 function complete() { 137 function complete() {
143 if (self.UIContext_.imageView) { 138 if (self.UIContext_.imageView) {
144 command.revertView(self.currentImage_, self.UIContext_.imageView); 139 command.revertView(self.currentImage_, self.UIContext_.imageView);
145 } 140 }
146 self.setBusy_(false); 141 self.save_();
147 } 142 }
148 143
149 if (this.previousImage_) { 144 if (this.previousImage_) {
150 // First undo after an execute call. 145 // First undo after an execute call.
151 this.currentImage_ = this.previousImage_; 146 this.currentImage_ = this.previousImage_;
152 this.previousImage_ = null; 147 this.previousImage_ = null;
153 complete(); 148 complete();
154 // TODO(kaznacheev) Consider recalculating previousImage_ right here 149 // TODO(kaznacheev) Consider recalculating previousImage_ right here
155 // by replaying the commands in the background. 150 // by replaying the commands in the background.
156 } else { 151 } else {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 328
334 function onProgressInvisible(updatedRow, rowCount) { 329 function onProgressInvisible(updatedRow, rowCount) {
335 if (updatedRow == rowCount) { 330 if (updatedRow == rowCount) {
336 callback(result); 331 callback(result);
337 } 332 }
338 } 333 }
339 334
340 filter.applyByStrips(result, srcCanvas, this.filter_, 335 filter.applyByStrips(result, srcCanvas, this.filter_,
341 uiContext.imageView ? onProgressVisible : onProgressInvisible); 336 uiContext.imageView ? onProgressVisible : onProgressInvisible);
342 }; 337 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698