Web Inspector: Make closing ContentViews more leak proof
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / ClusterContentView.js
1 /*
2  * Copyright (C) 2013 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.ClusterContentView = function(representedObject)
27 {
28     WebInspector.ContentView.call(this, representedObject);
29
30     this.element.classList.add(WebInspector.ClusterContentView.StyleClassName);
31
32     this._contentViewContainer = new WebInspector.ContentViewContainer();
33     this._contentViewContainer.addEventListener(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange, this._currentContentViewDidChange, this);
34     this.element.appendChild(this._contentViewContainer.element);
35
36     WebInspector.ContentView.addEventListener(WebInspector.ContentView.Event.SelectionPathComponentsDidChange, this._contentViewSelectionPathComponentDidChange, this);
37     WebInspector.ContentView.addEventListener(WebInspector.ContentView.Event.SupplementalRepresentedObjectsDidChange, this._contentViewSupplementalRepresentedObjectsDidChange, this);
38     WebInspector.ContentView.addEventListener(WebInspector.ContentView.Event.NumberOfSearchResultsDidChange, this._contentViewNumberOfSearchResultsDidChange, this);
39 };
40
41 WebInspector.ClusterContentView.StyleClassName = "cluster";
42
43 WebInspector.ClusterContentView.prototype = {
44     constructor: WebInspector.ClusterContentView,
45
46     // Public
47
48     get navigationItems()
49     {
50         var currentContentView = this._contentViewContainer.currentContentView;
51         return currentContentView ? currentContentView.navigationItems : [];
52     },
53
54     get contentViewContainer()
55     {
56         return this._contentViewContainer;
57     },
58
59     get supportsSplitContentBrowser()
60     {
61         if (this._contentViewContainer.currentContentView)
62             return this._contentViewContainer.currentContentView.supportsSplitContentBrowser;
63         return true;
64     },
65
66     updateLayout: function()
67     {
68         var currentContentView = this._contentViewContainer.currentContentView;
69         if (currentContentView)
70             currentContentView.updateLayout();
71     },
72
73     shown: function()
74     {
75         this._contentViewContainer.shown();
76     },
77
78     hidden: function()
79     {
80         this._contentViewContainer.hidden();
81     },
82
83     closed: function()
84     {
85         this._contentViewContainer.closeAllContentViews();
86
87         WebInspector.ContentView.removeEventListener(null, null, this);
88     },
89
90     canGoBack: function()
91     {
92         return this._contentViewContainer.canGoBack();
93     },
94
95     canGoForward: function()
96     {
97         return this._contentViewContainer.canGoForward();
98     },
99
100     goBack: function()
101     {
102         this._contentViewContainer.goBack();
103     },
104
105     goForward: function()
106     {
107         this._contentViewContainer.goForward();
108     },
109
110     get selectionPathComponents()
111     {
112         if (!this._contentViewContainer.currentContentView)
113             return [];
114         return this._contentViewContainer.currentContentView.selectionPathComponents;
115     },
116
117     get supplementalRepresentedObjects()
118     {
119         if (!this._contentViewContainer.currentContentView)
120             return [];
121         return this._contentViewContainer.currentContentView.supplementalRepresentedObjects;
122     },
123
124     get handleCopyEvent()
125     {
126         var currentContentView = this._contentViewContainer.currentContentView;
127         return currentContentView && typeof currentContentView.handleCopyEvent === "function" ? currentContentView.handleCopyEvent.bind(currentContentView) : null;
128     },
129
130     get supportsSave()
131     {
132         var currentContentView = this._contentViewContainer.currentContentView;
133         return currentContentView && currentContentView.supportsSave;
134     },
135
136     get saveData()
137     {
138         var currentContentView = this._contentViewContainer.currentContentView;
139         return currentContentView && currentContentView.saveData || null;
140     },
141
142     get supportsSearch()
143     {
144         // Always return true so we can intercept the search query to resend it when switching content views.
145         return true;
146     },
147
148     get numberOfSearchResults()
149     {
150         var currentContentView = this._contentViewContainer.currentContentView;
151         if (!currentContentView || !currentContentView.supportsSearch)
152             return null;
153         return currentContentView.numberOfSearchResults;
154     },
155
156     get hasPerformedSearch()
157     {
158         var currentContentView = this._contentViewContainer.currentContentView;
159         if (!currentContentView || !currentContentView.supportsSearch)
160             return false;
161         return currentContentView.hasPerformedSearch;
162     },
163
164     set automaticallyRevealFirstSearchResult(reveal)
165     {
166         var currentContentView = this._contentViewContainer.currentContentView;
167         if (!currentContentView || !currentContentView.supportsSearch)
168             return;
169         currentContentView.automaticallyRevealFirstSearchResult = reveal;
170     },
171
172     performSearch: function(query)
173     {
174         this._searchQuery = query;
175
176         var currentContentView = this._contentViewContainer.currentContentView;
177         if (!currentContentView || !currentContentView.supportsSearch)
178             return;
179         currentContentView.performSearch(query);
180     },
181
182     searchCleared: function()
183     {
184         this._searchQuery = null;
185
186         var currentContentView = this._contentViewContainer.currentContentView;
187         if (!currentContentView || !currentContentView.supportsSearch)
188             return;
189         currentContentView.searchCleared();
190     },
191
192     searchQueryWithSelection: function()
193     {
194         var currentContentView = this._contentViewContainer.currentContentView;
195         if (!currentContentView || !currentContentView.supportsSearch)
196             return null;
197         return currentContentView.searchQueryWithSelection();
198     },
199
200     revealPreviousSearchResult: function(changeFocus)
201     {
202         var currentContentView = this._contentViewContainer.currentContentView;
203         if (!currentContentView || !currentContentView.supportsSearch)
204             return;
205         currentContentView.revealPreviousSearchResult(changeFocus);
206     },
207
208     revealNextSearchResult: function(changeFocus)
209     {
210         var currentContentView = this._contentViewContainer.currentContentView;
211         if (!currentContentView || !currentContentView.supportsSearch)
212             return;
213         currentContentView.revealNextSearchResult(changeFocus);
214     },
215
216     // Private
217
218     _currentContentViewDidChange: function(event)
219     {
220         var currentContentView = this._contentViewContainer.currentContentView;
221         if (currentContentView && currentContentView.supportsSearch) {
222             if (this._searchQuery)
223                 currentContentView.performSearch(this._searchQuery);
224             else
225                 currentContentView.searchCleared();
226         }
227
228         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
229         this.dispatchEventToListeners(WebInspector.ContentView.Event.NumberOfSearchResultsDidChange);
230         this.dispatchEventToListeners(WebInspector.ContentView.Event.NavigationItemsDidChange);
231     },
232
233     _contentViewSelectionPathComponentDidChange: function(event)
234     {
235         if (event.target !== this._contentViewContainer.currentContentView)
236             return;
237         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
238     },
239
240     _contentViewSupplementalRepresentedObjectsDidChange: function(event)
241     {
242         if (event.target !== this._contentViewContainer.currentContentView)
243             return;
244         this.dispatchEventToListeners(WebInspector.ContentView.Event.SupplementalRepresentedObjectsDidChange);
245     },
246
247     _contentViewNumberOfSearchResultsDidChange: function(event)
248     {
249         if (event.target !== this._contentViewContainer.currentContentView)
250             return;
251         this.dispatchEventToListeners(WebInspector.ContentView.Event.NumberOfSearchResultsDidChange);
252     }
253 };
254
255 WebInspector.ClusterContentView.prototype.__proto__ = WebInspector.ContentView.prototype;