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.View}
35 WebInspector.InspectorView = function()
37 WebInspector.View.call(this);
39 this.element.classList.add("fill", "vbox");
40 this.element.setAttribute("spellcheck", false);
42 this._tabbedPane = new WebInspector.TabbedPane();
43 this._tabbedPane.setRetainTabsOrder(true);
44 this._tabbedPane.show(this.element);
46 var toolbarElement = document.createElement("div");
47 toolbarElement.className = "toolbar toolbar-background";
48 var headerElement = this._tabbedPane.headerElement();
49 headerElement.parentElement.insertBefore(toolbarElement, headerElement);
51 this._leftToolbarElement = toolbarElement.createChild("div", "toolbar-controls-left");
52 toolbarElement.appendChild(headerElement);
53 this._rightToolbarElement = toolbarElement.createChild("div", "toolbar-controls-right");
55 this._errorWarningCountElement = this._rightToolbarElement.createChild("div", "hidden");
56 this._errorWarningCountElement.id = "error-warning-count";
58 this._footerElementContainer = this.element.createChild("div", "inspector-footer status-bar hidden");
60 this._drawer = new WebInspector.Drawer(this);
61 this.appendToRightToolbar(this._drawer.toggleButtonElement());
64 this._historyIterator = -1;
65 document.addEventListener("keydown", this._keyDown.bind(this), false);
66 document.addEventListener("keypress", this._keyPress.bind(this), false);
67 this._panelDescriptors = {};
69 // Windows and Mac have two different definitions of '[' and ']', so accept both of each.
70 this._openBracketIdentifiers = ["U+005B", "U+00DB"].keySet();
71 this._closeBracketIdentifiers = ["U+005D", "U+00DD"].keySet();
72 this._lastActivePanelSetting = WebInspector.settings.createSetting("lastActivePanel", "elements");
75 WebInspector.InspectorView.prototype = {
77 * @param {Element} element
79 appendToLeftToolbar: function(element)
81 this._leftToolbarElement.appendChild(element);
85 * @param {Element} element
87 appendToRightToolbar: function(element)
89 this._rightToolbarElement.appendChild(element);
93 * @return {WebInspector.Drawer}
101 * @param {WebInspector.PanelDescriptor} panelDescriptor
103 addPanel: function(panelDescriptor)
105 var panelName = panelDescriptor.name();
106 this._panelDescriptors[panelName] = panelDescriptor;
107 this._tabbedPane.appendTab(panelName, panelDescriptor.title(), new WebInspector.View());
108 if (this._lastActivePanelSetting.get() === panelName)
109 this._tabbedPane.selectTab(panelName);
113 * @param {string} panelName
114 * @return {?WebInspector.Panel}
116 panel: function(panelName)
118 var panelDescriptor = this._panelDescriptors[panelName];
119 var panelOrder = this._tabbedPane.allTabs();
120 if (!panelDescriptor && panelOrder.length)
121 panelDescriptor = this._panelDescriptors[panelOrder[0]];
122 return panelDescriptor ? panelDescriptor.panel() : null;
126 * @param {string} panelName
127 * @return {?WebInspector.Panel}
129 showPanel: function(panelName)
131 var panel = this.panel(panelName);
133 this.setCurrentPanel(panel);
138 * @return {WebInspector.Panel}
140 currentPanel: function()
142 return this._currentPanel;
146 * @return {WebInspector.Searchable}
148 getSearchProvider: function()
150 return this._currentPanel && this._currentPanel.canSearch() ? this._currentPanel : null;
153 showInitialPanel: function()
155 this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
159 _tabSelected: function()
161 // FIXME: remove search controller.
162 WebInspector.searchController.cancelSearch();
164 var panelName = this._tabbedPane.selectedTabId;
165 var panel = this._panelDescriptors[this._tabbedPane.selectedTabId].panel();
166 this._tabbedPane.changeTabView(panelName, panel);
168 this._drawer.panelSelected(panel);
169 this._currentPanel = panel;
170 this._lastActivePanelSetting.set(panel.name);
171 this._pushToHistory(panel.name);
172 WebInspector.userMetrics.panelShown(panel.name);
177 * @param {WebInspector.Panel} x
179 setCurrentPanel: function(x)
181 if (this._currentPanel === x)
184 this._tabbedPane.changeTabView(x.name, x);
185 this._tabbedPane.selectTab(x.name);
191 closeViewInDrawer: function(id)
193 return this._drawer.closeView(id);
198 * @param {string} title
199 * @param {WebInspector.View} view
201 showCloseableViewInDrawer: function(id, title, view)
203 this._drawer.showCloseableView(id, title, view);
208 * @param {string} title
209 * @param {WebInspector.ViewFactory} factory
211 registerViewInDrawer: function(id, title, factory)
213 this._drawer.registerView(id, title, factory);
219 unregisterViewInDrawer: function(id)
221 this._drawer.unregisterView(id);
227 showViewInDrawer: function(id)
229 this._drawer.showView(id);
232 closeDrawer: function()
240 defaultFocusedElement: function()
242 return this._currentPanel ? this._currentPanel.defaultFocusedElement() : null;
245 _keyPress: function(event)
247 // BUG 104250: Windows 7 posts a WM_CHAR message upon the Ctrl+']' keypress.
248 // Any charCode < 32 is not going to be a valid keypress.
249 if (event.charCode < 32 && WebInspector.isWin())
251 clearTimeout(this._keyDownTimer);
252 delete this._keyDownTimer;
255 _keyDown: function(event)
257 if (!WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event))
260 // Ctrl/Cmd + 1-9 should show corresponding panel.
261 var panelShortcutEnabled = WebInspector.settings.shortcutPanelSwitch.get();
262 if (panelShortcutEnabled && !event.shiftKey && !event.altKey && event.keyCode > 0x30 && event.keyCode < 0x3A) {
263 var panelName = this._tabbedPane.allTabs()[event.keyCode - 0x31];
265 this.showPanel(panelName);
271 // BUG85312: On French AZERTY keyboards, AltGr-]/[ combinations (synonymous to Ctrl-Alt-]/[ on Windows) are used to enter ]/[,
272 // so for a ]/[-related keydown we delay the panel switch using a timer, to see if there is a keypress event following this one.
273 // If there is, we cancel the timer and do not consider this a panel switch.
274 if (!WebInspector.isWin() || (!this._openBracketIdentifiers[event.keyIdentifier] && !this._closeBracketIdentifiers[event.keyIdentifier])) {
275 this._keyDownInternal(event);
279 this._keyDownTimer = setTimeout(this._keyDownInternal.bind(this, event), 0);
282 _keyDownInternal: function(event)
284 if (this._openBracketIdentifiers[event.keyIdentifier]) {
285 var isRotateLeft = !event.shiftKey && !event.altKey;
287 var panelOrder = this._tabbedPane.allTabs();
288 var index = panelOrder.indexOf(this.currentPanel().name);
289 index = (index === 0) ? panelOrder.length - 1 : index - 1;
290 this.showPanel(panelOrder[index]);
295 var isGoBack = event.altKey;
296 if (isGoBack && this._canGoBackInHistory()) {
297 this._goBackInHistory();
303 if (this._closeBracketIdentifiers[event.keyIdentifier]) {
304 var isRotateRight = !event.shiftKey && !event.altKey;
306 var panelOrder = this._tabbedPane.allTabs();
307 var index = panelOrder.indexOf(this.currentPanel().name);
308 index = (index + 1) % panelOrder.length;
309 this.showPanel(panelOrder[index]);
314 var isGoForward = event.altKey;
315 if (isGoForward && this._canGoForwardInHistory()) {
316 this._goForwardInHistory();
323 _canGoBackInHistory: function()
325 return this._historyIterator > 0;
328 _goBackInHistory: function()
330 this._inHistory = true;
331 this.setCurrentPanel(WebInspector.panels[this._history[--this._historyIterator]]);
332 delete this._inHistory;
335 _canGoForwardInHistory: function()
337 return this._historyIterator < this._history.length - 1;
340 _goForwardInHistory: function()
342 this._inHistory = true;
343 this.setCurrentPanel(WebInspector.panels[this._history[++this._historyIterator]]);
344 delete this._inHistory;
347 _pushToHistory: function(panelName)
352 this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1);
353 if (!this._history.length || this._history[this._history.length - 1] !== panelName)
354 this._history.push(panelName);
355 this._historyIterator = this._history.length - 1;
359 * @param {?Element} element
361 setFooterElement: function(element)
363 if (this._currentPanel && this._currentPanel.canSetFooterElement()) {
364 this._currentPanel.setFooterElement(element);
368 this._footerElementContainer.removeStyleClass("hidden");
369 this._footerElementContainer.appendChild(element);
371 this._footerElementContainer.addStyleClass("hidden");
372 this._footerElementContainer.removeChildren();
379 // FIXME: make drawer a view.
381 this._drawer.resize();
384 __proto__: WebInspector.View.prototype
388 * @type {WebInspector.InspectorView}
390 WebInspector.inspectorView = null;