summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordgozman@chromium.org <dgozman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-30 16:45:13 +0000
committerdgozman@chromium.org <dgozman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-30 16:45:13 +0000
commit0d4cd065a9b3e28de6ae1e332e1b5fe1d38d6cb6 (patch)
tree4d531a08192b846f52ae4ec21d94a85783eb77f1 /chrome
parentc37c498ddc13f35a7a199c4e03e6f1ec047f9c52 (diff)
downloadchromium_src-0d4cd065a9b3e28de6ae1e332e1b5fe1d38d6cb6.zip
chromium_src-0d4cd065a9b3e28de6ae1e332e1b5fe1d38d6cb6.tar.gz
chromium_src-0d4cd065a9b3e28de6ae1e332e1b5fe1d38d6cb6.tar.bz2
[filebrowser] Changed task buttons to single dropdown. Double-click and click-on-preview for default action.
BUG=chromium-os:23582,chromium-os:17507,chromium-os:25022 TEST=See bugs. Review URL: https://chromiumcodereview.appspot.com/9284019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119678 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_file_browser_private_api.cc3
-rw-r--r--chrome/browser/resources/file_manager/css/combobutton.css110
-rw-r--r--chrome/browser/resources/file_manager/css/file_manager.css35
-rw-r--r--chrome/browser/resources/file_manager/images/disclosure_arrow_dk_grey_down.pngbin0 -> 138 bytes
-rw-r--r--chrome/browser/resources/file_manager/js/combobutton.js142
-rw-r--r--chrome/browser/resources/file_manager/js/file_manager.js85
-rw-r--r--chrome/browser/resources/file_manager/js/mock_chrome.js3
-rw-r--r--chrome/browser/resources/file_manager/main.html10
8 files changed, 343 insertions, 45 deletions
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.cc b/chrome/browser/extensions/extension_file_browser_private_api.cc
index 245b025..c2dd955 100644
--- a/chrome/browser/extensions/extension_file_browser_private_api.cc
+++ b/chrome/browser/extensions/extension_file_browser_private_api.cc
@@ -1624,6 +1624,9 @@ bool FileDialogStringsFunction::RunImpl() {
SET_STRING(IDS_FILE_BROWSER, SAVE_LABEL);
SET_STRING(IDS_FILE_BROWSER, OK_LABEL);
+ SET_STRING(IDS_FILE_BROWSER, ERROR_VIEWING_FILE_TITLE);
+ SET_STRING(IDS_FILE_BROWSER, ERROR_VIEWING_FILE);
+
SET_STRING(IDS_FILE_BROWSER, DEFAULT_NEW_FOLDER_NAME);
SET_STRING(IDS_FILE_BROWSER, MORE_FILES);
diff --git a/chrome/browser/resources/file_manager/css/combobutton.css b/chrome/browser/resources/file_manager/css/combobutton.css
new file mode 100644
index 0000000..7daed67
--- /dev/null
+++ b/chrome/browser/resources/file_manager/css/combobutton.css
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.cr-button {
+ border: 1px solid #aaa;
+ border-radius: 2px;
+ font: -webkit-small-control;
+}
+
+.cr-button:hover {
+ border: 1px solid #999;
+ -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 3px 0;
+}
+
+.cr-button:active {
+ -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 3px 0 inset;
+}
+
+
+
+.cr-combobutton {
+ position: relative;
+ display: none;
+ font: -webkit-small-control;
+}
+
+.cr-combobutton[visible] {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+}
+
+.cr-cb-container {
+ -webkit-box-flex: 1;
+ display: -webkit-box;
+}
+
+.cr-cb-button-container {
+ -webkit-box-flex: 1;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0px;
+}
+
+.cr-combobutton[open] .cr-cb-button-container {
+ border-top-left-radius: 0;
+}
+
+.cr-cb-button-container > * {
+ background-color: rgba(0, 0, 0, 0);
+}
+
+.cr-combobutton[open] .cr-cb-button-container:hover > * {
+ background-color: #f2f6fa;
+}
+
+.cr-cb-trigger {
+ -webkit-box-flex: 0;
+ -webkit-margin-start: -1px;
+ width: 20px;
+ background-image: url('../images/disclosure_arrow_dk_grey_down.png');
+ background-repeat: no-repeat;
+ background-position: center;
+ display: none;
+ border-top-left-radius: 0px;
+ border-bottom-left-radius: 0px;
+}
+
+.cr-combobutton[multiple] .cr-cb-trigger {
+ display: block;
+}
+
+.cr-combobutton[open] .cr-cb-trigger {
+ border-top-right-radius: 0;
+}
+
+.cr-cb-popup {
+ position: absolute;
+ left: 0;
+ right: 0;
+ display: none;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: stretch;
+
+ border: 1px solid #aaa;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ border-bottom-width: 0;
+}
+
+.cr-cb-popup:active {
+ box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.cr-combobutton[open] .cr-cb-popup {
+ display: -webkit-box;
+}
+
+.cr-cb-popup > * {
+ background-color: white;
+}
+
+.cr-cb-popup > *:hover {
+ background-color: #f2f6fa;
+}
diff --git a/chrome/browser/resources/file_manager/css/file_manager.css b/chrome/browser/resources/file_manager/css/file_manager.css
index 9cf64a0..ba2df36 100644
--- a/chrome/browser/resources/file_manager/css/file_manager.css
+++ b/chrome/browser/resources/file_manager/css/file_manager.css
@@ -529,6 +529,7 @@ input.rename {
.preview-panel {
-webkit-box-orient: horizontal;
display: -webkit-box;
+ -webkit-box-align: center;
height: 61px;
background-color: #F0F0F0;
padding: 0 14px;
@@ -598,11 +599,6 @@ input.rename {
pointer-events: auto;
}
-.preview-panel > * {
- display: -webkit-box;
- -webkit-box-align: center;
-}
-
/* cr.ui.Table has a black focus border by default, which we don't want. */
.detail-table:focus {
border: 0;
@@ -803,28 +799,31 @@ li.table-row {
-webkit-margin-end: 6px;
}
-/* The task buttons at the bottom of the preview pane. */
-.task-buttons {
+.preview-panel .spacer {
-webkit-box-flex: 1;
- overflow: hidden;
+}
- display: -webkit-box;
- -webkit-box-orient: horizontal;
- -webkit-box-pack: end;
+.delete-button {
+ -webkit-margin-start: 4px;
+ -webkit-margin-end: 4px;
}
-.task-button {
+.task-item {
display: -webkit-box;
-webkit-box-orient: horizontal;
- -webkit-margin-end: 4px;
- -webkit-margin-start: 4px;
- height: 29px;
+ -webkit-box-align: center;
text-align: left;
- vertical-align: middle;
- padding: 6px;
+ padding: 5px;
+}
+
+.task-item > div {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding-right: 5px;
}
-.task-button > img {
+.task-item > img {
-webkit-margin-end: 5px;
}
diff --git a/chrome/browser/resources/file_manager/images/disclosure_arrow_dk_grey_down.png b/chrome/browser/resources/file_manager/images/disclosure_arrow_dk_grey_down.png
new file mode 100644
index 0000000..88f9bde
--- /dev/null
+++ b/chrome/browser/resources/file_manager/images/disclosure_arrow_dk_grey_down.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/js/combobutton.js b/chrome/browser/resources/file_manager/js/combobutton.js
new file mode 100644
index 0000000..a0324d5
--- /dev/null
+++ b/chrome/browser/resources/file_manager/js/combobutton.js
@@ -0,0 +1,142 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview This implements a combobutton control.
+ */
+
+cr.define('cr.ui', function() {
+ /**
+ * Creates a new combobutton element.
+ * @param {Object=} opt_propertyBag Optional properties.
+ * @constructor
+ * @extends {HTMLUListElement}
+ */
+ var ComboButton = cr.ui.define('div');
+
+ ComboButton.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ /**
+ * The items list.
+ */
+ items_: null,
+
+ clear: function() {
+ this.items_ = [];
+ this.popup_.textContent = '';
+ this.buttonContainer_.textContent = '';
+ this.multiple = false;
+ },
+
+ addItem: function(item) {
+ this.items_.push(item);
+ if (this.items_.length == 1) {
+ this.buttonContainer_.appendChild(item);
+ } else {
+ this.multiple = true;
+ if (this.visible)
+ this.popup_.style.bottom = this.clientHeight + 'px';
+ if (this.popup_.hasChildNodes())
+ this.popup_.insertBefore(item, this.popup_.firstChild);
+ else
+ this.popup_.appendChild(item);
+ }
+ },
+
+ /**
+ * Initializes the element.
+ */
+ decorate: function() {
+ this.items_ = [];
+
+ this.classList.add('cr-combobutton');
+
+ this.container_ = this.ownerDocument.createElement('div');
+ this.container_.className = 'cr-cb-container';
+ this.buttonContainer_ = this.ownerDocument.createElement('div');
+ this.buttonContainer_.className = 'cr-button cr-cb-button-container';
+ this.trigger_ = this.ownerDocument.createElement('div');
+ this.trigger_.className = 'cr-button cr-cb-trigger';
+ this.container_.appendChild(this.buttonContainer_);
+ this.container_.appendChild(this.trigger_);
+
+ this.popup_ = this.ownerDocument.createElement('div');
+ this.popup_.className = 'cr-cb-popup';
+
+ this.textContent = '';
+ this.appendChild(this.container_);
+ this.appendChild(this.popup_);
+
+ this.buttonContainer_.addEventListener('click',
+ this.handleButtonClick_.bind(this));
+ this.popup_.addEventListener('click',
+ this.handlePopupClick_.bind(this));
+ this.trigger_.addEventListener('click',
+ this.handleTriggerClicked_.bind(this));
+ this.addEventListener('mouseout', this.handleMouseOut_.bind(this));
+ this.popup_.addEventListener('mouseout',
+ this.handleMouseOut_.bind(this));
+
+ this.visible = true;
+ },
+
+ handleTriggerClicked_: function(event) {
+ this.open = !this.open;
+ },
+
+ handleMouseOut_: function(event) {
+ var x = event.x;
+ var y = event.y;
+ var r = this.popup_.getBoundingClientRect();
+ if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom)
+ return;
+ r = this.container_.getBoundingClientRect();
+ if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom)
+ return;
+ this.open = false;
+ },
+
+ handleButtonClick_: function(event) {
+ this.dispatchSelectEvent(this.items_[0]);
+ },
+
+ handlePopupClick_: function(event) {
+ var item = event.target;
+ while (item && item.parentNode != this.popup_)
+ item = item.parentNode;
+ if (!item)
+ return;
+
+ this.open = false;
+ this.dispatchSelectEvent(item);
+ },
+
+ dispatchSelectEvent: function(item) {
+ var selectEvent = new Event('select');
+ selectEvent.item = item;
+ this.dispatchEvent(selectEvent);
+ },
+
+ get visible() {
+ return this.hasAttribute('visible');
+ },
+ set visible(value) {
+ if (value) {
+ this.setAttribute('visible', 'visible');
+ this.popup_.style.bottom = this.clientHeight + 'px';
+ } else {
+ this.removeAttribute('visible');
+ }
+ }
+ };
+
+ cr.defineProperty(ComboButton, 'disabled', cr.PropertyKind.BOOL_ATTR);
+ cr.defineProperty(ComboButton, 'open', cr.PropertyKind.BOOL_ATTR);
+ cr.defineProperty(ComboButton, 'multiple', cr.PropertyKind.BOOL_ATTR);
+
+ return {
+ ComboButton: ComboButton
+ }
+});
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index bbbf127..a049159 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -629,7 +629,7 @@ FileManager.prototype = {
this.previewFilename_ = this.dialogDom_.querySelector('.preview-filename');
this.previewSummary_ = this.dialogDom_.querySelector('.preview-summary');
this.filenameInput_ = this.dialogDom_.querySelector('.filename-input');
- this.taskButtons_ = this.dialogDom_.querySelector('.task-buttons');
+ this.taskItems_ = this.dialogDom_.querySelector('.tasks');
this.okButton_ = this.dialogDom_.querySelector('.ok');
this.cancelButton_ = this.dialogDom_.querySelector('.cancel');
this.deleteButton_ = this.dialogDom_.querySelector('.delete-button');
@@ -678,6 +678,10 @@ FileManager.prototype = {
this.dialogDom_.querySelector('button.thumbnail-view').addEventListener(
'click', this.onThumbnailViewButtonClick_.bind(this));
+ cr.ui.ComboButton.decorate(this.taskItems_);
+ this.taskItems_.addEventListener('select',
+ this.onTaskItemClicked_.bind(this));
+
this.dialogDom_.ownerDocument.defaultView.addEventListener(
'resize', this.onResize_.bind(this));
@@ -1788,7 +1792,8 @@ FileManager.prototype = {
// Removing childrens of task buttons and preview thumbnails after simple
// event dispatched (see above). This can ensure a smooth disappearing
// animation when nothing is selected.
- removeChildren(this.taskButtons_);
+ this.taskItems_.visible = false;
+ this.taskItems_.clear();
removeChildren(this.previewThumbnails_);
var fileCount = 0;
@@ -1819,6 +1824,7 @@ FileManager.prototype = {
var thumbnail = this.renderThumbnailBox_(entry, true, imageLoadCalback);
box.appendChild(thumbnail);
box.style.zIndex = MAX_PREVIEW_THUMBAIL_COUNT + 1 - i;
+ box.addEventListener('click', this.dispatchDefaultTask_.bind(this));
this.previewThumbnails_.appendChild(box);
thumbnailCount++;
@@ -1866,7 +1872,7 @@ FileManager.prototype = {
}
if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) {
- removeChildren(this.taskButtons_);
+ this.taskItems_.clear();
// Some internal tasks cannot be defined in terms of file patterns,
// so we pass selection to check for them manually.
if (selection.directoryCount == 0 && selection.fileCount > 0) {
@@ -2022,7 +2028,7 @@ FileManager.prototype = {
* @param {Array.<Task>} tasksList The tasks list.
*/
FileManager.prototype.onTasksFound_ = function(selection, tasksList) {
- removeChildren(this.taskButtons_);
+ this.taskItems_.clear();
for (var i = 0; i < tasksList.length; i++) {
var task = tasksList[i];
@@ -2054,29 +2060,42 @@ FileManager.prototype = {
this.galleryTask_ = task;
}
}
- this.renderTaskButton_(task);
+ this.renderTaskItem_(task);
}
+ this.taskItems_.visible = tasksList.length > 0;
+
+ selection.tasksList = tasksList;
+ if (selection.dispatchDefault) {
+ // We got a request to dispatch the default task for the selection.
+ selection.dispatchDefault = false;
+ if (tasksList.length > 0) {
+ this.dispatchFileTask_(tasksList[0], selection.urls);
+ } else {
+ this.alert.showWithTitle(
+ strf('ERROR_VIEWING_FILE_TITLE', selection.entries[0].name),
+ strf('ERROR_VIEWING_FILE'));
+ }
+ }
// These are done in separate functions, as the checks require
// asynchronous function calls.
this.maybeRenderFormattingTask_(selection);
};
- FileManager.prototype.renderTaskButton_ = function(task) {
- var button = this.document_.createElement('button');
- button.addEventListener('click',
- this.onTaskButtonClicked_.bind(this, task));
- button.className = 'task-button';
+ FileManager.prototype.renderTaskItem_ = function(task) {
+ var item = this.document_.createElement('div');
+ item.className = 'task-item';
+ item.task = task;
var img = this.document_.createElement('img');
img.src = task.iconUrl;
+ item.appendChild(img);
- button.appendChild(img);
var label = this.document_.createElement('div');
- label.appendChild(this.document_.createTextNode(task.title))
- button.appendChild(label);
+ label.appendChild(this.document_.createTextNode(task.title));
+ item.appendChild(label);
- this.taskButtons_.appendChild(button);
+ this.taskItems_.addItem(item);
};
/**
@@ -2106,7 +2125,7 @@ FileManager.prototype = {
title: str('FORMAT_DEVICE'),
internal: true
};
- self.renderTaskButton_(task);
+ self.renderTaskItem_(task);
}
}
@@ -2138,19 +2157,34 @@ FileManager.prototype = {
}
};
- FileManager.prototype.onTaskButtonClicked_ = function(task, event) {
- this.dispatchFileTask_(task, this.selection.urls);
+ FileManager.prototype.onTaskItemClicked_ = function(event) {
+ this.dispatchFileTask_(event.item.task, this.selection.urls);
+ };
+
+ /**
+ * Dispatches default task for the current selection. If tasks are not ready
+ * yet, dispatches after task are available.
+ */
+ FileManager.prototype.dispatchDefaultTask_ = function() {
+ if (this.selection.tasksList) {
+ if (this.selection.tasksList.length > 0 && this.selection.urls.length > 0)
+ this.dispatchFileTask_(this.selection.tasksList[0],
+ this.selection.urls);
+ } else {
+ // Request to dispatch default task after we get all the tasks.
+ this.selection.dispatchDefault = true;
+ }
};
FileManager.prototype.dispatchFileTask_ = function(task, urls) {
+ chrome.fileBrowserPrivate.executeTask(task.taskId, urls);
if (task.internal) {
- // For internal tasks call the handler directly to avoid being handled
- // multiple times.
+ // For internal tasks we do not listen to the event to avoid
+ // handling the same task instance from multiple tabs.
+ // So, we manually execute the task.
var taskId = task.taskId.split('|')[1];
this.onFileTaskExecute_(taskId, {urls: urls, task: task});
- return;
}
- chrome.fileBrowserPrivate.executeTask(task.taskId, urls);
};
/**
@@ -2824,9 +2858,12 @@ FileManager.prototype = {
return this.onDirectoryAction(entry);
}
- if (!this.okButton_.disabled)
- this.onOk_();
-
+ if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) {
+ this.dispatchDefaultTask_();
+ } else {
+ if (!this.okButton_.disabled)
+ this.onOk_();
+ }
};
FileManager.prototype.onDirectoryAction = function(entry) {
diff --git a/chrome/browser/resources/file_manager/js/mock_chrome.js b/chrome/browser/resources/file_manager/js/mock_chrome.js
index ac4eaaa..0fd2075 100644
--- a/chrome/browser/resources/file_manager/js/mock_chrome.js
+++ b/chrome/browser/resources/file_manager/js/mock_chrome.js
@@ -298,6 +298,9 @@ chrome.fileBrowserPrivate = {
OPEN_LABEL: 'Open',
SAVE_LABEL: 'Save',
OK_LABEL: 'OK',
+ ERROR_VIEWING_FILE_TITLE: '$1',
+ ERROR_VIEWING_FILE: 'To view this file, convert it to a format that\'s ' +
+ 'viewable on the web. For example, you can upload it to Google Docs.',
DEFAULT_NEW_FOLDER_NAME: 'New Folder',
MORE_FILES: 'Show all files',
diff --git a/chrome/browser/resources/file_manager/main.html b/chrome/browser/resources/file_manager/main.html
index 9ee92e6..001a820 100644
--- a/chrome/browser/resources/file_manager/main.html
+++ b/chrome/browser/resources/file_manager/main.html
@@ -84,6 +84,9 @@
<script src="../shared/js/cr/ui/menu.js"></script>
<script src="../shared/js/cr/ui/context_menu_handler.js"></script>
+ <script src="js/combobutton.js"></script>
+ <link rel="stylesheet" href="css/combobutton.css"></link>
+
<link rel="stylesheet" href="css/file_manager.css"></link>
<script src="js/util.js"></script>
@@ -176,15 +179,16 @@
<div class=preview-panel visibility=hidden>
<div><div class=preview-thumbnails></div></div>
<div><div class=preview-summary></div></div>
- <div class=task-buttons></div>
+ <div class=spacer></div>
+ <div class=tasks></div>
<div>
- <button class='delete-button task-button' command='#delete'
+ <div class='delete-button cr-button task-item' command='#delete'
onclick='fileManager.deleteEntries(
fileManager.selection.entries, false)'
visibleif='this.dialogType_ == "full-page"'
><img src='images/button-icon-delete.png'
><div i18n-content=DELETE_BUTTON_LABEL></div
- ></button>
+ ></div>
</div>
</div>
</div>