- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / InspectorView.js
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 /**
32  * @constructor
33  * @extends {WebInspector.View}
34  */
35 WebInspector.InspectorView = function()
36 {
37     WebInspector.View.call(this);
38     this.markAsRoot();
39     this.element.classList.add("fill", "vbox");
40     this.element.setAttribute("spellcheck", false);
41
42     this._tabbedPane = new WebInspector.TabbedPane();
43     this._tabbedPane.setRetainTabsOrder(true);
44     this._tabbedPane.show(this.element);
45
46     var toolbarElement = document.createElement("div");
47     toolbarElement.className = "toolbar toolbar-background";
48     var headerElement = this._tabbedPane.headerElement();
49     headerElement.parentElement.insertBefore(toolbarElement, headerElement);
50
51     this._leftToolbarElement = toolbarElement.createChild("div", "toolbar-controls-left");
52     toolbarElement.appendChild(headerElement);
53     this._rightToolbarElement = toolbarElement.createChild("div", "toolbar-controls-right");
54
55     this._errorWarningCountElement = this._rightToolbarElement.createChild("div", "hidden");
56     this._errorWarningCountElement.id = "error-warning-count";
57
58     this._footerElementContainer = this.element.createChild("div", "inspector-footer status-bar hidden");
59
60     this._drawer = new WebInspector.Drawer(this);
61     this.appendToRightToolbar(this._drawer.toggleButtonElement());
62
63     this._history = [];
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 = {};
68
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");
73 }
74
75 WebInspector.InspectorView.prototype = {
76     /**
77      * @param {Element} element
78      */
79     appendToLeftToolbar: function(element)
80     {
81         this._leftToolbarElement.appendChild(element);
82     },
83
84     /**
85      * @param {Element} element
86      */
87     appendToRightToolbar: function(element)
88     {
89         this._rightToolbarElement.appendChild(element);
90     },
91
92     /**
93      * @return {WebInspector.Drawer}
94      */
95     drawer: function()
96     {
97         return this._drawer;
98     },
99
100     /**
101      * @param {WebInspector.PanelDescriptor} panelDescriptor
102      */
103     addPanel: function(panelDescriptor)
104     {
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);
110     },
111
112     /**
113      * @param {string} panelName
114      * @return {?WebInspector.Panel}
115      */
116     panel: function(panelName)
117     {
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;
123     },
124
125     /**
126      * @param {string} panelName
127      * @return {?WebInspector.Panel}
128      */
129     showPanel: function(panelName)
130     {
131         var panel = this.panel(panelName);
132         if (panel)
133             this.setCurrentPanel(panel);
134         return panel;
135     },
136
137     /**
138      * @return {WebInspector.Panel}
139      */
140     currentPanel: function()
141     {
142         return this._currentPanel;
143     },
144
145     /**
146      * @return {WebInspector.Searchable}
147      */
148     getSearchProvider: function()
149     {
150         return this._currentPanel && this._currentPanel.canSearch() ? this._currentPanel : null;
151     },
152
153     showInitialPanel: function()
154     {
155         this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
156         this._tabSelected();
157     },
158
159     _tabSelected: function()
160     {
161         // FIXME: remove search controller.
162         WebInspector.searchController.cancelSearch();
163
164         var panelName = this._tabbedPane.selectedTabId;
165         var panel = this._panelDescriptors[this._tabbedPane.selectedTabId].panel();
166         this._tabbedPane.changeTabView(panelName, panel);
167
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);
173         panel.focus();
174     },
175
176     /**
177      * @param {WebInspector.Panel} x
178      */
179     setCurrentPanel: function(x)
180     {
181         if (this._currentPanel === x)
182             return;
183
184         this._tabbedPane.changeTabView(x.name, x);
185         this._tabbedPane.selectTab(x.name);
186     },
187
188     /**
189      * @param {string} id
190      */
191     closeViewInDrawer: function(id)
192     {
193         return this._drawer.closeView(id);
194     },
195
196     /**
197      * @param {string} id
198      * @param {string} title
199      * @param {WebInspector.View} view
200      */
201     showCloseableViewInDrawer: function(id, title, view)
202     {
203         this._drawer.showCloseableView(id, title, view);
204     },
205
206     /**
207      * @param {string} id
208      * @param {string} title
209      * @param {WebInspector.ViewFactory} factory
210      */
211     registerViewInDrawer: function(id, title, factory)
212     {
213         this._drawer.registerView(id, title, factory);
214     },
215
216     /**
217      * @param {string} id
218      */
219     unregisterViewInDrawer: function(id)
220     {
221         this._drawer.unregisterView(id);
222     },
223
224     /**
225      * @param {string} id
226      */
227     showViewInDrawer: function(id)
228     {
229         this._drawer.showView(id);
230     },
231
232     closeDrawer: function()
233     {
234         this._drawer.hide();
235     },
236
237     /**
238      * @return {Element}
239      */
240     defaultFocusedElement: function()
241     {
242         return this._currentPanel ? this._currentPanel.defaultFocusedElement() : null;
243     },
244
245     _keyPress: function(event)
246     {
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())
250             return;
251         clearTimeout(this._keyDownTimer);
252         delete this._keyDownTimer;
253     },
254
255     _keyDown: function(event)
256     {
257         if (!WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event))
258             return;
259
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];
264             if (panelName) {
265                 this.showPanel(panelName);
266                 event.consume(true);
267             }
268             return;
269         }
270
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);
276             return;
277         }
278
279         this._keyDownTimer = setTimeout(this._keyDownInternal.bind(this, event), 0);
280     },
281
282     _keyDownInternal: function(event)
283     {
284         if (this._openBracketIdentifiers[event.keyIdentifier]) {
285             var isRotateLeft = !event.shiftKey && !event.altKey;
286             if (isRotateLeft) {
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]);
291                 event.consume(true);
292                 return;
293             }
294
295             var isGoBack = event.altKey;
296             if (isGoBack && this._canGoBackInHistory()) {
297                 this._goBackInHistory();
298                 event.consume(true);
299             }
300             return;
301         }
302
303         if (this._closeBracketIdentifiers[event.keyIdentifier]) {
304             var isRotateRight = !event.shiftKey && !event.altKey;
305             if (isRotateRight) {
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]);
310                 event.consume(true);
311                 return;
312             }
313
314             var isGoForward = event.altKey;
315             if (isGoForward && this._canGoForwardInHistory()) {
316                 this._goForwardInHistory();
317                 event.consume(true);
318             }
319             return;
320         }
321     },
322
323     _canGoBackInHistory: function()
324     {
325         return this._historyIterator > 0;
326     },
327
328     _goBackInHistory: function()
329     {
330         this._inHistory = true;
331         this.setCurrentPanel(WebInspector.panels[this._history[--this._historyIterator]]);
332         delete this._inHistory;
333     },
334
335     _canGoForwardInHistory: function()
336     {
337         return this._historyIterator < this._history.length - 1;
338     },
339
340     _goForwardInHistory: function()
341     {
342         this._inHistory = true;
343         this.setCurrentPanel(WebInspector.panels[this._history[++this._historyIterator]]);
344         delete this._inHistory;
345     },
346
347     _pushToHistory: function(panelName)
348     {
349         if (this._inHistory)
350             return;
351
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;
356     },
357
358     /**
359      * @param {?Element} element
360      */
361     setFooterElement: function(element)
362     {
363         if (this._currentPanel && this._currentPanel.canSetFooterElement()) {
364             this._currentPanel.setFooterElement(element);
365             return;
366         }
367         if (element) {
368             this._footerElementContainer.removeStyleClass("hidden");
369             this._footerElementContainer.appendChild(element);
370         } else {
371             this._footerElementContainer.addStyleClass("hidden");
372             this._footerElementContainer.removeChildren();
373         }
374         this.doResize();
375     },
376
377     onResize: function()
378     {
379         // FIXME: make drawer a view.
380         this.doResize();
381         this._drawer.resize();
382     },
383
384     __proto__: WebInspector.View.prototype
385 }
386
387 /**
388  * @type {WebInspector.InspectorView}
389  */
390 WebInspector.inspectorView = null;