2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * @extends {WebInspector.VBox}
35 WebInspector.InspectorView = function()
37 WebInspector.VBox.call(this);
38 WebInspector.Dialog.setModalHostView(this);
39 WebInspector.GlassPane.DefaultFocusedViewStack.push(this);
40 this.setMinimumSize(180, 72);
42 // DevTools sidebar is a vertical split of panels tabbed pane and a drawer.
43 this._drawerSplitView = new WebInspector.SplitView(false, true, "Inspector.drawerSplitViewState", 200, 200);
44 this._drawerSplitView.hideSidebar();
45 this._drawerSplitView.enableShowModeSaving();
46 this._drawerSplitView.show(this.element);
48 this._tabbedPane = new WebInspector.TabbedPane();
49 this._tabbedPane.setRetainTabOrder(true, self.runtime.orderComparator(WebInspector.Panel, "name", "order"));
50 this._tabbedPane.show(this._drawerSplitView.mainElement());
51 this._drawer = new WebInspector.Drawer(this._drawerSplitView);
53 // Patch tabbed pane header with toolbar actions.
54 this._toolbarElement = document.createElement("div");
55 this._toolbarElement.className = "toolbar toolbar-background toolbar-colors";
56 var headerElement = this._tabbedPane.headerElement();
57 headerElement.parentElement.insertBefore(this._toolbarElement, headerElement);
59 this._leftToolbarElement = this._toolbarElement.createChild("div", "toolbar-controls-left");
60 this._toolbarElement.appendChild(headerElement);
61 this._rightToolbarElement = this._toolbarElement.createChild("div", "toolbar-controls-right");
62 this._toolbarItems = [];
64 this._closeButtonToolbarItem = document.createElementWithClass("div", "toolbar-close-button-item");
65 var closeButtonElement = this._closeButtonToolbarItem.createChild("div", "close-button");
66 closeButtonElement.addEventListener("click", InspectorFrontendHost.closeWindow.bind(InspectorFrontendHost), true);
67 this._rightToolbarElement.appendChild(this._closeButtonToolbarItem);
71 WebInspector["panels"] = this._panels;
74 this._historyIterator = -1;
75 document.addEventListener("keydown", this._keyDown.bind(this), false);
76 document.addEventListener("keypress", this._keyPress.bind(this), false);
77 this._panelDescriptors = {};
79 // Windows and Mac have two different definitions of '[' and ']', so accept both of each.
80 this._openBracketIdentifiers = ["U+005B", "U+00DB"].keySet();
81 this._closeBracketIdentifiers = ["U+005D", "U+00DD"].keySet();
82 this._lastActivePanelSetting = WebInspector.settings.createSetting("lastActivePanel", "elements");
84 // FIXME(399531): enable timelineOnTraceEvents experiment when running layout tests under inspector/tracing/. This code
85 // should be removed along with the old Timeline implementation once we move tracing based Timeline out of experimental.
86 if ("tracing" === this._lastActivePanelSetting.get()) {
87 Runtime.experiments.setEnabled("timelineOnTraceEvents", true);
88 this._lastActivePanelSetting.set("timeline");
91 this._loadPanelDesciptors();
93 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ShowConsole, this.showPanel.bind(this, "console"));
96 WebInspector.InspectorView.prototype = {
97 _loadPanelDesciptors: function()
99 WebInspector.startBatchUpdate();
100 self.runtime.extensions(WebInspector.Panel).forEach(processPanelExtensions.bind(this));
102 * @param {!Runtime.Extension} extension
103 * @this {!WebInspector.InspectorView}
105 function processPanelExtensions(extension)
107 this.addPanel(new WebInspector.RuntimeExtensionPanelDescriptor(extension));
109 WebInspector.endBatchUpdate();
113 * @param {!WebInspector.StatusBarItem} item
115 appendToLeftToolbar: function(item)
117 this._toolbarItems.push(item);
118 this._leftToolbarElement.appendChild(item.element);
122 * @param {!WebInspector.StatusBarItem} item
124 appendToRightToolbar: function(item)
126 this._toolbarItems.push(item);
127 this._rightToolbarElement.insertBefore(item.element, this._closeButtonToolbarItem);
131 * @param {!WebInspector.PanelDescriptor} panelDescriptor
133 addPanel: function(panelDescriptor)
135 var panelName = panelDescriptor.name();
136 this._panelDescriptors[panelName] = panelDescriptor;
137 this._tabbedPane.appendTab(panelName, panelDescriptor.title(), new WebInspector.View());
138 if (this._lastActivePanelSetting.get() === panelName)
139 this._tabbedPane.selectTab(panelName);
143 * @param {string} panelName
146 hasPanel: function(panelName)
148 return !!this._panelDescriptors[panelName];
152 * @param {string} panelName
153 * @return {?WebInspector.Panel}
155 panel: function(panelName)
157 var panelDescriptor = this._panelDescriptors[panelName];
158 var panelOrder = this._tabbedPane.allTabs();
159 if (!panelDescriptor && panelOrder.length)
160 panelDescriptor = this._panelDescriptors[panelOrder[0]];
161 var panel = panelDescriptor ? panelDescriptor.panel() : null;
163 this._panels[panelName] = panel;
168 * @param {boolean} locked
170 setCurrentPanelLocked: function(locked)
172 this._currentPanelLocked = locked;
173 this._tabbedPane.setCurrentTabLocked(locked);
174 for (var i = 0; i < this._toolbarItems.length; ++i)
175 this._toolbarItems[i].setEnabled(!locked);
179 * @param {string} panelName
180 * @return {?WebInspector.Panel}
182 showPanel: function(panelName)
184 if (this._currentPanelLocked)
185 return this._currentPanel === this._panels[panelName] ? this._currentPanel : null;
187 var panel = this.panel(panelName);
189 this.setCurrentPanel(panel);
194 * @return {!WebInspector.Panel}
196 currentPanel: function()
198 return this._currentPanel;
201 showInitialPanel: function()
203 this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
205 this._drawer.initialPanelShown();
208 _tabSelected: function()
210 var panelName = this._tabbedPane.selectedTabId;
213 var panel = this._panelDescriptors[this._tabbedPane.selectedTabId].panel();
214 this._panels[panelName] = panel;
215 this._tabbedPane.changeTabView(panelName, panel);
217 this._currentPanel = panel;
218 this._lastActivePanelSetting.set(panel.name);
219 this._pushToHistory(panel.name);
220 WebInspector.userMetrics.panelShown(panel.name);
225 * @param {!WebInspector.Panel} x
227 setCurrentPanel: function(x)
229 if (this._currentPanelLocked)
231 InspectorFrontendHost.bringToFront();
232 if (this._currentPanel === x)
235 this._tabbedPane.changeTabView(x.name, x);
236 this._tabbedPane.selectTab(x.name);
242 closeViewInDrawer: function(id)
244 this._drawer.closeView(id);
249 * @param {string} title
250 * @param {!WebInspector.View} view
252 showCloseableViewInDrawer: function(id, title, view)
254 this._drawer.showCloseableView(id, title, view);
257 showDrawer: function()
259 this._drawer.showDrawer();
265 drawerVisible: function()
267 return this._drawer.isShowing();
272 * @param {boolean=} immediate
274 showViewInDrawer: function(id, immediate)
276 this._drawer.showView(id, immediate);
282 selectedViewInDrawer: function()
284 return this._drawer.selectedViewId();
287 closeDrawer: function()
289 this._drawer.closeDrawer();
295 defaultFocusedElement: function()
297 return this._currentPanel ? this._currentPanel.defaultFocusedElement() : null;
300 _keyPress: function(event)
302 // BUG 104250: Windows 7 posts a WM_CHAR message upon the Ctrl+']' keypress.
303 // Any charCode < 32 is not going to be a valid keypress.
304 if (event.charCode < 32 && WebInspector.isWin())
306 clearTimeout(this._keyDownTimer);
307 delete this._keyDownTimer;
310 _keyDown: function(event)
312 if (!WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event))
315 var keyboardEvent = /** @type {!KeyboardEvent} */ (event);
316 // Ctrl/Cmd + 1-9 should show corresponding panel.
317 var panelShortcutEnabled = WebInspector.settings.shortcutPanelSwitch.get();
318 if (panelShortcutEnabled && !event.shiftKey && !event.altKey) {
320 if (event.keyCode > 0x30 && event.keyCode < 0x3A)
321 panelIndex = event.keyCode - 0x31;
322 else if (event.keyCode > 0x60 && event.keyCode < 0x6A && keyboardEvent.location === KeyboardEvent.DOM_KEY_LOCATION_NUMPAD)
323 panelIndex = event.keyCode - 0x61;
324 if (panelIndex !== -1) {
325 var panelName = this._tabbedPane.allTabs()[panelIndex];
327 if (!WebInspector.Dialog.currentInstance() && !this._currentPanelLocked)
328 this.showPanel(panelName);
335 // BUG85312: On French AZERTY keyboards, AltGr-]/[ combinations (synonymous to Ctrl-Alt-]/[ on Windows) are used to enter ]/[,
336 // so for a ]/[-related keydown we delay the panel switch using a timer, to see if there is a keypress event following this one.
337 // If there is, we cancel the timer and do not consider this a panel switch.
338 if (!WebInspector.isWin() || (!this._openBracketIdentifiers[event.keyIdentifier] && !this._closeBracketIdentifiers[event.keyIdentifier])) {
339 this._keyDownInternal(event);
343 this._keyDownTimer = setTimeout(this._keyDownInternal.bind(this, event), 0);
346 _keyDownInternal: function(event)
348 if (this._currentPanelLocked)
353 if (this._openBracketIdentifiers[event.keyIdentifier])
356 if (this._closeBracketIdentifiers[event.keyIdentifier])
362 if (!event.shiftKey && !event.altKey) {
363 if (!WebInspector.Dialog.currentInstance())
364 this._changePanelInDirection(direction);
369 if (event.altKey && this._moveInHistory(direction))
373 _changePanelInDirection: function(direction)
375 var panelOrder = this._tabbedPane.allTabs();
376 var index = panelOrder.indexOf(this.currentPanel().name);
377 index = (index + panelOrder.length + direction) % panelOrder.length;
378 this.showPanel(panelOrder[index]);
381 _moveInHistory: function(move)
383 var newIndex = this._historyIterator + move;
384 if (newIndex >= this._history.length || newIndex < 0)
387 this._inHistory = true;
388 this._historyIterator = newIndex;
389 if (!WebInspector.Dialog.currentInstance())
390 this.setCurrentPanel(this._panels[this._history[this._historyIterator]]);
391 delete this._inHistory;
396 _pushToHistory: function(panelName)
401 this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1);
402 if (!this._history.length || this._history[this._history.length - 1] !== panelName)
403 this._history.push(panelName);
404 this._historyIterator = this._history.length - 1;
409 WebInspector.Dialog.modalHostRepositioned();
415 topResizerElement: function()
417 return this._tabbedPane.headerElement();
420 toolbarItemResized: function()
422 this._tabbedPane.headerResized();
425 __proto__: WebInspector.VBox.prototype
429 * @type {!WebInspector.InspectorView}
431 WebInspector.inspectorView;
435 * @implements {WebInspector.ActionDelegate}
437 WebInspector.InspectorView.DrawerToggleActionDelegate = function()
441 WebInspector.InspectorView.DrawerToggleActionDelegate.prototype = {
445 handleAction: function()
447 if (WebInspector.inspectorView.drawerVisible()) {
448 WebInspector.inspectorView.closeDrawer();
451 WebInspector.inspectorView.showDrawer();
458 * @implements {WebInspector.StatusBarItem.Provider}
460 WebInspector.InspectorView.ToggleDrawerButtonProvider = function()
464 WebInspector.InspectorView.ToggleDrawerButtonProvider.prototype = {
466 * @return {?WebInspector.StatusBarItem}
470 return WebInspector.inspectorView._drawer.toggleButton();