| /* |
| * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. |
| * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com). |
| * Copyright (C) 2009 Joseph Pecoraro |
| * Copyright (C) 2011 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @constructor |
| */ |
| WebInspector.Toolbar = function() |
| { |
| this.element = document.getElementById("toolbar"); |
| WebInspector.installDragHandle(this.element, this._toolbarDragStart.bind(this), this._toolbarDrag.bind(this), this._toolbarDragEnd.bind(this), "default"); |
| |
| this._dropdownButton = document.getElementById("toolbar-dropdown-arrow"); |
| this._dropdownButton.addEventListener("click", this._toggleDropdown.bind(this), false); |
| |
| this._panelsMenuButton = document.getElementById("toolbar-panels-menu"); |
| if (this._isToolbarCustomizable()) { |
| this._panelsMenuButton.addEventListener("mousedown", this._togglePanelsMenu.bind(this), false); |
| this._panelsMenuButton.removeStyleClass("hidden"); |
| } |
| |
| document.getElementById("close-button-left").addEventListener("click", this._onClose, true); |
| document.getElementById("close-button-right").addEventListener("click", this._onClose, true); |
| |
| this._panelDescriptors = []; |
| } |
| |
| WebInspector.Toolbar.prototype = { |
| resize: function() |
| { |
| this._updateDropdownButtonAndHideDropdown(); |
| }, |
| |
| /** |
| * @param {!WebInspector.PanelDescriptor} panelDescriptor |
| */ |
| addPanel: function(panelDescriptor) |
| { |
| this._panelDescriptors.push(panelDescriptor); |
| panelDescriptor._toolbarElement = this._createPanelToolbarItem(panelDescriptor); |
| if (!this._isToolbarCustomizable() || this._isPanelVisible(panelDescriptor.name())) |
| this.element.insertBefore(panelDescriptor._toolbarElement, this._panelInsertLocation(panelDescriptor)); |
| this._updatePanelsMenuState(); |
| this.resize(); |
| }, |
| |
| /** |
| * @param {!WebInspector.PanelDescriptor} panelDescriptor |
| * @return {Element} |
| */ |
| _panelInsertLocation: function(panelDescriptor) |
| { |
| if (!this._isToolbarCustomizable()) |
| return null; |
| |
| if (this._isDefaultPanel(panelDescriptor.name())) |
| return this._firstNonDefaultPanel || null; |
| |
| if (!this._firstNonDefaultPanel) |
| this._firstNonDefaultPanel = panelDescriptor._toolbarElement; |
| return null; |
| }, |
| |
| /** |
| * @param {!string} name |
| * @return {boolean} |
| */ |
| _isDefaultPanel: function(name) |
| { |
| var defaultPanels = { |
| "elements": true, |
| "resources": true, |
| "scripts": true, |
| "console": true, |
| "network": true, |
| "timeline": true, |
| }; |
| return !!defaultPanels[name]; |
| }, |
| |
| /** |
| * @param {!string} name |
| * @return {boolean} |
| */ |
| _isPanelVisibleByDefault: function(name) |
| { |
| var visible = { |
| "elements": true, |
| "console": true, |
| "network": true, |
| "scripts": true, |
| "timeline": true, |
| "profiles": true, |
| "cpu-profiler": true, |
| "heap-profiler": true, |
| "audits": true, |
| "resources": true, |
| }; |
| return !!visible[name]; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _isToolbarCustomizable: function() |
| { |
| return WebInspector.experimentsSettings.customizableToolbar.isEnabled(); |
| }, |
| |
| /** |
| * @param {!string} name |
| * @return {boolean} |
| */ |
| _isPanelVisible: function(name) |
| { |
| if (!this._isToolbarCustomizable()) |
| return true; |
| var visiblePanels = WebInspector.settings.visiblePanels.get(); |
| return visiblePanels.hasOwnProperty(name) ? visiblePanels[name] : this._isPanelVisibleByDefault(name); |
| }, |
| |
| /** |
| * @param {!string} name |
| * @param {boolean} visible |
| */ |
| _setPanelVisible: function(name, visible) |
| { |
| var visiblePanels = WebInspector.settings.visiblePanels.get(); |
| visiblePanels[name] = visible; |
| WebInspector.settings.visiblePanels.set(visiblePanels); |
| }, |
| |
| /** |
| * @param {!WebInspector.PanelDescriptor} panelDescriptor |
| */ |
| _hidePanel: function(panelDescriptor) |
| { |
| if (!this._isPanelVisible(panelDescriptor.name())) |
| return; |
| var switchToSibling = panelDescriptor._toolbarElement.nextSibling; |
| if (!switchToSibling || !switchToSibling.classList.contains("toggleable")) |
| switchToSibling = panelDescriptor._toolbarElement.previousSibling; |
| if (!switchToSibling || !switchToSibling.classList || !switchToSibling.classList.contains("toggleable")) |
| return; |
| this._setPanelVisible(panelDescriptor.name(), false); |
| this.element.removeChild(panelDescriptor._toolbarElement); |
| if (WebInspector.inspectorView.currentPanel().name === panelDescriptor.name()) { |
| for (var i = 0; i < this._panelDescriptors.length; ++i) { |
| var descr = this._panelDescriptors[i]; |
| if (descr._toolbarElement === switchToSibling) { |
| WebInspector.showPanel(descr.name()); |
| break; |
| } |
| } |
| } |
| this._updatePanelsMenuState(); |
| this.resize(); |
| }, |
| |
| _updatePanelsMenuState: function() |
| { |
| if (this._panelDescriptors.every(function (descr) { return this._isPanelVisible(descr.name()); }, this) && this._allItemsFitOntoToolbar()) |
| document.getElementById("toolbar-panels-menu").addStyleClass("disabled"); |
| else |
| document.getElementById("toolbar-panels-menu").removeStyleClass("disabled"); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _allItemsFitOntoToolbar: function() |
| { |
| var toolbarItems = this.element.querySelectorAll(".toolbar-item.toggleable"); |
| return toolbarItems.length === 0 || this.element.scrollHeight < toolbarItems[0].offsetHeight * 2; |
| }, |
| |
| /** |
| * @param {!WebInspector.PanelDescriptor} panelDescriptor |
| */ |
| _showPanel: function(panelDescriptor) |
| { |
| if (this._isPanelVisible(panelDescriptor.name())) |
| return; |
| this.element.appendChild(panelDescriptor._toolbarElement); |
| panelDescriptor._toolbarElement.removeStyleClass("hidden"); |
| this._setPanelVisible(panelDescriptor.name(), true); |
| this._updatePanelsMenuState(); |
| this.resize(); |
| }, |
| |
| /** |
| * @param {WebInspector.PanelDescriptor} panelDescriptor |
| * @param {boolean=} noCloseButton |
| * @return {Element} |
| */ |
| _createPanelToolbarItem: function(panelDescriptor, noCloseButton) |
| { |
| var toolbarItem = document.createElement("button"); |
| toolbarItem.className = "toolbar-item toggleable"; |
| toolbarItem.panelDescriptor = panelDescriptor; |
| toolbarItem.addStyleClass(panelDescriptor.name()); |
| |
| /** |
| * @param {Event} event |
| */ |
| function onContextMenuEvent(event) |
| { |
| var contextMenu = new WebInspector.ContextMenu(event); |
| contextMenu.appendItem(WebInspector.UIString("Close"), this._hidePanel.bind(this, panelDescriptor)); |
| contextMenu.show(); |
| } |
| if (!this._isDefaultPanel(panelDescriptor.name())) |
| toolbarItem.addEventListener("contextmenu", onContextMenuEvent.bind(this), true); |
| |
| function onToolbarItemClicked() |
| { |
| this._showPanel(panelDescriptor); |
| this._updateDropdownButtonAndHideDropdown(); |
| WebInspector.inspectorView.setCurrentPanel(panelDescriptor.panel()); |
| } |
| toolbarItem.addEventListener("click", onToolbarItemClicked.bind(this), false); |
| |
| function onToolbarItemCloseButtonClicked(event) |
| { |
| event.stopPropagation(); |
| this._hidePanel(panelDescriptor); |
| } |
| |
| function panelSelected() |
| { |
| if (WebInspector.inspectorView.currentPanel() && panelDescriptor.name() === WebInspector.inspectorView.currentPanel().name) |
| toolbarItem.addStyleClass("toggled-on"); |
| else |
| toolbarItem.removeStyleClass("toggled-on"); |
| } |
| WebInspector.inspectorView.addEventListener(WebInspector.InspectorView.Events.PanelSelected, panelSelected); |
| |
| toolbarItem.createChild("div", "toolbar-label").textContent = panelDescriptor.title(); |
| if (this._isToolbarCustomizable() && !this._isDefaultPanel(panelDescriptor.name()) && !noCloseButton) { |
| var closeButton = toolbarItem.createChild("div", "close-button"); |
| closeButton.addEventListener("click", onToolbarItemCloseButtonClicked.bind(this), false); |
| } |
| panelSelected(); |
| return toolbarItem; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _isDockedToBottom: function() |
| { |
| return !!WebInspector.dockController && WebInspector.dockController.dockSide() == WebInspector.DockController.State.DockedToBottom; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _isUndocked: function() |
| { |
| return !!WebInspector.dockController && WebInspector.dockController.dockSide() == WebInspector.DockController.State.Undocked; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _toolbarDragStart: function(event) |
| { |
| if (this._isUndocked()) |
| return false; |
| |
| var target = event.target; |
| if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable")) |
| return false; |
| |
| if (target !== this.element && !target.hasStyleClass("toolbar-item")) |
| return false; |
| |
| this._lastScreenX = event.screenX; |
| this._lastScreenY = event.screenY; |
| this._lastHeightDuringDrag = window.innerHeight; |
| this._startDistanceToRight = window.innerWidth - event.clientX; |
| this._startDinstanceToBottom = window.innerHeight - event.clientY; |
| return true; |
| }, |
| |
| _toolbarDragEnd: function(event) |
| { |
| // We may not get the drag event at the end. |
| // Apply last changes manually. |
| this._toolbarDrag(event); |
| delete this._lastScreenX; |
| delete this._lastScreenY; |
| delete this._lastHeightDuringDrag; |
| delete this._startDistanceToRight; |
| delete this._startDinstanceToBottom; |
| }, |
| |
| _toolbarDrag: function(event) |
| { |
| event.preventDefault(); |
| |
| if (this._isUndocked()) |
| return this._toolbarDragMoveWindow(event); |
| |
| return this._toolbarDragChangeDocking(event); |
| }, |
| |
| _toolbarDragMoveWindow: function(event) |
| { |
| var x = event.screenX - this._lastScreenX; |
| var y = event.screenY - this._lastScreenY; |
| this._lastScreenX = event.screenX; |
| this._lastScreenY = event.screenY; |
| InspectorFrontendHost.moveWindowBy(x, y); |
| }, |
| |
| _toolbarDragChangeDocking: function(event) |
| { |
| if (this._isDockedToBottom()) { |
| var distanceToRight = window.innerWidth - event.clientX; |
| if (distanceToRight < this._startDistanceToRight * 2 / 3) { |
| InspectorFrontendHost.requestSetDockSide(WebInspector.DockController.State.DockedToRight); |
| return true; |
| } |
| } else { |
| var distanceToBottom = window.innerHeight - event.clientY; |
| if (distanceToBottom < this._startDinstanceToBottom * 2 / 3) { |
| InspectorFrontendHost.requestSetDockSide(WebInspector.DockController.State.DockedToBottom); |
| return true; |
| } |
| } |
| }, |
| |
| _onClose: function() |
| { |
| WebInspector.close(); |
| }, |
| |
| _setDropdownVisible: function(visible) |
| { |
| if (!this._dropdown) { |
| if (!visible) |
| return; |
| this._dropdown = new WebInspector.ToolbarDropdown(this); |
| } |
| if (visible) |
| this._dropdown.show(); |
| else |
| this._dropdown.hide(); |
| }, |
| |
| _toggleDropdown: function() |
| { |
| this._setDropdownVisible(!this._dropdown || !this._dropdown.visible); |
| }, |
| |
| _togglePanelsMenu: function(event) |
| { |
| function activatePanel(panelDescriptor) |
| { |
| this._showPanel(panelDescriptor); |
| WebInspector.showPanel(panelDescriptor.name()); |
| } |
| |
| var contextMenu = new WebInspector.ContextMenu(event); |
| var currentPanelName = WebInspector.inspectorView.currentPanel().name; |
| var toolbarItems = this.element.querySelectorAll(".toolbar-item.toggleable"); |
| for (var i = 0; i < toolbarItems.length; ++i) { |
| if (toolbarItems[i].offsetTop >= toolbarItems[0].offsetHeight) { |
| var descr = toolbarItems[i].panelDescriptor; |
| if (descr.name() === currentPanelName) |
| contextMenu.appendCheckboxItem(descr.title(), activatePanel.bind(this, descr), true); |
| else |
| contextMenu.appendItem(descr.title(), activatePanel.bind(this, descr)); |
| } |
| } |
| contextMenu.appendSeparator(); |
| for (var i = 0; i < this._panelDescriptors.length; ++i) { |
| var descr = this._panelDescriptors[i]; |
| if (this._isPanelVisible(descr.name())) |
| continue; |
| contextMenu.appendItem(descr.title(), activatePanel.bind(this, descr)); |
| } |
| |
| contextMenu.showSoftMenu(); |
| }, |
| |
| _updateDropdownButtonAndHideDropdown: function() |
| { |
| WebInspector.invokeOnceAfterBatchUpdate(this, this._innerUpdateDropdownButtonAndHideDropdown); |
| }, |
| |
| _innerUpdateDropdownButtonAndHideDropdown: function() |
| { |
| if (this._isToolbarCustomizable()) { |
| this._updatePanelsMenuState(); |
| return; |
| } |
| this._setDropdownVisible(false); |
| |
| if (this.element.scrollHeight > this.element.offsetHeight) |
| this._dropdownButton.removeStyleClass("hidden"); |
| else |
| this._dropdownButton.addStyleClass("hidden"); |
| } |
| } |
| |
| /** |
| * @constructor |
| * @param {WebInspector.Toolbar} toolbar |
| */ |
| WebInspector.ToolbarDropdown = function(toolbar) |
| { |
| this._toolbar = toolbar; |
| this._arrow = document.getElementById("toolbar-dropdown-arrow"); |
| this.element = document.createElement("div"); |
| this.element.id = "toolbar-dropdown"; |
| this.element.className = "toolbar-small"; |
| this._contentElement = this.element.createChild("div", "scrollable-content"); |
| this._contentElement.tabIndex = 0; |
| this._contentElement.addEventListener("keydown", this._onKeyDown.bind(this), true); |
| } |
| |
| WebInspector.ToolbarDropdown.prototype = { |
| show: function() |
| { |
| if (this.visible) |
| return; |
| var style = this.element.style; |
| this._populate(); |
| var top = this._arrow.totalOffsetTop() + this._arrow.clientHeight; |
| this._arrow.addStyleClass("dropdown-visible"); |
| this.element.style.top = top + "px"; |
| this.element.style.right = window.innerWidth - this._arrow.totalOffsetLeft() - this._arrow.clientWidth + "px"; |
| this._contentElement.style.maxHeight = window.innerHeight - top - 20 + "px"; |
| this._toolbar.element.appendChild(this.element); |
| }, |
| |
| hide: function() |
| { |
| if (!this.visible) |
| return; |
| this._arrow.removeStyleClass("dropdown-visible"); |
| this.element.remove(); |
| this._contentElement.removeChildren(); |
| }, |
| |
| get visible() |
| { |
| return !!this.element.parentNode; |
| }, |
| |
| _populate: function() |
| { |
| var toolbarItems = this._toolbar.element.querySelectorAll(".toolbar-item.toggleable"); |
| |
| var needsSeparator = false; |
| for (var i = 0; i < toolbarItems.length; ++i) { |
| if (toolbarItems[i].offsetTop >= toolbarItems[0].offsetHeight) { |
| this._contentElement.appendChild(this._toolbar._createPanelToolbarItem(toolbarItems[i].panelDescriptor, true)); |
| needsSeparator = true; |
| } |
| } |
| |
| var panelDescriptors = this._toolbar._panelDescriptors; |
| for (var i = 0; i < panelDescriptors.length; ++i) { |
| var descr = panelDescriptors[i]; |
| if (this._toolbar._isPanelVisible(descr.name())) |
| continue; |
| if (needsSeparator) { |
| this._contentElement.createChild("div", "toolbar-items-separator"); |
| needsSeparator = false; |
| } |
| this._contentElement.appendChild(this._toolbar._createPanelToolbarItem(descr, true)); |
| } |
| }, |
| |
| _onKeyDown: function(event) |
| { |
| if (event.keyCode !== WebInspector.KeyboardShortcut.Keys.Esc.code) |
| return; |
| event.consume(); |
| this.hide(); |
| } |
| } |
| |
| /** |
| * @type {?WebInspector.Toolbar} |
| */ |
| WebInspector.toolbar = null; |