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

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

Issue 6881031: FileManager: Add thumbnail view. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 8 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/file_manager.js
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 03bc6c065b833340ae98ae18fba8097f88ebef3b..1e7fac2939fab224d1cd4bf3d4017f4228027d37 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -30,6 +30,8 @@ function FileManager(dialogDom, rootEntries, params) {
this.filesystem_ = rootEntries[0].filesystem;
this.params_ = params || {};
+ this.listType_ = null;
+
this.document_ = dialogDom.ownerDocument;
this.dialogType_ =
this.params_.type || FileManager.DialogType.FULL_PAGE;
@@ -52,7 +54,9 @@ function FileManager(dialogDom, rootEntries, params) {
chrome.fileBrowserPrivate.onDiskChanged.addListener(
this.onDiskChanged_.bind(this));
- this.table.querySelector('.list').focus();
+ // TODO(rginda) Add a focus() method to the various list classes to take care
+ // of this.
+ // this.currentList_.list_.focus();
}
FileManager.prototype = {
@@ -146,29 +150,40 @@ FileManager.prototype = {
* 'unknown'.
*/
function getIconType(entry) {
- if (entry.isDirectory)
- return 'folder';
-
- for (var name in iconTypes) {
- var value = iconTypes[name];
-
- if (value instanceof RegExp) {
- if (value.test(entry.name))
- return name;
- } else if (typeof value == 'function') {
- try {
- if (value(entry))
- return name;
- } catch (ex) {
- console.error('Caught exception while evaluating iconType: ' +
- name, ex);
+ if (entry.cachedIconType_)
+ return entry.cachedIconType_;
+
+ var rv = 'unknown';
+
+ if (entry.isDirectory) {
+ rv = 'folder';
+ } else {
+ for (var name in iconTypes) {
+ var value = iconTypes[name];
+
+ if (value instanceof RegExp) {
+ if (value.test(entry.name)) {
+ rv = name;
+ break;
+ }
+ } else if (typeof value == 'function') {
+ try {
+ if (value(entry)) {
+ rv = name;
+ break;
+ }
+ } catch (ex) {
+ console.error('Caught exception while evaluating iconType: ' +
+ name, ex);
+ }
+ } else {
+ console.log('Unexpected value in iconTypes[' + name + ']: ' + value);
}
- } else {
- console.log('Unexpected value in iconTypes[' + name + ']: ' + value);
}
}
- return 'unknown';
+ entry.cachedIconType_ = rv;
+ return rv;
}
/**
@@ -328,7 +343,7 @@ FileManager.prototype = {
* icon type is known.
*/
function cacheEntryIconType(entry, successCallback) {
- entry.cachedIconType_ = getIconType(entry);
+ getIconType(entry);
if (successCallback)
setTimeout(function() { successCallback(entry) }, 0);
}
@@ -351,6 +366,11 @@ FileManager.prototype = {
FULL_PAGE: 'full-page'
};
+ FileManager.ListType = {
+ DETAIL: 'detail',
+ THUMBNAIL: 'thumb'
+ };
+
/**
* Load translated strings.
*/
@@ -404,13 +424,80 @@ FileManager.prototype = {
// Populate the static localized strings.
i18nTemplate.process(this.document_, localStrings.templateData);
- // Set up the detail table.
- var dataModel = new cr.ui.table.TableDataModel([]);
- dataModel.sort('name');
- dataModel.addEventListener('sorted',
- this.onDataModelSorted_.bind(this));
- dataModel.prepareSort = this.prepareSort_.bind(this);
+ this.dataModel_ = new cr.ui.table.TableDataModel([]);
+ this.dataModel_.sort('name');
+ this.dataModel_.addEventListener('sorted',
+ this.onDataModelSorted_.bind(this));
+ this.dataModel_.prepareSort = this.prepareSort_.bind(this);
+
+ this.initTable_();
+ this.initGrid_();
+ this.setListType(FileManager.ListType.DETAIL);
+
+ this.onResize_();
+ this.dialogDom_.style.opacity = '1';
+ };
+
+
+ FileManager.prototype.setListType = function(type) {
+ console.log('set list: ' + type);
+
+ if (type && type == this.listType_) {
+ console.log('no change: ' + type);
+ return;
+ }
+
+ if (type == FileManager.ListType.DETAIL) {
+ this.table_.style.display = '';
+ this.grid_.style.display = 'none';
+ this.currentList_ = this.table_;
+ this.dialogDom_.querySelector('button.detail-view').disabled = true;
+ this.dialogDom_.querySelector('button.thumbnail-view').disabled = false;
+ } else if (type == FileManager.ListType.THUMBNAIL) {
+ this.grid_.style.display = '';
+ this.table_.style.display = 'none';
+ this.currentList_ = this.grid_;
+ this.dialogDom_.querySelector('button.thumbnail-view').disabled = true;
+ this.dialogDom_.querySelector('button.detail-view').disabled = false;
+ } else {
+ throw new Error('Unknown list type: ' + type);
+ }
+
+ this.listType_ = type;
+ this.onResize_();
+ this.currentList_.redraw();
+
+ console.log('type now: ' + this.listType_);
+ };
+
+ /**
+ * Initialize the file thumbnail grid.
+ */
+ FileManager.prototype.initGrid_ = function() {
+ this.grid_ = this.dialogDom_.querySelector('.thumbnail-grid');
+ cr.ui.Grid.decorate(this.grid_);
+ this.grid_.dataModel = this.dataModel_;
+
+ var self = this;
+ this.grid_.itemConstructor = function(entry) {
+ return self.renderThumbnail_(entry);
+ };
+
+ if (this.dialogType_ != FileManager.DialogType.SELECT_OPEN_MULTI_FILE) {
+ this.grid_.selectionModel = new cr.ui.ListSingleSelectionModel();
+ }
+
+ this.grid_.addEventListener(
+ 'dblclick', this.onDetailDoubleClick_.bind(this));
+ this.grid_.selectionModel.addEventListener(
+ 'change', this.onDetailSelectionChanged_.bind(this));
+ };
+
+ /**
+ * Initialize the file list table.
+ */
+ FileManager.prototype.initTable_ = function() {
var columns = [
new cr.ui.table.TableColumn('cachedIconType_', '', 5.4),
new cr.ui.table.TableColumn('name', str('NAME_COLUMN_LABEL'), 64),
@@ -425,32 +512,42 @@ FileManager.prototype = {
columns[2].renderFunction = this.renderSize_.bind(this);
columns[3].renderFunction = this.renderDate_.bind(this);
- this.table = this.dialogDom_.querySelector('.detail-table');
- cr.ui.Table.decorate(this.table);
+ this.table_ = this.dialogDom_.querySelector('.detail-table');
+ cr.ui.Table.decorate(this.table_);
- this.table.dataModel = dataModel;
- this.table.columnModel = new cr.ui.table.TableColumnModel(columns);
+ this.table_.dataModel = this.dataModel_;
+ this.table_.columnModel = new cr.ui.table.TableColumnModel(columns);
if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FILE ||
this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FOLDER ||
this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) {
- this.table.selectionModel = new cr.ui.table.TableSingleSelectionModel();
+ this.table_.selectionModel = new cr.ui.table.TableSingleSelectionModel();
}
- this.table.addEventListener(
+ this.table_.addEventListener(
'dblclick', this.onDetailDoubleClick_.bind(this));
- this.table.selectionModel.addEventListener(
+ this.table_.selectionModel.addEventListener(
'change', this.onDetailSelectionChanged_.bind(this));
-
- this.onResize_();
- this.dialogDom_.style.opacity = '1';
};
FileManager.prototype.onResize_ = function() {
- // TODO(rginda): Remove this hack when cr.ui.List supports resizing.
- this.table.list_.style.height =
- (this.table.clientHeight - this.table.header_.clientHeight) + 'px';
- this.table.redraw();
+ console.log('onResize');
+
+ this.table_.style.height = this.grid_.style.height =
+ this.grid_.parentNode.clientHeight + 'px';
+ this.table_.style.width = this.grid_.style.width =
+ this.grid_.parentNode.clientWidth + 'px';
+
+ this.table_.list_.style.width = this.table_.parentNode.clientWidth + 'px';
+ this.table_.list_.style.height = (this.table_.clientHeight - 1 -
+ this.table_.header_.clientHeight) + 'px';
+
+ if (this.listType_ == FileManager.ListType.THUMBNAIL) {
+ var self = this;
+ setTimeout(function () { self.grid_.columns = 0 }, 100);
+ } else {
+ this.currentList_.redraw();
+ }
};
/**
@@ -566,7 +663,7 @@ FileManager.prototype = {
}
}
- var dataModel = this.table.dataModel;
+ var dataModel = this.dataModel_;
var uncachedCount = dataModel.length;
for (var i = uncachedCount - 1; i >= 0 ; i--) {
@@ -584,6 +681,24 @@ FileManager.prototype = {
checkCount();
}
+ FileManager.prototype.renderThumbnail_ = function(entry) {
+ var li = this.document_.createElement('li');
+ li.className = 'thumbnail-item';
+
+ var img = this.document_.createElement('img');
+ this.setIconSrc(entry, img);
+ li.appendChild(img);
+
+ var div = this.document_.createElement('div');
+ div.textContent = entry.name;
+ li.appendChild(div);
+
+ cr.defineProperty(li, 'lead', cr.PropertyKind.BOOL_ATTR);
+ cr.defineProperty(li, 'selected', cr.PropertyKind.BOOL_ATTR);
+
+ return li;
+ }
+
/**
* Render the type column of the detail table.
*
@@ -687,7 +802,7 @@ FileManager.prototype = {
FileManager.prototype.summarizeSelection_ = function() {
var selection = this.selection = {
entries: [],
- uris: [],
+ urls: [],
leadEntry: null,
totalCount: 0,
fileCount: 0,
@@ -699,7 +814,7 @@ FileManager.prototype = {
this.previewSummary_.textContent = str('COMPUTING_SELECTION');
this.taskButtons_.innerHTML = '';
- var selectedIndexes = this.table.selectionModel.selectedIndexes;
+ var selectedIndexes = this.currentList_.selectionModel.selectedIndexes;
if (!selectedIndexes.length) {
cr.dispatchSimpleEvent(this, 'selection-summarized');
return;
@@ -710,10 +825,11 @@ FileManager.prototype = {
var pendingFiles = [];
for (var i = 0; i < selectedIndexes.length; i++) {
- var entry = this.table.dataModel.item(selectedIndexes[i]);
+ var entry = this.dataModel_.item(selectedIndexes[i]);
selection.entries.push(entry);
- selection.uris.push(entry.toURI());
+
+ selection.urls.push(entry.toURL());
if (selection.iconType == null) {
selection.iconType = getIconType(entry);
@@ -743,9 +859,9 @@ FileManager.prototype = {
}
}
- var leadIndex = this.table.selectionModel.leadIndex;
+ var leadIndex = this.currentList_.selectionModel.leadIndex;
if (leadIndex > -1) {
- selection.leadEntry = this.table.dataModel.item(leadIndex);
+ selection.leadEntry = this.dataModel_.item(leadIndex);
} else {
selection.leadEntry = selection.entries[0];
}
@@ -768,7 +884,7 @@ FileManager.prototype = {
};
if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) {
- chrome.fileBrowserPrivate.getFileTasks(selection.uris,
+ chrome.fileBrowserPrivate.getFileTasks(selection.urls,
this.onTasksFound_.bind(this));
}
@@ -796,7 +912,7 @@ FileManager.prototype = {
FileManager.prototype.onTaskButtonClicked_ = function(event) {
chrome.fileBrowserPrivate.executeTask(event.srcElement.task.taskId,
- this.selection.uris);
+ this.selection.urls);
}
/**
@@ -867,30 +983,29 @@ FileManager.prototype = {
this.previewFilename_.textContent = previewName;
- var entry = this.selection.leadEntry;
+ var iconType = getIconType(this.selection.leadEntry);
+ if (iconType == 'image') {
+ this.previewImage_.classList.add('transparent-background');
+ if (fileManager.selection.totalCount > 1)
+ this.previewImage_.classList.add('multiple-selected');
+ }
+
+ this.setIconSrc(this.selection.leadEntry, this.previewImage_);
+
+ };
+
+ FileManager.prototype.setIconSrc = function(entry, img, callback) {
var iconType = getIconType(entry);
if (iconType != 'image') {
// Not an image, display a canned clip-art graphic.
- this.previewImage_.src = previewArt[iconType];
+ img.src = previewArt[iconType];
} else {
// File is an image, fetch the thumbnail.
- var fileManager = this;
-
- batchAsyncCall(entry, 'file', function(file) {
- var reader = new FileReader();
-
- reader.onerror = util.ferr('Error reading preview: ' + entry.fullPath);
- reader.onloadend = function(e) {
- fileManager.previewImage_.src = this.result;
- fileManager.previewImage_.classList.add('transparent-background');
- if (fileManager.selection.totalCount > 1)
- fileManager.previewImage_.classList.add('multiple-selected');
- };
-
- reader.readAsDataURL(file);
- });
+ img.src = entry.toURL();
}
+ if (callback)
+ callback();
};
/**
@@ -939,8 +1054,8 @@ FileManager.prototype = {
* We use this hook to make sure selected files stay visible after a sort.
*/
FileManager.prototype.onDataModelSorted_ = function() {
- var i = this.table.selectionModel.leadIndex;
- this.table.scrollIntoView(i);
+ var i = this.currentList_.selectionModel.leadIndex;
+ this.currentList_.scrollIntoView(i);
}
/**
@@ -1012,8 +1127,8 @@ FileManager.prototype = {
* @param {Event} event The click event.
*/
FileManager.prototype.onDetailDoubleClick_ = function(event) {
- var i = this.table.selectionModel.leadIndex;
- var entry = this.table.dataModel.item(i);
+ var i = this.currentList_.selectionModel.leadIndex;
+ var entry = this.dataModel_.item(i);
if (entry.isDirectory)
return this.changeDirectory(entry.fullPath);
@@ -1053,8 +1168,8 @@ FileManager.prototype = {
function onReadSome(entries) {
if (entries.length == 0) {
- if (self.table.dataModel.sortStatus.field != 'name')
- self.table.dataModel.updateIndex(0);
+ if (self.dataModel_.sortStatus.field != 'name')
+ self.dataModel_.updateIndex(0);
if (opt_callback)
opt_callback();
@@ -1073,14 +1188,14 @@ FileManager.prototype = {
});
spliceArgs.unshift(0, 0); // index, deleteCount
- self.table.dataModel.splice.apply(self.table.dataModel, spliceArgs);
+ self.dataModel_.splice.apply(self.dataModel_, spliceArgs);
// Keep reading until entries.length is 0.
reader.readEntries(onReadSome);
};
// Clear the table first.
- this.table.dataModel.splice(0, this.table.dataModel.length);
+ this.dataModel_.splice(0, this.dataModel_.length);
this.updateBreadcrumbs_();
@@ -1096,8 +1211,8 @@ FileManager.prototype = {
// harness) can't be enumerated yet.
var spliceArgs = [].slice.call(this.rootEntries_);
spliceArgs.unshift(0, 0); // index, deleteCount
- self.table.dataModel.splice.apply(self.table.dataModel, spliceArgs);
- self.table.dataModel.updateIndex(0);
+ self.dataModel_.splice.apply(self.dataModel_, spliceArgs);
+ self.dataModel_.updateIndex(0);
if (opt_callback)
opt_callback();
@@ -1145,11 +1260,11 @@ FileManager.prototype = {
function onSuccess(dirEntry) {
self.rescanDirectory_(function () {
- for (var i = 0; i < self.table.dataModel.length; i++) {
- if (self.table.dataModel.item(i).name == dirEntry.name) {
- self.table.selectionModel.selectedIndex = i;
- self.table.scrollIndexIntoView(i);
- self.table.focus();
+ for (var i = 0; i < self.dataModel_.length; i++) {
+ if (self.dataModel_.item(i).name == dirEntry.name) {
+ self.currentList_.selectionModel.selectedIndex = i;
+ self.currentList_.scrollIndexIntoView(i);
+ self.currentList_.focus();
return;
}
};
@@ -1236,7 +1351,7 @@ FileManager.prototype = {
}
var ary = [];
- var selectedIndexes = this.table.selectionModel.selectedIndexes;
+ var selectedIndexes = this.currentList_.selectionModel.selectedIndexes;
// All other dialog types require at least one selected list item.
// The logic to control whether or not the ok button is enabled should
@@ -1245,7 +1360,7 @@ FileManager.prototype = {
throw new Error('Nothing selected!');
for (var i = 0; i < selectedIndexes.length; i++) {
- var entry = this.table.dataModel.item(selectedIndexes[i]);
+ var entry = this.dataModel_.item(selectedIndexes[i]);
if (!entry) {
console.log('Error locating selected file at index: ' + i);
continue;

Powered by Google App Engine
This is Rietveld 408576698