diff options
11 files changed, 267 insertions, 5 deletions
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 086d2bc..e5b6c8e 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc @@ -39,6 +39,19 @@ IN_PROC_BROWSER_TEST_P(FileManagerBrowserTest, Test) { StartTest(); } +// Test fixture class for details panel. +// TODO(ryoh): remove after we release details panel feature. +class FileManagerDetailsPanelBrowserTest : public FileManagerBrowserTest { + void SetUpCommandLine(base::CommandLine* command_line) override { + FileManagerBrowserTestBase::SetUpCommandLine(command_line); + command_line->AppendSwitch("--enable-files-details-panel"); + } +}; + +IN_PROC_BROWSER_TEST_P(FileManagerDetailsPanelBrowserTest, Test) { + StartTest(); +} + // Unlike TEST/TEST_F, which are macros that expand to further macros, // INSTANTIATE_TEST_CASE_P is a macro that expands directly to code that // stringizes the arguments. As a result, macros passed as parameters (such as @@ -167,6 +180,13 @@ WRAPPED_INSTANTIATE_TEST_CASE_P( "deleteMenuItemIsDisabledWhenNoItemIsSelected"), TestParameter(NOT_IN_GUEST_MODE, "deleteOneItemFromToolbar"))); +WRAPPED_INSTANTIATE_TEST_CASE_P( + DetailsPanel, + FileManagerDetailsPanelBrowserTest, + ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "openDetailsPanel"), + TestParameter(NOT_IN_GUEST_MODE, + "openDetailsPanelForSingleFile"))); + #if defined(DISABLE_SLOW_FILESAPP_TESTS) #define MAYBE_DirectoryTreeContextMenu DISABLED_DirectoryTreeContextMenu #else diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index f83f14f..c05be9d 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css @@ -127,11 +127,13 @@ a:focus { /* Details pane */ .details-container { background-color: rgb(250, 250, 250); + display: flex; flex: none; max-width: 30%; min-width: 100px; overflow: hidden; position: relative; + width: 240px; } #list-details-splitter:not([activated]) { @@ -142,6 +144,22 @@ a:focus { display: none; } +.details-container > div:not([activated]) { + display: none !important; +} + +.details-container > #single-file-details { + display: flex; + flex: auto; + flex-direction: row; + width: 100%; +} + +#single-file-details > .details-list { + flex: auto; + width: 100%; +} + /* Directory tree at the left. */ .dialog-navigation-list { -webkit-border-end: 1px solid rgba(0, 0, 0, 0.15); diff --git a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp index 9b9a5da..e000c3d 100644 --- a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp +++ b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp @@ -147,6 +147,7 @@ './ui/scrollbar.js', './ui/search_box.js', './ui/share_dialog.js', + './ui/single_file_details.js', './ui/suggest_apps_dialog.js', './main_window_component.js', './volume_manager_wrapper.js', diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index 811a998..e808134 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js @@ -833,12 +833,17 @@ FileManager.prototype = /** @struct */ { this.metadataModel_, this.volumeManager_, this.historyLoader_); + var singlePanel = queryRequiredElement('#single-file-details', dom); + SingleFileDetailsPanel.decorate( + assertInstanceof(singlePanel, HTMLDivElement), + this.metadataModel_); this.addHistoryObserver_(); this.ui_.initAdditionalUI( assertInstanceof(table, FileTable), assertInstanceof(grid, FileGrid), + assertInstanceof(singlePanel, SingleFileDetailsPanel), new LocationLine( queryRequiredElement('#location-breadcrumbs', dom), this.volumeManager_)); diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js index c7c905a..7a053ab 100644 --- a/ui/file_manager/file_manager/foreground/js/main_scripts.js +++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js @@ -163,6 +163,7 @@ //<include src="ui/scrollbar.js"> //<include src="ui/search_box.js"> //<include src="ui/share_dialog.js"> +//<include src="ui/single_file_details.js"> //<include src="ui/suggest_apps_dialog.js"> //<include src="main_window_component.js"> //<include src="volume_manager_wrapper.js"> diff --git a/ui/file_manager/file_manager/foreground/js/ui/details_container.js b/ui/file_manager/file_manager/foreground/js/ui/details_container.js index 1d54bad..298f607 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/details_container.js +++ b/ui/file_manager/file_manager/foreground/js/ui/details_container.js @@ -4,13 +4,15 @@ /** * @param {!HTMLElement} element + * @param {!SingleFileDetailsPanel} singlePanel * @param {!Element} splitter * @param {!Element} button * @param {!FilesToggleRipple} toggleRipple * @constructor * @struct */ -function DetailsContainer(element, splitter, button, toggleRipple) { +function DetailsContainer(element, singlePanel, splitter, button, + toggleRipple) { /** * Container element. * @private {!HTMLElement} @@ -36,6 +38,12 @@ function DetailsContainer(element, splitter, button, toggleRipple) { */ this.toggleRipple_ = toggleRipple; /** + * Details panel for a single file. + * @private {!SingleFileDetailsPanel} + * @const + */ + this.singlePanel_ = singlePanel; + /** * @type {boolean} */ this.visible = false; @@ -43,7 +51,17 @@ function DetailsContainer(element, splitter, button, toggleRipple) { } DetailsContainer.prototype.onFileSelectionChanged = function(event) { - var selection = event.target.selection; + var entries = event.target.selection.entries; + if (entries.length === 0) { + this.singlePanel_.removeAttribute('activated'); + this.singlePanel_.classList.toggle('activated', false); + // TODO(ryoh): make a panel for empty selection + } else if (entries.length === 1) { + this.singlePanel_.setAttribute('activated', ''); + this.singlePanel_.onFileSelectionChanged(entries[0]); + } else { + // TODO(ryoh): make a panel for multiple selection + } }; /** diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index 4c04632..4459932 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js @@ -338,10 +338,11 @@ function FileManagerUI(providersModel, element, launchParam) { * * @param {!FileTable} table * @param {!FileGrid} grid + * @param {!SingleFileDetailsPanel} singlePanel * @param {!LocationLine} locationLine */ FileManagerUI.prototype.initAdditionalUI = function( - table, grid, locationLine) { + table, grid, singlePanel, locationLine) { // List container. this.listContainer = new ListContainer( queryRequiredElement('#list-container', this.element), table, grid); @@ -357,9 +358,10 @@ FileManagerUI.prototype.initAdditionalUI = function( this.detailsButton.style.display = 'block'; var listDetailsSplitter = queryRequiredElement('#list-details-splitter', this.element); - this.decorateSplitter_(listDetailsSplitter); + this.decorateSplitter_(listDetailsSplitter, true); this.detailsContainer = new DetailsContainer( queryRequiredElement('#details-container', this.element), + singlePanel, listDetailsSplitter, this.detailsButton, this.detailsButtonToggleRipple_); @@ -515,9 +517,11 @@ FileManagerUI.prototype.onExternalLinkClick_ = function(event) { /** * Decorates the given splitter element. * @param {!HTMLElement} splitterElement + * @param {boolean=} opt_resizeNextElement * @private */ -FileManagerUI.prototype.decorateSplitter_ = function(splitterElement) { +FileManagerUI.prototype.decorateSplitter_ = function(splitterElement, + opt_resizeNextElement) { var self = this; var Splitter = cr.ui.Splitter; var customSplitter = cr.ui.define('div'); @@ -542,4 +546,5 @@ FileManagerUI.prototype.decorateSplitter_ = function(splitterElement) { }; customSplitter.decorate(splitterElement); + splitterElement.resizeNextElement = !!opt_resizeNextElement; }; diff --git a/ui/file_manager/file_manager/foreground/js/ui/single_file_details.js b/ui/file_manager/file_manager/foreground/js/ui/single_file_details.js new file mode 100644 index 0000000..5329e1c --- /dev/null +++ b/ui/file_manager/file_manager/foreground/js/ui/single_file_details.js @@ -0,0 +1,130 @@ +// Copyright 2016 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. + + +/** + * SingleFileDetailsPanel constructor. + * + * Represents grid for the details panel for a single file in Files app. + * @constructor + * @extends {HTMLDivElement} + */ +function SingleFileDetailsPanel() { + throw new Error('Use SingleFileDetailsList.decorate'); +} + +/** + * Inherits from cr.ui.List. + */ +SingleFileDetailsPanel.prototype = { + __proto__: HTMLDivElement.prototype, + onFileSelectionChanged: function(entry) { + this.filename_.textContent = entry.name; + } +}; + +/** + * Decorates an HTML element to be a SingleFileDetailsList. + * @param {!HTMLDivElement} self The grid to decorate. + * @param {!MetadataModel} metadataModel File system metadata. + */ +SingleFileDetailsPanel.decorate = function(self, metadataModel) { + self.__proto__ = SingleFileDetailsPanel.prototype; + self.metadataModel = metadataModel; + /** + * Data model of detail infos. + * @private {!SingleFileDetailsDataModel} + * @const + */ + self.model_ = new SingleFileDetailsDataModel(); + self.filename_ = assertInstanceof(queryRequiredElement('.filename', self), + HTMLDivElement); + var list = queryRequiredElement('.details-list', self); + SingleFileDetailsList.decorate(list, metadataModel); + self.list_ = assertInstanceof(list, SingleFileDetailsList); + self.list_.dataModel = self.model_; + self.list_.autoExpands = true; +}; + +/** + * SingleFileDetailsList constructor. + * + * Represents grid for the details list for a single file in Files app. + * @constructor + * @extends {cr.ui.List} + */ +function SingleFileDetailsList() { + throw new Error('Use SingleFileDetailsList.decorate'); +} + +/** + * Inherits from cr.ui.List. + */ +SingleFileDetailsList.prototype = { + __proto__: cr.ui.List.prototype, + onFileSelectionChanged: function(entry) { + console.log(entry); + } +}; + +/** + * Decorates an HTML element to be a SingleFileDetailsList. + * @param {!Element} self The grid to decorate. + * @param {!MetadataModel} metadataModel File system metadata. + */ +SingleFileDetailsList.decorate = function(self, metadataModel) { + cr.ui.Grid.decorate(self); + self.__proto__ = SingleFileDetailsList.prototype; + self.metadataModel_ = metadataModel; + + self.scrollBar_ = new ScrollBar(); + self.scrollBar_.initialize(self.parentElement, self); + + self.itemConstructor = function(entry) { + var item = self.ownerDocument.createElement('li'); + SingleFileDetailsList.Item.decorate( + item, + entry, + /** @type {FileGrid} */ (self)); + return item; + }; +}; + +/** + * Item for the Grid View. + * @constructor + * @extends {cr.ui.ListItem} + */ +SingleFileDetailsList.Item = function() { + throw new Error(); +}; + +/** + * Inherits from cr.ui.DetailsItem. + */ +SingleFileDetailsList.Item.prototype.__proto__ = cr.ui.ListItem.prototype; + +/** + * @param {Element} li List item element. + * @param {!Entry} entry File entry. + * @param {FileGrid} grid Owner. + */ +SingleFileDetailsList.Item.decorate = function(li, entry, grid) { + li.__proto__ = SingleFileDetailsList.Item.prototype; +}; + +/** + * Data model for details panel. + * + * @constructor + * @extends {cr.ui.ArrayDataModel} + */ +function SingleFileDetailsDataModel() { + cr.ui.ArrayDataModel.call(this, []); +} + +SingleFileDetailsDataModel.prototype = { + __proto__: cr.ui.ArrayDataModel.prototype, + +}; diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index 3639d5a..bc66610 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html @@ -411,6 +411,10 @@ </div> <div class="splitter" id="list-details-splitter"></div> <div id="details-container" class="details-container"> + <div id="single-file-details"> + <div class="filename"></div> + <ul class="details-list"></ul> + </div> </div> </div> <div class="dialog-footer progressable" tabindex="-1" diff --git a/ui/file_manager/integration_tests/file_manager/details_panel.js b/ui/file_manager/integration_tests/file_manager/details_panel.js new file mode 100644 index 0000000..f5fd6f8 --- /dev/null +++ b/ui/file_manager/integration_tests/file_manager/details_panel.js @@ -0,0 +1,59 @@ +// Copyright 2016 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. + +'use strict'; + +testcase.openDetailsPanel = function() { + var appId; + StepsRunner.run([ + function() { + setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next); + }, + function(results) { + appId = results.windowId; + remoteCall.callRemoteTestUtil('fakeEvent', + appId, + ['#details-button', 'click'], + this.next); + }, + function(result) { + remoteCall.waitForElement(appId, "#details-container").then(this.next); + }, + function(result) { + chrome.test.assertFalse(result.hidden); + checkIfNoErrorsOccured(this.next); + } + ]); +}; + +testcase.openDetailsPanelForSingleFile = function() { + var appId; + StepsRunner.run([ + function() { + setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next); + }, + function(results) { + appId = results.windowId; + remoteCall.callRemoteTestUtil('fakeEvent', + appId, + ['#details-button', 'click'], + this.next); + }, + function(result) { + remoteCall.waitForElement(appId, "#details-container").then(this.next); + }, + function(result) { + chrome.test.assertFalse(result.hidden); + remoteCall.waitForAFile('downloads', + 'hello.txt').then(this.next); + }, + function(result) { + remoteCall.waitForElement(appId, "#single-file-details").then(this.next); + }, + function(result) { + chrome.test.assertFalse(result.hidden); + checkIfNoErrorsOccured(this.next); + } + ]); +}; diff --git a/ui/file_manager/integration_tests/file_manager_test_manifest.json b/ui/file_manager/integration_tests/file_manager_test_manifest.json index 69ec689..3395de6 100644 --- a/ui/file_manager/integration_tests/file_manager_test_manifest.json +++ b/ui/file_manager/integration_tests/file_manager_test_manifest.json @@ -15,6 +15,7 @@ "file_manager/copy_between_windows.js", "file_manager/create_new_folder.js", "file_manager/delete.js", + "file_manager/details_panel.js", "file_manager/directory_tree_context_menu.js", "file_manager/drive_specific.js", "file_manager/file_dialog.js", |