d92ab85ea454e02fab487df2e8ea820c27404bd6
[WebKit-https.git] / Source / WebCore / inspector / front-end / Toolbar.js
1  /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
3  * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
4  * Copyright (C) 2009 Joseph Pecoraro
5  * Copyright (C) 2011 Google Inc. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1.  Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  * 2.  Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
17  *     its contributors may be used to endorse or promote products derived
18  *     from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /**
33  * @constructor
34  */
35 WebInspector.Toolbar = function()
36 {
37     this.element = document.getElementById("toolbar");
38     WebInspector.installDragHandle(this.element, this._toolbarDragStart.bind(this), this._toolbarDrag.bind(this), this._toolbarDragEnd.bind(this), "default");
39
40     this._dropdownButton = document.getElementById("toolbar-dropdown-arrow");
41     this._dropdownButton.addEventListener("click", this._toggleDropdown.bind(this), false);
42
43     document.getElementById("close-button-left").addEventListener("click", this._onClose, true);
44     document.getElementById("close-button-right").addEventListener("click", this._onClose, true);
45 }
46
47 WebInspector.Toolbar.prototype = {
48     resize: function()
49     {
50         this._updateDropdownButtonAndHideDropdown();
51     },
52
53     /**
54      * @param {WebInspector.PanelDescriptor} panelDescriptor
55      */
56     addPanel: function(panelDescriptor)
57     {
58         this.element.appendChild(this._createPanelToolbarItem(panelDescriptor));
59         this.resize();
60     },
61
62     /**
63      * @param {WebInspector.PanelDescriptor} panelDescriptor
64      * @return {Element}
65      */
66     _createPanelToolbarItem: function(panelDescriptor)
67     {
68         var toolbarItem = document.createElement("button");
69         toolbarItem.className = "toolbar-item toggleable";
70         toolbarItem.panelDescriptor = panelDescriptor;
71         toolbarItem.addStyleClass(panelDescriptor.name());
72
73         function onToolbarItemClicked()
74         {
75             this._updateDropdownButtonAndHideDropdown();
76             WebInspector.inspectorView.setCurrentPanel(panelDescriptor.panel());
77         }
78         toolbarItem.addEventListener("click", onToolbarItemClicked.bind(this), false);
79
80         function panelSelected()
81         {
82             if (WebInspector.inspectorView.currentPanel() && panelDescriptor.name() === WebInspector.inspectorView.currentPanel().name)
83                 toolbarItem.addStyleClass("toggled-on");
84             else
85                 toolbarItem.removeStyleClass("toggled-on");
86         }
87         WebInspector.inspectorView.addEventListener(WebInspector.InspectorView.Events.PanelSelected, panelSelected);
88
89         var iconElement = toolbarItem.createChild("div", "toolbar-icon");
90         toolbarItem.createChild("div", "toolbar-label").textContent = panelDescriptor.title();
91         if (panelDescriptor.iconURL()) {
92             iconElement.addStyleClass("custom-toolbar-icon");
93             iconElement.style.backgroundImage = "url(" + panelDescriptor.iconURL() + ")";
94         }
95         panelSelected();
96         return toolbarItem;
97     },
98
99     /**
100      * @return {boolean}
101      */
102     _isDockedToBottom: function()
103     {
104         return !!WebInspector.dockController && WebInspector.dockController.isDockedToBottom();
105     },
106
107     /**
108      * @return {boolean}
109      */
110     _toolbarDragStart: function(event)
111     {
112         if ((!this._isDockedToBottom() && WebInspector.platformFlavor() !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor() !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port() == "qt")
113             return false;
114
115         var target = event.target;
116         if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
117             return false;
118
119         if (target !== this.element && !target.hasStyleClass("toolbar-item"))
120             return false;
121
122         this.element.lastScreenX = event.screenX;
123         this.element.lastScreenY = event.screenY;
124         this._lastHeightDuringDrag = window.innerHeight;
125         return true;
126     },
127
128     _toolbarDragEnd: function(event)
129     {
130         // We may not get the drag event at the end.
131         // Apply last changes manually.
132         this._toolbarDrag(event);
133         delete this.element.lastScreenX;
134         delete this.element.lastScreenY;
135         delete this._lastHeightDuringDrag;
136     },
137
138     _toolbarDrag: function(event)
139     {
140         if (this._isDockedToBottom()) {
141             var height = this._lastHeightDuringDrag - (event.screenY - this.element.lastScreenY);
142             this._lastHeightDuringDrag = height;
143
144             InspectorFrontendHost.setAttachedWindowHeight(height);
145         } else {
146             var x = event.screenX - this.element.lastScreenX;
147             var y = event.screenY - this.element.lastScreenY;
148
149             // We cannot call window.moveBy here because it restricts the movement
150             // of the window at the edges.
151             InspectorFrontendHost.moveWindowBy(x, y);
152         }
153
154         this.element.lastScreenX = event.screenX;
155         this.element.lastScreenY = event.screenY;
156
157         event.preventDefault();
158     },
159
160     _onClose: function()
161     {
162         WebInspector.close();
163     },
164
165     _setDropdownVisible: function(visible)
166     {
167         if (!this._dropdown) {
168             if (!visible)
169                 return;
170             this._dropdown = new WebInspector.ToolbarDropdown(this);
171         }
172         if (visible)
173             this._dropdown.show();
174         else
175             this._dropdown.hide();
176     },
177
178     _toggleDropdown: function()
179     {
180         this._setDropdownVisible(!this._dropdown || !this._dropdown.visible);
181     },
182
183     _updateDropdownButtonAndHideDropdown: function()
184     {
185         WebInspector.invokeOnceAfterBatchUpdate(this, this._innerUpdateDropdownButtonAndHideDropdown);
186     },
187
188     _innerUpdateDropdownButtonAndHideDropdown: function()
189     {
190         this._setDropdownVisible(false);
191
192         if (this.element.scrollHeight > this.element.offsetHeight)
193             this._dropdownButton.removeStyleClass("hidden");
194         else
195             this._dropdownButton.addStyleClass("hidden");
196     }
197 }
198
199 /**
200  * @constructor
201  * @param {WebInspector.Toolbar} toolbar
202  */
203 WebInspector.ToolbarDropdown = function(toolbar)
204 {
205     this._toolbar = toolbar;
206     this._arrow = document.getElementById("toolbar-dropdown-arrow");
207     this.element = document.createElement("div");
208     this.element.id = "toolbar-dropdown";
209     this.element.className = "toolbar-small";
210     this._contentElement = this.element.createChild("div", "scrollable-content");
211     this._contentElement.tabIndex = 0;
212     this._contentElement.addEventListener("keydown", this._onKeyDown.bind(this), true);
213 }
214
215 WebInspector.ToolbarDropdown.prototype = {
216     show: function()
217     {
218         if (this.visible)
219             return;
220         var style = this.element.style;
221         this._populate();
222         var top = this._arrow.totalOffsetTop() + this._arrow.clientHeight;
223         this._arrow.addStyleClass("dropdown-visible");
224         this.element.style.top = top + "px";
225         this.element.style.right = window.innerWidth - this._arrow.totalOffsetLeft() - this._arrow.clientWidth + "px";
226         this._contentElement.style.maxHeight = window.innerHeight - top - 20 + "px";
227         this._toolbar.element.appendChild(this.element);
228     },
229
230     hide: function()
231     {
232         if (!this.visible)
233             return;
234         this._arrow.removeStyleClass("dropdown-visible");
235         this.element.parentNode.removeChild(this.element);
236         this._contentElement.removeChildren();
237     },
238
239     get visible()
240     {
241         return !!this.element.parentNode;
242     },
243
244     _populate: function()
245     {
246         var toolbarItems = this._toolbar.element.querySelectorAll(".toolbar-item.toggleable");
247
248         for (var i = 0; i < toolbarItems.length; ++i) {
249             if (toolbarItems[i].offsetTop > 1)
250                 this._contentElement.appendChild(this._toolbar._createPanelToolbarItem(toolbarItems[i].panelDescriptor));
251         }
252     },
253
254     _onKeyDown: function(event)
255     {
256         if (event.keyCode !== WebInspector.KeyboardShortcut.Keys.Esc.code)
257             return;
258         event.consume();
259         this.hide();
260     }
261 }
262
263 /**
264  * @type {?WebInspector.Toolbar}
265  */
266 WebInspector.toolbar = null;