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

Unified Diff: chrome/browser/resources/file_manager/js/photo/gallery.js

Issue 10829421: First cut of the updated Photo Editor UI (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/file_manager/js/photo/gallery.js
diff --git a/chrome/browser/resources/file_manager/js/photo/gallery.js b/chrome/browser/resources/file_manager/js/photo/gallery.js
index 046665e6fc9d2e44170400ba30920ea8c5330fad..9c087048489cf37ad3572949e6e98d43a6454dbc 100644
--- a/chrome/browser/resources/file_manager/js/photo/gallery.js
+++ b/chrome/browser/resources/file_manager/js/photo/gallery.js
@@ -28,6 +28,9 @@ function Gallery(context) {
this.context_ = context;
this.metadataCache_ = context.metadataCache;
+ this.dataModel_ = new cr.ui.ArrayDataModel([]);
+ this.selectionModel_ = new cr.ui.ListSelectionModel();
+
var strf = context.displayStringFunction;
this.displayStringFunction_ = function(id, formatArgs) {
var args = Array.prototype.slice.call(arguments);
@@ -45,10 +48,11 @@ function Gallery(context) {
* @param {Object} context Gallery context.
* @param {Array.<string>} urls Array of image urls.
* @param {string} selectedUrl Selected url.
+ * @param {boolean} opt_grid True if open in the grid view.
*/
-Gallery.open = function(context, urls, selectedUrl) {
+Gallery.open = function(context, urls, selectedUrl, opt_grid) {
Gallery.instance = new Gallery(context);
- Gallery.instance.load(urls, selectedUrl);
+ Gallery.instance.load(urls, selectedUrl, opt_grid);
};
/**
@@ -90,7 +94,7 @@ Gallery.openStandalone = function(path) {
}
function onNameChange(name) {
- window.top.document.title = name;
+ window.top.document.title = name || currentDir.name;
var newPath = currentDir.fullPath + '/' + name;
var location = document.location.origin + document.location.pathname +
@@ -104,6 +108,7 @@ Gallery.openStandalone = function(path) {
}
function open() {
+ urls.sort();
Gallery.getFileBrowserPrivate().getStrings(function(strings) {
loadTimeData.data = strings;
var context = {
@@ -114,7 +119,7 @@ Gallery.openStandalone = function(path) {
onClose: onClose,
displayStringFunction: strf
};
- Gallery.open(context, urls, selectedUrl || urls[0]);
+ Gallery.open(context, urls, selectedUrl, !selectedUrl);
});
}
};
@@ -194,19 +199,41 @@ Gallery.prototype.initDom_ = function() {
this.prompt_ = new ImageEditor.Prompt(
this.container_, this.displayStringFunction_);
- this.slideMode_ = new SlideMode(this.container_, this.toolbar_, this.prompt_,
+ this.modeButton_ = util.createChild(this.toolbar_, 'button mode');
+ this.modeButton_.addEventListener('click', this.toggleMode_.bind(this, null));
+
+ this.gridMode_ = new GridMode(this.container_, content,
+ this.dataModel_, this.selectionModel_, this.metadataCache_,
+ this.toggleMode_.bind(this, null));
+
+ this.slideMode_ = new SlideMode(this.container_, content,
+ this.toolbar_, this.prompt_,
+ this.dataModel_, this.selectionModel_,
this.context_, this.displayStringFunction_);
- this.slideMode_.addEventListener('edit', this.onEdit_.bind(this));
- this.slideMode_.addEventListener('selection', this.onSelection_.bind(this));
- this.shareMode_ = new ShareMode(
- this.slideMode_.editor_, this.container_, this.toolbar_,
- this.onShare_.bind(this), this.executeWhenReady.bind(this),
- this.displayStringFunction_);
+ var deleteButton = this.document_.createElement('div');
+ deleteButton.className = 'button delete';
+ deleteButton.title = this.displayStringFunction_('delete');
+ deleteButton.addEventListener('click', this.onDelete_.bind(this));
+ this.toolbar_.insertBefore(
+ deleteButton, this.toolbar_.querySelector('.edit'));
+
+ this.shareButton_ = util.createChild(this.toolbar_, 'button share');
+ this.shareButton_.title = this.displayStringFunction_('share');
+ this.shareButton_.addEventListener('click', this.toggleShare_.bind(this));
+
+ this.shareMenu_ = util.createChild(this.container_, 'share-menu');
+ this.shareMenu_.hidden = true;
+ util.createChild(this.shareMenu_, 'bubble-point');
Gallery.getFileBrowserPrivate().isFullscreen(function(fullscreen) {
this.originalFullscreen_ = fullscreen;
}.bind(this));
+
+ this.slideMode_.addEventListener('button', this.onModeButton_.bind(this));
+ this.slideMode_.addEventListener('content', this.onContentChange_.bind(this));
+ this.slideMode_.addEventListener('rename', this.onSelection_.bind(this));
+ this.selectionModel_.addEventListener('change', this.onSelection_.bind(this));
};
/**
@@ -214,19 +241,27 @@ Gallery.prototype.initDom_ = function() {
*
* @param {Array.<string>} urls Array of urls.
* @param {string} selectedUrl Selected url.
+ * @param {boolean} opt_grid True if open in the grid view.
*/
-Gallery.prototype.load = function(urls, selectedUrl) {
- this.items_ = [];
+Gallery.prototype.load = function(urls, selectedUrl, opt_grid) {
+ var items = [];
for (var index = 0; index < urls.length; ++index) {
- this.items_.push(new Gallery.Item(urls[index]));
+ items.push(new Gallery.Item(urls[index]));
}
+ this.dataModel_.push.apply(this.dataModel_, items);
var selectedIndex = urls.indexOf(selectedUrl);
- this.slideMode_.load(this.items_, selectedIndex, function() {
- // Flash the toolbar briefly to show it is there.
- this.inactivityWatcher_.startActivity();
- this.inactivityWatcher_.stopActivity(Gallery.FIRST_FADE_TIMEOUT);
- }.bind(this));
+ if (selectedIndex >= 0)
+ this.selectionModel_.setIndexSelected(selectedIndex, true);
+ else
+ this.onSelection_();
+
+ this.currentMode_ = opt_grid ? this.gridMode_ : this.slideMode_;
+ this.currentMode_.enter(function() {
+ // Flash the toolbar briefly to show it is there.
+ this.inactivityWatcher_.startActivity();
+ this.inactivityWatcher_.stopActivity(Gallery.FIRST_FADE_TIMEOUT);
+ }.bind(this));
};
/**
@@ -255,8 +290,10 @@ Gallery.prototype.onClose_ = function() {
* @param {function} callback Function to execute.
*/
Gallery.prototype.executeWhenReady = function(callback) {
- //TODO(kaznacheev): Execute directly when in grid mode.
- this.slideMode_.editor_.executeWhenReady(callback);
+ if (this.currentMode_ == this.slideMode_)
+ this.slideMode_.editor_.executeWhenReady(callback);
+ else
+ callback();
};
/**
@@ -277,7 +314,8 @@ Gallery.toggleFullscreen = function() {
* @return {boolean} True if some tool is currently active.
*/
Gallery.prototype.hasActiveTool = function() {
- return this.slideMode_.isEditing() || this.isSharing_() || this.isRenaming_();
+ return this.currentMode_.hasActiveTool() ||
+ this.isSharing_() || this.isRenaming_();
};
/**
@@ -292,22 +330,52 @@ Gallery.prototype.checkActivity_ = function() {
};
/**
-* Edit toggle event handler.
+* External button event handler.
* @private
*/
-Gallery.prototype.onEdit_ = function() {
- // The user has just clicked on the Edit button. Dismiss the Share menu.
- if (this.isSharing_())
- this.onShare_();
+Gallery.prototype.onModeButton_ = function() {
+ this.closeShareMenu_();
this.checkActivity_();
};
/**
+ * Mode toggle event handler.
+ * @param {function} opt_callback Callback.
+ * @private
+ */
+Gallery.prototype.toggleMode_ = function(opt_callback) {
+ this.currentMode_.leave(function() {
+ if (this.currentMode_ == this.gridMode_) {
+ this.currentMode_ = this.slideMode_;
+ this.modeButton_.title = this.displayStringFunction_('mosaic');
+ } else {
+ this.currentMode_ = this.gridMode_;
+ this.modeButton_.title = this.displayStringFunction_('slide');
+ }
+ this.currentMode_.enter(opt_callback);
+ this.updateFilename_();
+ }.bind(this));
+};
+
+/**
+ * Delete event handler.
+ * @private
+ */
+Gallery.prototype.onDelete_ = function() {
+ var indexes = this.selectionModel_.selectedIndexes;
+ for (var i = 0; i != indexes.length; i++)
+ this.dataModel_.splice(indexes[i], 1);
+
+ // TODO: delete actual files.
+};
+
+/**
* @return {Array.<Gallery.Item>} Current selection.
*/
Gallery.prototype.getSelectedItems = function() {
- // TODO(kaznacheev) support multiple selection grid/mosaic mode.
- return [this.slideMode_.getSelectedItem()];
+ return this.selectionModel_.selectedIndexes.map(function(index) {
+ return this.dataModel_.item(index);
dgozman 2012/08/27 13:23:42 You can use this.dataModel_.item.bind(this.dataMo
Vladislav Kaznacheev 2012/08/27 14:49:08 Done.
+ }.bind(this));
};
/**
@@ -326,8 +394,16 @@ Gallery.prototype.getSingleSelectedItem = function() {
*/
Gallery.prototype.onSelection_ = function() {
this.updateFilename_();
- this.shareMode_.updateMenu(
- this.getSelectedItems().map(function(item) { return item.getUrl() }));
+ this.updateShareMenu_();
+};
+
+/**
+* Content change event handler.
+* @private
+*/
+Gallery.prototype.onContentChange_ = function() {
+ this.updateFilename_();
+ this.gridMode_.updateThumbnail(this.getSingleSelectedItem());
};
/**
@@ -336,7 +412,9 @@ Gallery.prototype.onSelection_ = function() {
* @private
*/
Gallery.prototype.onKeyDown_ = function(event) {
- if (this.slideMode_.onKeyDown(event))
+ this.closeShareMenu_();
+
+ if (this.currentMode_.onKeyDown(event))
return;
switch (util.getKeyModifiers(event) + event.keyIdentifier) {
@@ -347,7 +425,7 @@ Gallery.prototype.onKeyDown_ = function(event) {
case 'U+001B': // Escape
if (this.isSharing_())
dgozman 2012/08/27 13:23:42 You have just closed share menu at line 415. Why?
Vladislav Kaznacheev 2012/08/27 14:49:08 Good catch! Rewrote. On 2012/08/27 13:23:42, dgoz
- this.onShare_();
+ this.toggleShare_();
else
this.onClose_();
break;
@@ -362,11 +440,21 @@ Gallery.prototype.onKeyDown_ = function(event) {
* @private
*/
Gallery.prototype.updateFilename_ = function() {
- var fullName = this.getSingleSelectedItem().getFileName();
+ var displayName = '';
+ var fullName = '';
+
+ var selectedItems = this.getSelectedItems();
+ if (selectedItems.length == 1) {
+ fullName = selectedItems[0].getFileName();
+ displayName = ImageUtil.getFileNameFromFullName(fullName);
+ } else if (selectedItems.length > 1) {
+ displayName =
+ this.displayStringFunction_('ITEMS_SELECTED', selectedItems.length);
+ }
- this.context_.onNameChange(fullName);
+ this.context_.onNameChange(
+ this.currentMode_ == this.slideMode_ ? fullName : '');
- var displayName = ImageUtil.getFileNameFromFullName(fullName);
this.filenameEdit_.value = displayName;
this.filenameText_.textContent = displayName;
};
@@ -380,6 +468,10 @@ Gallery.prototype.onFilenameClick_ = function() {
if (this.context_.readonlyDirName)
return;
+ // We can only rename a single file.
+ if (this.getSelectedItems().length != 1)
+ return;
+
ImageUtil.setAttribute(this.filenameSpacer_, 'renaming', true);
setTimeout(this.filenameEdit_.select.bind(this.filenameEdit_), 0);
this.inactivityWatcher_.startActivity();
@@ -407,6 +499,7 @@ Gallery.prototype.onFilenameEditBlur_ = function() {
var onSuccess = function() {
this.slideMode_.updateSelectedUrl_(oldUrl, item.getUrl());
+ this.updateFilename_();
}.bind(this);
if (this.filenameEdit_.value) {
@@ -449,129 +542,210 @@ Gallery.prototype.isRenaming_ = function() {
* @private
*/
Gallery.prototype.onContentClick_ = function() {
+ this.closeShareMenu_();
this.filenameEdit_.blur();
};
// Share button support.
/**
- * @return {boolean} True if the Share mode is active.
+ * @return {boolean} True if the Share menu is active.
* @private
*/
Gallery.prototype.isSharing_ = function() {
- return this.shareMode_.isActive();
+ return !this.shareMenu_.hidden;
+};
+
+/**
+ * Close Share menu if it is open.
+ * @private
+ */
+Gallery.prototype.closeShareMenu_ = function() {
+ if (this.isSharing_())
+ this.toggleShare_();
};
/**
* Share button handler.
- * @param {Event} event Event.
* @private
*/
-Gallery.prototype.onShare_ = function(event) {
- this.shareMode_.toggle(event);
+Gallery.prototype.toggleShare_ = function() {
+ if (!this.shareButton_.hasAttribute('disabled'))
+ this.shareMenu_.hidden = !this.shareMenu_.hidden;
this.checkActivity_();
};
/**
- *
- * @param {ImageEditor} editor Editor.
- * @param {Element} container Container element.
- * @param {Element} toolbar Toolbar element.
- * @param {function} onClick Click handler.
- * @param {function(function())} actionCallback Function to execute the action.
- * @param {function(string):string} displayStringFunction String formatting
- * function.
- * @constructor
+ * Update available actions list based on the currently selected urls.
+ * @private.
*/
-function ShareMode(editor, container, toolbar,
- onClick, actionCallback, displayStringFunction) {
- ImageEditor.Mode.call(this, 'share');
+Gallery.prototype.updateShareMenu_ = function() {
+ var urls =
+ this.getSelectedItems().map(function(item) { return item.getUrl() });
+
+ var internalId = util.getExtensionId();
+ function isShareAction(task) {
+ var task_parts = task.taskId.split('|');
+ return task_parts[0] != internalId;
+ }
- this.message_ = null;
+ var api = Gallery.getFileBrowserPrivate();
+ api.getFileTasks(urls, function(tasks) {
+ var wasHidden = this.shareMenu_.hidden;
+ this.shareMenu_.hidden = true;
+ var items = this.shareMenu_.querySelectorAll('.item');
+ for (var i = 0; i != items.length; i++) {
+ items[i].parentNode.removeChild(items[i]);
+ }
- var button = util.createChild(toolbar, 'button share');
- button.textContent = displayStringFunction('share');
- button.addEventListener('click', onClick);
- this.bind(editor, button);
+ for (var t = 0; t != tasks.length; t++) {
+ var task = tasks[t];
+ if (!isShareAction(task)) continue;
- this.actionCallback_ = actionCallback;
+ var item = util.createChild(this.shareMenu_, 'item');
+ item.textContent = task.title;
+ item.style.backgroundImage = 'url(' + task.iconUrl + ')';
+ item.addEventListener('click', function(taskId) {
+ this.toggleShare_(); // Hide the menu.
+ this.executeWhenReady(api.executeTask.bind(api, taskId, urls));
+ }.bind(this, task.taskId));
+ }
- this.menu_ = util.createChild(container, 'share-menu');
- this.menu_.hidden = true;
+ var empty = this.shareMenu_.querySelector('.item') == null;
+ ImageUtil.setAttribute(this.shareButton_, 'disabled', empty);
+ this.shareMenu_.hidden = wasHidden || empty;
+ }.bind(this));
+};
- util.createChild(this.menu_, 'bubble-point');
+/**
+ * @param {Element} container Main container.
+ * @param {Element} content Content container.
+ * @param {cr.ui.ArrayDataModel} dataModel Data model.
+ * @param {cr.ui.ListSelectionModel} selectionModel Selection model.
+ * @param {MetadataCache} metadataCache Metadata cache.
+ * @param {function} openSelectedItem Function to open the selected item in the
+ * slide mode.
+ * @constructor
+ */
+function GridMode(container, content, dataModel, selectionModel,
+ metadataCache, openSelectedItem) {
+ this.container_ = container;
+ this.metadataCache_ = metadataCache;
+ this.grid_ = util.createChild(content, 'thumbnail-grid', 'grid');
+ cr.ui.Grid.decorate(this.grid_);
+
+ this.grid_.dataModel = dataModel;
+ this.grid_.selectionModel = selectionModel;
+ this.grid_.itemConstructor =
+ GridMode.Item.bind(null, container.ownerDocument, metadataCache);
+
+ this.container_.ownerDocument.defaultView.addEventListener(
+ 'resize', this.redraw_.bind(this));
+
+ this.openSelectedItem_ = openSelectedItem;
+ this.grid_.addEventListener('dblclick', this.openSelectedItem_);
}
-ShareMode.prototype = { __proto__: ImageEditor.Mode.prototype };
+/**
+ * Enter the mode.
+ * @param {function} opt_callback Callback.
+ */
+GridMode.prototype.enter = function(opt_callback) {
+ this.container_.setAttribute('mode', 'grid');
+ this.redraw_();
+ if (opt_callback) opt_callback();
+};
/**
- * Shows share mode UI.
+ * Leave the mode.
+ * @param {function} opt_callback Callback.
*/
-ShareMode.prototype.setUp = function() {
- ImageEditor.Mode.prototype.setUp.apply(this, arguments);
- this.menu_.hidden = false;
- ImageUtil.setAttribute(this.button_, 'pressed', false);
+GridMode.prototype.leave = function(opt_callback) {
+ if (opt_callback) opt_callback();
};
/**
- * Hides share mode UI.
+ * Redraw the grid.
+ * @private
*/
-ShareMode.prototype.cleanUpUI = function() {
- ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments);
- this.menu_.hidden = true;
+GridMode.prototype.redraw_ = function() {
+ this.grid_.startBatchUpdates();
+ setTimeout(function() {
+ this.grid_.columns = 0;
+ this.grid_.redraw();
+ this.grid_.endBatchUpdates();
+ }.bind(this), 0);
};
/**
- * @return {boolean} True if the menu is currently open.
+ * @param {Gallery.Item} item The updated item.
*/
-ShareMode.prototype.isActive = function() {
- return !this.menu_.hidden;
+GridMode.prototype.updateThumbnail = function(item) {
+ var listItems = this.grid_.querySelectorAll('li');
+ for (var i = 0; i != listItems.length; i++) {
+ GridMode.Item.updateThumbnail(listItems[i], this.metadataCache_, item);
+ }
};
/**
- * Show/hide the menu.
* @param {Event} event Event.
+ * @return {boolean} True if handled.
*/
-ShareMode.prototype.toggle = function(event) {
- this.editor_.enterMode(this, event);
+GridMode.prototype.onKeyDown = function(event) {
+ switch (util.getKeyModifiers(event) + event.keyIdentifier) {
+ case 'Enter':
+ this.openSelectedItem_();
dgozman 2012/08/27 13:23:42 Where is this function defined?
Vladislav Kaznacheev 2012/08/27 14:49:08 line 645 On 2012/08/27 13:23:42, dgozman wrote:
+ return true;
+ }
+
+ return false;
};
/**
- * Update available actions list based on the currently selected urls.
- *
- * @param {Array.<string>} urls Array of urls.
+ * @return {boolean} Always true (no tools fading in the Grid mode).
*/
-ShareMode.prototype.updateMenu = function(urls) {
- var internalId = util.getExtensionId();
- function isShareAction(task) {
- var task_parts = task.taskId.split('|');
- return task_parts[0] != internalId;
- }
+GridMode.prototype.hasActiveTool = function() {
+ return true;
+};
- var items = this.menu_.querySelectorAll('.item');
- for (var i = 0; i != items.length; i++) {
- items[i].parentNode.removeChild(items[i]);
- }
+/**
+ * @param {Document} document Document.
+ * @param {MetadataCache} metadataCache Metadata cache.
+ * @param {Gallery.Item} item Item.
+ * @return {Element} Newly created grid item.
+ * @constructor
+ */
+GridMode.Item = function(document, metadataCache, item) {
+ var li = document.createElement('li');
+ li.__proto__ = GridMode.Item.prototype;
+ li.className = 'thumbnail-item';
+ li.item = item;
- var api = Gallery.getFileBrowserPrivate();
- api.getFileTasks(urls, function(tasks) {
- for (var i = 0; i != tasks.length; i++) {
- var task = tasks[i];
- if (!isShareAction(task)) continue;
+ var box = util.createChild(li, 'img-container');
- var item = document.createElement('div');
- item.className = 'item';
- this.menu_.appendChild(item);
+ GridMode.Item.updateThumbnail(li, metadataCache, item);
+ return li;
+};
- item.textContent = task.title;
- item.style.backgroundImage = 'url(' + task.iconUrl + ')';
- item.addEventListener('click', this.actionCallback_.bind(null,
- api.executeTask.bind(api, task.taskId, urls)));
- }
+/**
+ * @param {Element} li Grid item.
+ * @param {MetadataCache} metadataCache Metadata cache.
+ * @param {Gallery.Item} item Gallery item.
+ */
+GridMode.Item.updateThumbnail = function(li, metadataCache, item) {
+ if (item != li.item)
+ return;
- if (this.menu_.firstChild)
- this.button_.removeAttribute('disabled');
- else
- this.button_.setAttribute('disabled', 'true');
- }.bind(this));
+ var box = li.querySelector('.img-container');
+ var url = item.getUrl();
+ metadataCache.get(url, Gallery.METADATA_TYPE,
+ function(metadata) {
+ new ThumbnailLoader(url, metadata).load(box, false /* fit */);
+ });
+};
+
+GridMode.Item.prototype = {
+ __proto__: cr.ui.ListItem.prototype,
+ get label() {},
+ set label(value) {}
};

Powered by Google App Engine
This is Rietveld 408576698