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._toggleDrawerButton = new WebInspector.StatusBarButton(WebInspector.UIString("Show drawer."), "console-status-bar-item");
45    this._toggleDrawerButton.addEventListener("click", this.toggle, this);
46
47    this._tabbedPane = new WebInspector.TabbedPane();
48    this._tabbedPane.element.id = "drawer-tabbed-pane";
49    this._tabbedPane.closeableTabs = false;
50    this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
51    new WebInspector.ExtensibleTabbedPaneController(this._tabbedPane, "drawer-view");
52
53    splitView.installResizer(this._tabbedPane.headerElement());
54    this._lastSelectedViewSetting = WebInspector.settings.createSetting("WebInspector.Drawer.lastSelectedView", "console");
55    this._tabbedPane.show(this.element);
56}
57
58WebInspector.Drawer.prototype = {
59    /**
60     * @return {!WebInspector.StatusBarButton}
61     */
62    toggleButton: function()
63    {
64        return this._toggleDrawerButton;
65    },
66
67    /**
68     * @param {string} id
69     */
70    closeView: function(id)
71    {
72        this._tabbedPane.closeTab(id);
73    },
74
75    /**
76     * @param {string} id
77     * @param {boolean=} immediate
78     */
79    showView: function(id, immediate)
80    {
81        if (!this._tabbedPane.hasTab(id)) {
82            // Hidden tab.
83            this._innerShow(immediate);
84            return;
85        }
86        this._innerShow(immediate);
87        this._tabbedPane.selectTab(id, true);
88        // In case this id is already selected, anyways persist it as the last saved value.
89        this._lastSelectedViewSetting.set(id);
90    },
91
92    /**
93     * @param {string} id
94     * @param {string} title
95     * @param {!WebInspector.View} view
96     */
97    showCloseableView: function(id, title, view)
98    {
99        if (!this._tabbedPane.hasTab(id)) {
100            this._tabbedPane.appendTab(id, title, view, undefined, false, true);
101        } else {
102            this._tabbedPane.changeTabView(id, view);
103            this._tabbedPane.changeTabTitle(id, title);
104        }
105        this._innerShow();
106        this._tabbedPane.selectTab(id, true);
107    },
108
109    showDrawer: function()
110    {
111        this.showView(this._lastSelectedViewSetting.get());
112    },
113
114    wasShown: function()
115    {
116        this.showView(this._lastSelectedViewSetting.get());
117        this._toggleDrawerButton.toggled = true;
118        this._toggleDrawerButton.title = WebInspector.UIString("Hide drawer.");
119    },
120
121    willHide: function()
122    {
123        this._toggleDrawerButton.toggled = false;
124        this._toggleDrawerButton.title = WebInspector.UIString("Show drawer.");
125    },
126
127    /**
128     * @param {boolean=} immediate
129     */
130    _innerShow: function(immediate)
131    {
132        if (this.isShowing())
133            return;
134
135        this._splitView.showBoth(!immediate);
136
137        if (this._visibleView())
138            this._visibleView().focus();
139    },
140
141    closeDrawer: function()
142    {
143        if (!this.isShowing())
144            return;
145
146        WebInspector.restoreFocusFromElement(this.element);
147        this._splitView.hideSidebar(true);
148    },
149
150    /**
151     * @return {?WebInspector.View} view
152     */
153    _visibleView: function()
154    {
155        return this._tabbedPane.visibleView;
156    },
157
158    /**
159     * @param {!WebInspector.Event} event
160     */
161    _tabSelected: function(event)
162    {
163        var tabId = this._tabbedPane.selectedTabId;
164        if (tabId && event.data["isUserGesture"] && !this._tabbedPane.isTabCloseable(tabId))
165            this._lastSelectedViewSetting.set(tabId);
166    },
167
168    toggle: function()
169    {
170        if (this._toggleDrawerButton.toggled)
171            this.closeDrawer();
172        else
173            this.showDrawer();
174    },
175
176    /**
177     * @return {boolean}
178     */
179    visible: function()
180    {
181        return this._toggleDrawerButton.toggled;
182    },
183
184    /**
185     * @return {?string}
186     */
187    selectedViewId: function()
188    {
189        return this._tabbedPane.selectedTabId;
190    },
191
192    initialPanelShown: function()
193    {
194        this._initialPanelWasShown = true;
195    },
196
197    __proto__: WebInspector.VBox.prototype
198}
199
200/**
201 * @interface
202 */
203WebInspector.Drawer.ViewFactory = function()
204{
205}
206
207WebInspector.Drawer.ViewFactory.prototype = {
208    /**
209     * @return {!WebInspector.View}
210     */
211    createView: function() {}
212}
213
214/**
215 * @constructor
216 * @implements {WebInspector.Drawer.ViewFactory}
217 * @param {function(new:T)} constructor
218 * @template T
219 */
220WebInspector.Drawer.SingletonViewFactory = function(constructor)
221{
222    this._constructor = constructor;
223}
224
225WebInspector.Drawer.SingletonViewFactory.prototype = {
226    /**
227     * @return {!WebInspector.View}
228     */
229    createView: function()
230    {
231        if (!this._instance)
232            this._instance = /** @type {!WebInspector.View} */(new this._constructor());
233        return this._instance;
234    }
235}
236