OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2007, 2008 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 * | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | |
14 * its contributors may be used to endorse or promote products derived | |
15 * from this software without specific prior written permission. | |
16 * | |
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 */ | |
28 | |
29 WebInspector.Panel = function() | |
30 { | |
31 WebInspector.View.call(this); | |
32 | |
33 this.element.addStyleClass("panel"); | |
34 } | |
35 | |
36 WebInspector.Panel.prototype = { | |
37 get toolbarItem() | |
38 { | |
39 if (this._toolbarItem) | |
40 return this._toolbarItem; | |
41 | |
42 // Sample toolbar item as markup: | |
43 // <button class="toolbar-item resources toggleable"> | |
44 // <div class="toolbar-icon"></div> | |
45 // <div class="toolbar-label">Resources</div> | |
46 // </button> | |
47 | |
48 this._toolbarItem = document.createElement("button"); | |
49 this._toolbarItem.className = "toolbar-item toggleable"; | |
50 this._toolbarItem.panel = this; | |
51 | |
52 if ("toolbarItemClass" in this) | |
53 this._toolbarItem.addStyleClass(this.toolbarItemClass); | |
54 | |
55 var iconElement = document.createElement("div"); | |
56 iconElement.className = "toolbar-icon"; | |
57 this._toolbarItem.appendChild(iconElement); | |
58 | |
59 if ("toolbarItemLabel" in this) { | |
60 var labelElement = document.createElement("div"); | |
61 labelElement.className = "toolbar-label"; | |
62 labelElement.textContent = this.toolbarItemLabel; | |
63 this._toolbarItem.appendChild(labelElement); | |
64 } | |
65 | |
66 return this._toolbarItem; | |
67 }, | |
68 | |
69 show: function() | |
70 { | |
71 WebInspector.View.prototype.show.call(this); | |
72 | |
73 var statusBarItems = this.statusBarItems; | |
74 if (statusBarItems) { | |
75 this._statusBarItemContainer = document.createElement("div"); | |
76 for (var i = 0; i < statusBarItems.length; ++i) | |
77 this._statusBarItemContainer.appendChild(statusBarItems[i]); | |
78 document.getElementById("main-status-bar").appendChild(this._statusB
arItemContainer); | |
79 } | |
80 | |
81 if ("_toolbarItem" in this) | |
82 this._toolbarItem.addStyleClass("toggled-on"); | |
83 | |
84 WebInspector.currentFocusElement = document.getElementById("main-panels"
); | |
85 }, | |
86 | |
87 hide: function() | |
88 { | |
89 WebInspector.View.prototype.hide.call(this); | |
90 | |
91 if (this._statusBarItemContainer && this._statusBarItemContainer.parentN
ode) | |
92 this._statusBarItemContainer.parentNode.removeChild(this._statusBarI
temContainer); | |
93 delete this._statusBarItemContainer; | |
94 if ("_toolbarItem" in this) | |
95 this._toolbarItem.removeStyleClass("toggled-on"); | |
96 }, | |
97 | |
98 attach: function() | |
99 { | |
100 if (!this.element.parentNode) | |
101 document.getElementById("main-panels").appendChild(this.element); | |
102 }, | |
103 | |
104 searchCanceled: function(startingNewSearch) | |
105 { | |
106 if (this._searchResults) { | |
107 for (var i = 0; i < this._searchResults.length; ++i) { | |
108 var view = this._searchResults[i]; | |
109 if (view.searchCanceled) | |
110 view.searchCanceled(); | |
111 delete view.currentQuery; | |
112 } | |
113 } | |
114 | |
115 WebInspector.updateSearchMatchesCount(0, this); | |
116 | |
117 if (this._currentSearchChunkIntervalIdentifier) { | |
118 clearInterval(this._currentSearchChunkIntervalIdentifier); | |
119 delete this._currentSearchChunkIntervalIdentifier; | |
120 } | |
121 | |
122 this._totalSearchMatches = 0; | |
123 this._currentSearchResultIndex = 0; | |
124 this._searchResults = []; | |
125 }, | |
126 | |
127 performSearch: function(query) | |
128 { | |
129 // Call searchCanceled since it will reset everything we need before doi
ng a new search. | |
130 this.searchCanceled(true); | |
131 | |
132 var searchableViews = this.searchableViews; | |
133 if (!searchableViews || !searchableViews.length) | |
134 return; | |
135 | |
136 var parentElement = this.viewsContainerElement; | |
137 var visibleView = this.visibleView; | |
138 var sortFuction = this.searchResultsSortFunction; | |
139 | |
140 var matchesCountUpdateTimeout = null; | |
141 | |
142 function updateMatchesCount() | |
143 { | |
144 WebInspector.updateSearchMatchesCount(this._totalSearchMatches, this
); | |
145 matchesCountUpdateTimeout = null; | |
146 } | |
147 | |
148 function updateMatchesCountSoon() | |
149 { | |
150 if (matchesCountUpdateTimeout) | |
151 return; | |
152 // Update the matches count every half-second so it doesn't feel twi
tchy. | |
153 matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this)
, 500); | |
154 } | |
155 | |
156 function finishedCallback(view, searchMatches) | |
157 { | |
158 if (!searchMatches) | |
159 return; | |
160 | |
161 this._totalSearchMatches += searchMatches; | |
162 this._searchResults.push(view); | |
163 | |
164 if (sortFuction) | |
165 this._searchResults.sort(sortFuction); | |
166 | |
167 if (this.searchMatchFound) | |
168 this.searchMatchFound(view, searchMatches); | |
169 | |
170 updateMatchesCountSoon.call(this); | |
171 | |
172 if (view === visibleView) | |
173 view.jumpToFirstSearchResult(); | |
174 } | |
175 | |
176 var i = 0; | |
177 var panel = this; | |
178 var boundFinishedCallback = finishedCallback.bind(this); | |
179 var chunkIntervalIdentifier = null; | |
180 | |
181 // Split up the work into chunks so we don't block the | |
182 // UI thread while processing. | |
183 | |
184 function processChunk() | |
185 { | |
186 var view = searchableViews[i]; | |
187 | |
188 if (++i >= searchableViews.length) { | |
189 if (panel._currentSearchChunkIntervalIdentifier === chunkInterva
lIdentifier) | |
190 delete panel._currentSearchChunkIntervalIdentifier; | |
191 clearInterval(chunkIntervalIdentifier); | |
192 } | |
193 | |
194 if (!view) | |
195 return; | |
196 | |
197 if (view.element.parentNode !== parentElement && view.element.parent
Node && parentElement) | |
198 view.detach(); | |
199 | |
200 view.currentQuery = query; | |
201 view.performSearch(query, boundFinishedCallback); | |
202 } | |
203 | |
204 processChunk(); | |
205 | |
206 chunkIntervalIdentifier = setInterval(processChunk, 25); | |
207 this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; | |
208 }, | |
209 | |
210 jumpToNextSearchResult: function() | |
211 { | |
212 if (!this.showView || !this._searchResults || !this._searchResults.lengt
h) | |
213 return; | |
214 | |
215 var showFirstResult = false; | |
216 | |
217 this._currentSearchResultIndex = this._searchResults.indexOf(this.visibl
eView); | |
218 if (this._currentSearchResultIndex === -1) { | |
219 this._currentSearchResultIndex = 0; | |
220 showFirstResult = true; | |
221 } | |
222 | |
223 var currentView = this._searchResults[this._currentSearchResultIndex]; | |
224 | |
225 if (currentView.showingLastSearchResult()) { | |
226 if (++this._currentSearchResultIndex >= this._searchResults.length) | |
227 this._currentSearchResultIndex = 0; | |
228 currentView = this._searchResults[this._currentSearchResultIndex]; | |
229 showFirstResult = true; | |
230 } | |
231 | |
232 if (currentView !== this.visibleView) | |
233 this.showView(currentView); | |
234 | |
235 if (showFirstResult) | |
236 currentView.jumpToFirstSearchResult(); | |
237 else | |
238 currentView.jumpToNextSearchResult(); | |
239 }, | |
240 | |
241 jumpToPreviousSearchResult: function() | |
242 { | |
243 if (!this.showView || !this._searchResults || !this._searchResults.lengt
h) | |
244 return; | |
245 | |
246 var showLastResult = false; | |
247 | |
248 this._currentSearchResultIndex = this._searchResults.indexOf(this.visibl
eView); | |
249 if (this._currentSearchResultIndex === -1) { | |
250 this._currentSearchResultIndex = 0; | |
251 showLastResult = true; | |
252 } | |
253 | |
254 var currentView = this._searchResults[this._currentSearchResultIndex]; | |
255 | |
256 if (currentView.showingFirstSearchResult()) { | |
257 if (--this._currentSearchResultIndex < 0) | |
258 this._currentSearchResultIndex = (this._searchResults.length - 1
); | |
259 currentView = this._searchResults[this._currentSearchResultIndex]; | |
260 showLastResult = true; | |
261 } | |
262 | |
263 if (currentView !== this.visibleView) | |
264 this.showView(currentView); | |
265 | |
266 if (showLastResult) | |
267 currentView.jumpToLastSearchResult(); | |
268 else | |
269 currentView.jumpToPreviousSearchResult(); | |
270 } | |
271 } | |
272 | |
273 WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype; | |
OLD | NEW |