1/* 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2009 Joseph Pecoraro 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/** 31 * @constructor 32 * @extends {WebInspector.VBox} 33 * @param {!WebInspector.SplitView} splitView 34 */ 35WebInspector.Drawer = function(splitView) 36{ 37 WebInspector.VBox.call(this); 38 this.element.id = "drawer-contents"; 39 40 this._splitView = splitView; 41 splitView.hideDefaultResizer(); 42 this.show(splitView.sidebarElement()); 43 44 this._drawerEditorSplitView = new WebInspector.SplitView(true, true, "editorInDrawerSplitViewState", 0.5, 0.5); 45 this._drawerEditorSplitView.hideSidebar(); 46 this._drawerEditorSplitView.addEventListener(WebInspector.SplitView.Events.ShowModeChanged, this._drawerEditorSplitViewShowModeChanged, this); 47 this._drawerEditorShownSetting = WebInspector.settings.createSetting("drawerEditorShown", true); 48 this._drawerEditorSplitView.show(this.element); 49 50 this._toggleDrawerButton = new WebInspector.StatusBarButton(WebInspector.UIString("Show drawer."), "console-status-bar-item"); 51 this._toggleDrawerButton.addEventListener("click", this.toggle, this); 52 53 this._tabbedPane = new WebInspector.TabbedPane(); 54 this._tabbedPane.element.id = "drawer-tabbed-pane"; 55 this._tabbedPane.closeableTabs = false; 56 this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); 57 new WebInspector.ExtensibleTabbedPaneController(this._tabbedPane, "drawer-view"); 58 59 this._toggleDrawerEditorButton = this._drawerEditorSplitView.createShowHideSidebarButton("editor in drawer", "drawer-editor-show-hide-button"); 60 this._tabbedPane.element.appendChild(this._toggleDrawerEditorButton.element); 61 if (!WebInspector.experimentsSettings.editorInDrawer.isEnabled()) 62 this.setDrawerEditorAvailable(false); 63 64 splitView.installResizer(this._tabbedPane.headerElement()); 65 this._lastSelectedViewSetting = WebInspector.settings.createSetting("WebInspector.Drawer.lastSelectedView", "console"); 66 this._tabbedPane.show(this._drawerEditorSplitView.mainElement()); 67} 68 69WebInspector.Drawer.prototype = { 70 /** 71 * @return {!Element} 72 */ 73 toggleButtonElement: function() 74 { 75 return this._toggleDrawerButton.element; 76 }, 77 78 /** 79 * @param {string} id 80 */ 81 closeView: function(id) 82 { 83 this._tabbedPane.closeTab(id); 84 }, 85 86 /** 87 * @param {string} id 88 * @param {boolean=} immediate 89 */ 90 showView: function(id, immediate) 91 { 92 if (!this._tabbedPane.hasTab(id)) { 93 // Hidden tab. 94 this._innerShow(immediate); 95 return; 96 } 97 this._innerShow(immediate); 98 this._tabbedPane.selectTab(id, true); 99 // In case this id is already selected, anyways persist it as the last saved value. 100 this._lastSelectedViewSetting.set(id); 101 }, 102 103 /** 104 * @param {string} id 105 * @param {string} title 106 * @param {!WebInspector.View} view 107 */ 108 showCloseableView: function(id, title, view) 109 { 110 if (!this._tabbedPane.hasTab(id)) { 111 this._tabbedPane.appendTab(id, title, view, undefined, false, true); 112 } else { 113 this._tabbedPane.changeTabView(id, view); 114 this._tabbedPane.changeTabTitle(id, title); 115 } 116 this._innerShow(); 117 this._tabbedPane.selectTab(id, true); 118 }, 119 120 showDrawer: function() 121 { 122 this.showView(this._lastSelectedViewSetting.get()); 123 }, 124 125 wasShown: function() 126 { 127 this.showView(this._lastSelectedViewSetting.get()); 128 this._toggleDrawerButton.toggled = true; 129 this._toggleDrawerButton.title = WebInspector.UIString("Hide drawer."); 130 this._ensureDrawerEditorExistsIfNeeded(); 131 }, 132 133 willHide: function() 134 { 135 this._toggleDrawerButton.toggled = false; 136 this._toggleDrawerButton.title = WebInspector.UIString("Show drawer."); 137 }, 138 139 /** 140 * @param {boolean=} immediate 141 */ 142 _innerShow: function(immediate) 143 { 144 if (this.isShowing()) 145 return; 146 147 this._splitView.showBoth(!immediate); 148 149 if (this._visibleView()) 150 this._visibleView().focus(); 151 }, 152 153 closeDrawer: function() 154 { 155 if (!this.isShowing()) 156 return; 157 158 WebInspector.restoreFocusFromElement(this.element); 159 this._splitView.hideSidebar(true); 160 }, 161 162 /** 163 * @return {?WebInspector.View} view 164 */ 165 _visibleView: function() 166 { 167 return this._tabbedPane.visibleView; 168 }, 169 170 /** 171 * @param {!WebInspector.Event} event 172 */ 173 _tabSelected: function(event) 174 { 175 var tabId = this._tabbedPane.selectedTabId; 176 if (tabId && event.data["isUserGesture"] && !this._tabbedPane.isTabCloseable(tabId)) 177 this._lastSelectedViewSetting.set(tabId); 178 }, 179 180 toggle: function() 181 { 182 if (this._toggleDrawerButton.toggled) 183 this.closeDrawer(); 184 else 185 this.showDrawer(); 186 }, 187 188 /** 189 * @return {boolean} 190 */ 191 visible: function() 192 { 193 return this._toggleDrawerButton.toggled; 194 }, 195 196 /** 197 * @return {?string} 198 */ 199 selectedViewId: function() 200 { 201 return this._tabbedPane.selectedTabId; 202 }, 203 204 /** 205 * @param {!WebInspector.Event} event 206 */ 207 _drawerEditorSplitViewShowModeChanged: function(event) 208 { 209 var mode = /** @type {string} */ (event.data); 210 var shown = mode === WebInspector.SplitView.ShowMode.Both; 211 212 if (this._isHidingDrawerEditor) 213 return; 214 215 this._drawerEditorShownSetting.set(shown); 216 217 if (!shown) 218 return; 219 220 this._ensureDrawerEditor(); 221 this._drawerEditor.view().show(this._drawerEditorSplitView.sidebarElement()); 222 }, 223 224 initialPanelShown: function() 225 { 226 this._initialPanelWasShown = true; 227 this._ensureDrawerEditorExistsIfNeeded(); 228 }, 229 230 _ensureDrawerEditorExistsIfNeeded: function() 231 { 232 if (!this._initialPanelWasShown || !this.isShowing() || !this._drawerEditorShownSetting.get() || !WebInspector.experimentsSettings.editorInDrawer.isEnabled()) 233 return; 234 this._ensureDrawerEditor(); 235 }, 236 237 _ensureDrawerEditor: function() 238 { 239 if (this._drawerEditor) 240 return; 241 this._drawerEditor = WebInspector.moduleManager.instance(WebInspector.DrawerEditor); 242 this._drawerEditor.installedIntoDrawer(); 243 }, 244 245 /** 246 * @param {boolean} available 247 */ 248 setDrawerEditorAvailable: function(available) 249 { 250 if (!WebInspector.experimentsSettings.editorInDrawer.isEnabled()) 251 available = false; 252 this._toggleDrawerEditorButton.element.classList.toggle("hidden", !available); 253 }, 254 255 showDrawerEditor: function() 256 { 257 if (!WebInspector.experimentsSettings.editorInDrawer.isEnabled()) 258 return; 259 260 this._splitView.showBoth(); 261 this._drawerEditorSplitView.showBoth(); 262 }, 263 264 hideDrawerEditor: function() 265 { 266 this._isHidingDrawerEditor = true; 267 this._drawerEditorSplitView.hideSidebar(); 268 this._isHidingDrawerEditor = false; 269 }, 270 271 /** 272 * @return {boolean} 273 */ 274 isDrawerEditorShown: function() 275 { 276 return this._drawerEditorShownSetting.get(); 277 }, 278 279 __proto__: WebInspector.VBox.prototype 280} 281 282/** 283 * @interface 284 */ 285WebInspector.Drawer.ViewFactory = function() 286{ 287} 288 289WebInspector.Drawer.ViewFactory.prototype = { 290 /** 291 * @return {!WebInspector.View} 292 */ 293 createView: function() {} 294} 295 296/** 297 * @constructor 298 * @implements {WebInspector.Drawer.ViewFactory} 299 * @param {function(new:T)} constructor 300 * @template T 301 */ 302WebInspector.Drawer.SingletonViewFactory = function(constructor) 303{ 304 this._constructor = constructor; 305} 306 307WebInspector.Drawer.SingletonViewFactory.prototype = { 308 /** 309 * @return {!WebInspector.View} 310 */ 311 createView: function() 312 { 313 if (!this._instance) 314 this._instance = /** @type {!WebInspector.View} */(new this._constructor()); 315 return this._instance; 316 } 317} 318 319/** 320 * @interface 321 */ 322WebInspector.DrawerEditor = function() 323{ 324} 325 326WebInspector.DrawerEditor.prototype = { 327 /** 328 * @return {!WebInspector.View} 329 */ 330 view: function() { }, 331 332 installedIntoDrawer: function() { }, 333} 334