diff options
7 files changed, 369 insertions, 57 deletions
diff --git a/chrome/browser/resources/gpu_internals.html b/chrome/browser/resources/gpu_internals.html index 9b3fb86..0a39277 100644 --- a/chrome/browser/resources/gpu_internals.html +++ b/chrome/browser/resources/gpu_internals.html @@ -7,26 +7,35 @@ found in the LICENSE file. --> <head i18n-values="dir:textdirection;"> <link rel="stylesheet" href="dom_ui.css"> -<link rel="stylesheet" href="net_internals/tabswitcherview.css"> <style> * { box-sizing: border-box; } + +html, body, #main-tabs { + height: 100%; +} + body { + cursor: default; font-family: sans-serif; + padding: 0; + margin: 0; } </style> +<link rel="stylesheet" href="gpu_internals/tab_control.css"> <link rel="stylesheet" href="gpu_internals/info_view.css"> <script src="chrome://resources/js/cr.js"></script> -<script src="net_internals/util.js"></script> -<script src="net_internals/view.js"></script> -<script src="net_internals/tabswitcherview.js"></script> +<script src="chrome://resources/js/cr/event_target.js"></script> +<script src="chrome://resources/js/cr/ui.js"></script> +<script src="chrome://resources/js/util.js"></script> +<script src="gpu_internals/tab_control.js"></script> <script src="gpu_internals/browser_bridge.js"></script> <script src="gpu_internals/info_view.js"></script> <script> -var browser = null; +var browser; /** * Main entry point. called once the page has loaded. @@ -34,41 +43,30 @@ var browser = null; function onLoad() { browserBridge = new gpu.BrowserBridge(); - // Create a view which will display general information - // about the gpu. - var infoView = new gpu.InfoView('info-view'); + // Create the views. + cr.ui.decorate('#info-view', gpu.InfoView); - // Create a view which lets you tab between the different sub-views. - var categoryTabSwitcher = - new TabSwitcherView('category-tab-handles'); - - // Populate the main tabs. - categoryTabSwitcher.addTab('info-tab', infoView, false); - - // Build a map from the anchor name of each tab handle to its 'tab ID'. - // We will consider navigations to the #hash as a switch tab request. - var anchorMap = {}; - var tabIds = categoryTabSwitcher.getAllTabIds(); - for (var i = 0; i < tabIds.length; i++) { - var aNode = document.getElementById(tabIds[i]); - anchorMap[aNode.hash] = tabIds[i]; - } - // Default the empty hash to the info tab. - anchorMap['#'] = anchorMap[''] = 'info-tab'; + // Create the main tab control + var tabs = $('main-tabs'); + cr.ui.decorate(tabs, gpu.TabControl); + // Sync the main-tabs selectedTabs in-sync with the location. + tabs.addEventListener('selectedTabChanged', function() { + if (tabs.selectedTab.id) { + history.pushState('', '', '#' + tabs.selectedTab.id); + } + }); window.onhashchange = function() { - var tabId = anchorMap[window.location.hash]; - if (tabId) - categoryTabSwitcher.switchToTab(tabId); + var cur = window.location.hash; + if (cur == '#' || cur == '') { + if (tabs.tabs.length) + tabs.selectedTab = tabs.tabs[0]; + } else { + var tab = $(window.location.hash.substr(1)); + if (tab) + tabs.selectedTab = tab; + } }; - - // Make this category tab widget the primary view, that fills the whole page. - var windowView = new WindowView(categoryTabSwitcher); - - // Trigger initial layout. - windowView.resetGeometry(); - - // Select the initial view based on the current URL. window.onhashchange(); } @@ -77,15 +75,9 @@ document.addEventListener('DOMContentLoaded', onLoad); </script> </head> <body> - - <!-- Tab switcher for main categories. --> - <div id=category-tab-handles> - <ul> - <li><a href="#info" id="info-tab">GPU Info</a></li> - </ul> - </div> - <!-- Tabs --> - <include src="gpu_internals/info_view.html"> + <div id="main-tabs"> + <include src="gpu_internals/info_view.html"> + </div> </body> </html> diff --git a/chrome/browser/resources/gpu_internals/info_view.css b/chrome/browser/resources/gpu_internals/info_view.css index d7c1f97..c4cd6ca 100644 --- a/chrome/browser/resources/gpu_internals/info_view.css +++ b/chrome/browser/resources/gpu_internals/info_view.css @@ -16,6 +16,7 @@ found in the LICENSE file. } #info-view table { + cursor: text; border-collapse: collapse; } diff --git a/chrome/browser/resources/gpu_internals/info_view.html b/chrome/browser/resources/gpu_internals/info_view.html index 2db2813..dc4c0cb 100644 --- a/chrome/browser/resources/gpu_internals/info_view.html +++ b/chrome/browser/resources/gpu_internals/info_view.html @@ -3,7 +3,7 @@ Copyright (c) 2010 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. --> -<div id=info-view> +<div id=info-view label="GPU Info"> <h3>Chrome Version</h3> <div id="client-info"></div> <h3>Driver Information</h3> diff --git a/chrome/browser/resources/gpu_internals/info_view.js b/chrome/browser/resources/gpu_internals/info_view.js index 4f73a86..bf53229 100644 --- a/chrome/browser/resources/gpu_internals/info_view.js +++ b/chrome/browser/resources/gpu_internals/info_view.js @@ -15,21 +15,24 @@ cr.define('gpu', function() { /** * Provides information on the GPU process and underlying graphics hardware. * @constructor + * @extends {Tab} */ - function InfoView(mainBoxId) { - DivView.call(this, mainBoxId); + var InfoView = cr.ui.define(gpu.Tab); - this.beginRequestClientInfo(); - this.beginRequestGpuInfo(); + InfoView.prototype = { + __proto__: gpu.Tab.prototype, - this.logMessages_ = []; - this.beginRequestLogMessages(); + decorate : function() { + gpu.Tab.prototype.decorate.apply(this); - this.refresh(); - } + this.beginRequestClientInfo(); + this.beginRequestGpuInfo(); - InfoView.prototype = { - __proto__: DivView.prototype, + this.logMessages_ = []; + this.beginRequestLogMessages(); + + this.refresh(); + }, /** * This function begins a request for the ClientInfo. If it comes back diff --git a/chrome/browser/resources/gpu_internals/tab_control.css b/chrome/browser/resources/gpu_internals/tab_control.css new file mode 100644 index 0000000..4d7b7f8 --- /dev/null +++ b/chrome/browser/resources/gpu_internals/tab_control.css @@ -0,0 +1,67 @@ +/* +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. +*/ +.tab-control { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-pack: start; + + padding: 0; + margin: 0; +} + +.tab-control > .tab-strip { + font-family: sans-serif; + background: #aaa; + border-bottom: 1px solid #555; + + -webkit-user-select: none; + + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-pack: start; +} + +.tab-control > .tabs { + -webkit-box-flex: 1; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-pack: stretch; + overflow: auto; +} + +.tab-control > .tabs > :not([selected]) { + display: none; +} + +.tab-control .tab-button { + -webkit-margin-start: 5px; + text-decoration: none; + text-align: center; + display: inline-block; + margin-top: 4px; + padding: 5px 10px 3px 10px; + border-top-right-radius: 8px; + border-top-left-radius: 8px; + background-clip: border-box; + background: #ccc; +} + +.tab-control .tab-button:hover { + background: #eee; +} + + +.tab-control .tab-button:visited, +.tab-control .tab-button { + color: blue; +} + +.tab-control .tab-button[selected] { + position: relative; + top: 1px; + color: black; + background: white; +} diff --git a/chrome/browser/resources/gpu_internals/tab_control.js b/chrome/browser/resources/gpu_internals/tab_control.js new file mode 100644 index 0000000..6c4a120 --- /dev/null +++ b/chrome/browser/resources/gpu_internals/tab_control.js @@ -0,0 +1,249 @@ +// 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. +/** + * + * @fileoverview This implements a tab control. + * + * An individual tab within a tab control is, unsurprisingly, a Tab. + * Tabs must be explicitly added/removed from the control. + * + * Tab titles are based on the label attribute of each child: + * + * <div> + * <div label='Tab 1'>Hello</div> + * <div label='Tab 2'>World</div> + * </div> + * + * Results in: + * + * --------------- + * | Tab1 | Tab2 | + * | --------------------------------------- + * | Hello World | + * ----------------------------------------- + * + */ +cr.define('gpu', function() { + /** + * Creates a new tab element. A tab element is one of multiple tabs + * within a TabControl. + * @constructor + * @param {Object=} opt_propertyBag Optional properties. + * @extends {HTMLDivElement} + */ + var Tab = cr.ui.define('div'); + Tab.prototype = { + __proto__: HTMLDivElement.prototype, + + decorate : function() { + } + }; + + /** + * Title for the tab. + * @type {String} + */ + cr.defineProperty(Tab, 'label', cr.PropertyKind.ATTR); + + /** + * Whether the item is selected. + * @type {boolean} + */ + cr.defineProperty(Tab, 'selected', cr.PropertyKind.BOOL_ATTR); + + + /** + * Creates a new tab button element in the tabstrip + * @constructor + * @param {Object=} opt_propertyBag Optional properties. + * @extends {HTMLDivElement} + */ + var TabButton = cr.ui.define('a'); + TabButton.prototype = { + __proto__: HTMLAnchorElement.prototype, + + decorate: function() { + this.classList.add('tab-button'); + this.onclick = function() { + if (this.tab_) + this.parentNode.parentNode.selectedTab = this.tab_; + }.bind(this); + }, + get tab() { + return this.tab_; + }, + set tab(tab) { + if (this.tab_) + throw Error('Cannot set tab once set.'); + this.tab_ = tab; + this.tab_.addEventListener('titleChange', this.onTabChanged_.bind(this)); + this.tab_.addEventListener('selectedChange', + this.onTabChanged_.bind(this)); + this.onTabChanged_(); + }, + + onTabChanged_ : function(e) { + if (this.tab_) { + this.textContent = this.tab_.label; + this.selected = this.tab_.selected; + } + } + + }; + + /** + * Whether the TabButton is selected. + * @type {boolean} + */ + cr.defineProperty(TabButton, 'selected', cr.PropertyKind.BOOL_ATTR); + + + /** + * Creates a new tab control element. + * @param {Object=} opt_propertyBag Optional properties. + * @constructor + * @extends {HTMLDivElement} + */ + var TabControl = cr.ui.define('div'); + TabControl.prototype = { + __proto__: HTMLDivElement.prototype, + + selectedTab_ : null, + + /** + * Initializes the tab control element. + * Any child elements pre-existing on the element will become tabs. + */ + decorate: function() { + this.classList.add('tab-control'); + + this.tabStrip_ = this.ownerDocument.createElement('div'); + this.tabStrip_.classList.add('tab-strip'); + + this.tabs_ = this.ownerDocument.createElement('div'); + this.tabs_.classList.add('tabs'); + + this.insertBefore(this.tabs_, this.firstChild); + this.insertBefore(this.tabStrip_, this.firstChild); + + this.boundOnTabSelectedChange_ = this.onTabSelectedChange_.bind(this); + + // Reparent existing tabs to the tabs_ div. + while (this.children.length > 2) + this.addTab(this.children[2]); + }, + + /** + * Adds an element to the tab control. + */ + addTab : function(tab) { + if (tab.parentNode == this.tabs_) + throw Error('Tab is already part of this control.'); + if (!(tab instanceof Tab)) + throw Error('Provided element is not instanceof Tab.'); + this.tabs_.appendChild(tab); + + tab.addEventListener('selectedChange', this.boundOnTabSelectedChange_); + + var button = new TabButton(); + button.tab = tab; + tab.tabStripButton_ = button; + + this.tabStrip_.appendChild(button); + + if (this.tabs_.length == 1) + this.tabs_.children[0].selected = true; + }, + + /** + * Removes a tab from the tab control. + * changing the selected tab if needed. + */ + removeTab : function(tab) { + if (tab.parentNode != this.tabs_) + throw new Error('Tab is not attached to this control.'); + + tab.removeEventListener('selectedChange', this.boundOnTabSelectedChange_); + + if (this.selectedTab_ == tab) { + if (this.tabs_.children.length) { + this.tabs_.children[0].selected = true; + } else { + this.selectedTab_ = undefined; + } + } + + this.tabs_.removeChild(tab); + tab.tabStripButton_.parentNode.removeChild( + tab.tabStripButton_); + }, + + /** + * Gets the currently selected tab element. + */ + get selectedTab() { + return this.selectedTab_; + }, + + /** + * Sets the currently selected tab element. + */ + set selectedTab(tab) { + if (tab.parentNode != this.tabs_) + throw Error("Tab is not part of this TabControl."); + tab.selected = true; + }, + + /** + * Hides the previously selected tab element and dispatches a + * 'selectedTabChanged' event. + */ + onTabSelectedChange_: function(e) { + var tab = e.target; + if (!e.newValue) { + // Usually we can ignore this event, as the tab becoming unselected + // needs no corrective action. However, if the currently selected + // tab is deselected, we do need to do some work. + if (tab == this.selectedTab_) { + var previousTab = this.selectedTab_; + var newTab; + for (var i = 0; i < this.tabs_.children.length; ++i) { + if (this.tabs_.children[i] != tab) { + newTab = this.tabs_.children[i]; + break; + } + } + if (newTab) { + newTab.selected = true; + } else { + this.selectedTab_ = undefined; + cr.dispatchPropertyChange( + this, 'selectedTab', this.selectedTab_, previousTab); + } + } + } else { + var previousTab = this.selectedTab_; + this.selectedTab_ = tab; + if (previousTab) + previousTab.selected = false; + cr.dispatchPropertyChange( + this, 'selectedTab', this.selectedTab_, previousTab); + } + }, + + /** + * Returns an array of all the tabs within this control. This is + * not the same as this.children because the actual tab elements are + * attached to the tabs_ element. + */ + get tabs() { + return Array.prototype.slice.call(this.tabs_.children); + } + }; + + return { + Tab : Tab, + TabControl: TabControl + }; +});
\ No newline at end of file diff --git a/chrome/browser/resources/net_internals/tabswitcherview.css b/chrome/browser/resources/net_internals/tabswitcherview.css index 4b8fb50..5600bee 100644 --- a/chrome/browser/resources/net_internals/tabswitcherview.css +++ b/chrome/browser/resources/net_internals/tabswitcherview.css @@ -24,7 +24,7 @@ found in the LICENSE file. -webkit-margin-start: 5px; } -xhtml[dir=rtl] .tab-switcher-view li { +html[dir=rtl] .tab-switcher-view li { float: right; } |