OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Google 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 are | |
6 * met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * | |
11 * 2. Redistributions in binary form must reproduce the above | |
12 * copyright notice, this list of conditions and the following disclaimer | |
13 * in the documentation and/or other materials provided with the | |
14 * distribution. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS | |
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. | |
20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 */ | |
28 | |
29 /** | |
30 * @constructor | |
31 */ | |
32 WebInspector.AdvancedSearchController = function() | |
33 { | |
34 this._searchId = 0; | |
35 | |
36 WebInspector.settings.advancedSearchConfig = WebInspector.settings.createSet
ting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false).toPl
ainObject()); | |
37 } | |
38 | |
39 WebInspector.AdvancedSearchController.prototype = { | |
40 show: function() | |
41 { | |
42 var selection = window.getSelection(); | |
43 var queryCandidate; | |
44 if (selection.rangeCount) | |
45 queryCandidate = selection.toString().replace(/\r?\n.*/, ""); | |
46 | |
47 if (!this._searchView || !this._searchView.isShowing()) | |
48 WebInspector.inspectorView.showViewInDrawer("search"); | |
49 if (queryCandidate) | |
50 this._searchView._search.value = queryCandidate; | |
51 this._searchView.focus(); | |
52 | |
53 this.startIndexing(); | |
54 }, | |
55 | |
56 /** | |
57 * @param {boolean} finished | |
58 */ | |
59 _onIndexingFinished: function(finished) | |
60 { | |
61 delete this._isIndexing; | |
62 this._searchView.indexingFinished(finished); | |
63 if (!finished) | |
64 delete this._pendingSearchConfig; | |
65 if (!this._pendingSearchConfig) | |
66 return; | |
67 var searchConfig = this._pendingSearchConfig | |
68 delete this._pendingSearchConfig; | |
69 this._innerStartSearch(searchConfig); | |
70 }, | |
71 | |
72 startIndexing: function() | |
73 { | |
74 this._isIndexing = true; | |
75 // FIXME: this._currentSearchScope should be initialized based on search
Config | |
76 this._currentSearchScope = this._searchScopes()[0]; | |
77 if (this._progressIndicator) | |
78 this._progressIndicator.done(); | |
79 this._progressIndicator = new WebInspector.ProgressIndicator(); | |
80 this._searchView.indexingStarted(this._progressIndicator); | |
81 this._currentSearchScope.performIndexing(this._progressIndicator, this._
onIndexingFinished.bind(this)); | |
82 }, | |
83 | |
84 /** | |
85 * @param {number} searchId | |
86 * @param {!WebInspector.FileBasedSearchResult} searchResult | |
87 */ | |
88 _onSearchResult: function(searchId, searchResult) | |
89 { | |
90 if (searchId !== this._searchId) | |
91 return; | |
92 this._searchView.addSearchResult(searchResult); | |
93 if (!searchResult.searchMatches.length) | |
94 return; | |
95 if (!this._searchResultsPane) | |
96 this._searchResultsPane = this._currentSearchScope.createSearchResul
tsPane(this._searchConfig); | |
97 this._searchView.resultsPane = this._searchResultsPane; | |
98 this._searchResultsPane.addSearchResult(searchResult); | |
99 }, | |
100 | |
101 /** | |
102 * @param {number} searchId | |
103 * @param {boolean} finished | |
104 */ | |
105 _onSearchFinished: function(searchId, finished) | |
106 { | |
107 if (searchId !== this._searchId) | |
108 return; | |
109 if (!this._searchResultsPane) | |
110 this._searchView.nothingFound(); | |
111 this._searchView.searchFinished(finished); | |
112 delete this._searchConfig; | |
113 }, | |
114 | |
115 /** | |
116 * @param {!WebInspector.SearchConfig} searchConfig | |
117 */ | |
118 startSearch: function(searchConfig) | |
119 { | |
120 this.resetSearch(); | |
121 ++this._searchId; | |
122 if (!this._isIndexing) | |
123 this.startIndexing(); | |
124 this._pendingSearchConfig = searchConfig; | |
125 }, | |
126 | |
127 /** | |
128 * @param {!WebInspector.SearchConfig} searchConfig | |
129 */ | |
130 _innerStartSearch: function(searchConfig) | |
131 { | |
132 this._searchConfig = searchConfig; | |
133 // FIXME: this._currentSearchScope should be initialized based on search
Config | |
134 this._currentSearchScope = this._searchScopes()[0]; | |
135 | |
136 if (this._progressIndicator) | |
137 this._progressIndicator.done(); | |
138 this._progressIndicator = new WebInspector.ProgressIndicator(); | |
139 this._searchView.searchStarted(this._progressIndicator); | |
140 this._currentSearchScope.performSearch(searchConfig, this._progressIndic
ator, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bi
nd(this, this._searchId)); | |
141 }, | |
142 | |
143 resetSearch: function() | |
144 { | |
145 this.stopSearch(); | |
146 | |
147 if (this._searchResultsPane) { | |
148 this._searchView.resetResults(); | |
149 delete this._searchResultsPane; | |
150 } | |
151 }, | |
152 | |
153 stopSearch: function() | |
154 { | |
155 if (this._progressIndicator) | |
156 this._progressIndicator.cancel(); | |
157 if (this._currentSearchScope) | |
158 this._currentSearchScope.stopSearch(); | |
159 delete this._searchConfig; | |
160 }, | |
161 | |
162 /** | |
163 * @return {!Array.<!WebInspector.SearchScope>} | |
164 */ | |
165 _searchScopes: function() | |
166 { | |
167 // FIXME: implement multiple search scopes. | |
168 return /** @type {!Array.<!WebInspector.SearchScope>} */ (WebInspector.m
oduleManager.instances(WebInspector.SearchScope)); | |
169 } | |
170 } | |
171 | |
172 /** | |
173 * @constructor | |
174 * @extends {WebInspector.VBox} | |
175 */ | |
176 WebInspector.SearchView = function() | |
177 { | |
178 WebInspector.VBox.call(this); | |
179 | |
180 this._controller = WebInspector.advancedSearchController; | |
181 WebInspector.advancedSearchController._searchView = this; | |
182 | |
183 this.element.classList.add("search-view"); | |
184 | |
185 this._searchPanelElement = this.element.createChild("div", "search-drawer-he
ader"); | |
186 this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(th
is), false); | |
187 | |
188 this._searchResultsElement = this.element.createChild("div"); | |
189 this._searchResultsElement.className = "search-results"; | |
190 | |
191 this._search = this._searchPanelElement.createChild("input"); | |
192 this._search.placeholder = WebInspector.UIString("Search sources"); | |
193 this._search.setAttribute("type", "text"); | |
194 this._search.classList.add("search-config-search"); | |
195 this._search.setAttribute("results", "0"); | |
196 this._search.setAttribute("size", 30); | |
197 | |
198 this._ignoreCaseLabel = this._searchPanelElement.createChild("label"); | |
199 this._ignoreCaseLabel.classList.add("search-config-label"); | |
200 this._ignoreCaseCheckbox = this._ignoreCaseLabel.createChild("input"); | |
201 this._ignoreCaseCheckbox.setAttribute("type", "checkbox"); | |
202 this._ignoreCaseCheckbox.classList.add("search-config-checkbox"); | |
203 this._ignoreCaseLabel.appendChild(document.createTextNode(WebInspector.UIStr
ing("Ignore case"))); | |
204 | |
205 this._regexLabel = this._searchPanelElement.createChild("label"); | |
206 this._regexLabel.classList.add("search-config-label"); | |
207 this._regexCheckbox = this._regexLabel.createChild("input"); | |
208 this._regexCheckbox.setAttribute("type", "checkbox"); | |
209 this._regexCheckbox.classList.add("search-config-checkbox"); | |
210 this._regexLabel.appendChild(document.createTextNode(WebInspector.UIString("
Regular expression"))); | |
211 | |
212 this._searchStatusBarElement = this.element.createChild("div", "search-statu
s-bar-summary"); | |
213 this._searchMessageElement = this._searchStatusBarElement.createChild("span"
); | |
214 this._searchResultsMessageElement = document.createElement("span"); | |
215 | |
216 this._load(); | |
217 } | |
218 | |
219 WebInspector.SearchView.prototype = { | |
220 /** | |
221 * @return {!WebInspector.SearchConfig} | |
222 */ | |
223 get searchConfig() | |
224 { | |
225 return new WebInspector.SearchConfig(this._search.value, this._ignoreCas
eCheckbox.checked, this._regexCheckbox.checked); | |
226 }, | |
227 | |
228 /** | |
229 * @type {!WebInspector.SearchResultsPane} | |
230 */ | |
231 set resultsPane(resultsPane) | |
232 { | |
233 this.resetResults(); | |
234 this._searchResultsElement.appendChild(resultsPane.element); | |
235 }, | |
236 | |
237 /** | |
238 * @param {!WebInspector.ProgressIndicator} progressIndicator | |
239 */ | |
240 searchStarted: function(progressIndicator) | |
241 { | |
242 this.resetResults(); | |
243 this._resetCounters(); | |
244 | |
245 this._searchMessageElement.textContent = WebInspector.UIString("Searchin
g..."); | |
246 progressIndicator.show(this._searchStatusBarElement); | |
247 this._updateSearchResultsMessage(); | |
248 | |
249 if (!this._searchingView) | |
250 this._searchingView = new WebInspector.EmptyView(WebInspector.UIStri
ng("Searching...")); | |
251 this._searchingView.show(this._searchResultsElement); | |
252 }, | |
253 | |
254 /** | |
255 * @param {!WebInspector.ProgressIndicator} progressIndicator | |
256 */ | |
257 indexingStarted: function(progressIndicator) | |
258 { | |
259 this._searchMessageElement.textContent = WebInspector.UIString("Indexing
..."); | |
260 progressIndicator.show(this._searchStatusBarElement); | |
261 }, | |
262 | |
263 /** | |
264 * @param {boolean} finished | |
265 */ | |
266 indexingFinished: function(finished) | |
267 { | |
268 this._searchMessageElement.textContent = finished ? "" : WebInspector.UI
String("Indexing interrupted."); | |
269 }, | |
270 | |
271 _updateSearchResultsMessage: function() | |
272 { | |
273 if (this._searchMatchesCount && this._searchResultsCount) | |
274 this._searchResultsMessageElement.textContent = WebInspector.UIStrin
g("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearc
hResultsCount); | |
275 else | |
276 this._searchResultsMessageElement.textContent = ""; | |
277 }, | |
278 | |
279 resetResults: function() | |
280 { | |
281 if (this._searchingView) | |
282 this._searchingView.detach(); | |
283 if (this._notFoundView) | |
284 this._notFoundView.detach(); | |
285 this._searchResultsElement.removeChildren(); | |
286 }, | |
287 | |
288 _resetCounters: function() | |
289 { | |
290 this._searchMatchesCount = 0; | |
291 this._searchResultsCount = 0; | |
292 this._nonEmptySearchResultsCount = 0; | |
293 }, | |
294 | |
295 nothingFound: function() | |
296 { | |
297 this.resetResults(); | |
298 | |
299 if (!this._notFoundView) | |
300 this._notFoundView = new WebInspector.EmptyView(WebInspector.UIStrin
g("No matches found.")); | |
301 this._notFoundView.show(this._searchResultsElement); | |
302 this._searchResultsMessageElement.textContent = WebInspector.UIString("N
o matches found."); | |
303 }, | |
304 | |
305 /** | |
306 * @param {!WebInspector.FileBasedSearchResult} searchResult | |
307 */ | |
308 addSearchResult: function(searchResult) | |
309 { | |
310 this._searchMatchesCount += searchResult.searchMatches.length; | |
311 this._searchResultsCount++; | |
312 if (searchResult.searchMatches.length) | |
313 this._nonEmptySearchResultsCount++; | |
314 this._updateSearchResultsMessage(); | |
315 }, | |
316 | |
317 /** | |
318 * @param {boolean} finished | |
319 */ | |
320 searchFinished: function(finished) | |
321 { | |
322 this._searchMessageElement.textContent = finished ? WebInspector.UIStrin
g("Search finished.") : WebInspector.UIString("Search interrupted."); | |
323 }, | |
324 | |
325 focus: function() | |
326 { | |
327 WebInspector.setCurrentFocusElement(this._search); | |
328 this._search.select(); | |
329 }, | |
330 | |
331 willHide: function() | |
332 { | |
333 this._controller.stopSearch(); | |
334 }, | |
335 | |
336 /** | |
337 * @param {?Event} event | |
338 */ | |
339 _onKeyDown: function(event) | |
340 { | |
341 switch (event.keyCode) { | |
342 case WebInspector.KeyboardShortcut.Keys.Enter.code: | |
343 this._onAction(); | |
344 break; | |
345 } | |
346 }, | |
347 | |
348 _save: function() | |
349 { | |
350 WebInspector.settings.advancedSearchConfig.set(this.searchConfig.toPlain
Object()); | |
351 }, | |
352 | |
353 _load: function() | |
354 { | |
355 var searchConfig = WebInspector.SearchConfig.fromPlainObject(WebInspecto
r.settings.advancedSearchConfig.get()); | |
356 this._search.value = searchConfig.query(); | |
357 this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase(); | |
358 this._regexCheckbox.checked = searchConfig.isRegex(); | |
359 }, | |
360 | |
361 _onAction: function() | |
362 { | |
363 var searchConfig = this.searchConfig; | |
364 if (!searchConfig.query() || !searchConfig.query().length) | |
365 return; | |
366 | |
367 this._save(); | |
368 this._controller.startSearch(searchConfig); | |
369 }, | |
370 | |
371 __proto__: WebInspector.VBox.prototype | |
372 } | |
373 | |
374 /** | |
375 * @constructor | |
376 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
377 */ | |
378 WebInspector.SearchResultsPane = function(searchConfig) | |
379 { | |
380 this._searchConfig = searchConfig; | |
381 this.element = document.createElement("div"); | |
382 } | |
383 | |
384 WebInspector.SearchResultsPane.prototype = { | |
385 /** | |
386 * @return {!WebInspector.ProjectSearchConfig} | |
387 */ | |
388 get searchConfig() | |
389 { | |
390 return this._searchConfig; | |
391 }, | |
392 | |
393 /** | |
394 * @param {!WebInspector.FileBasedSearchResult} searchResult | |
395 */ | |
396 addSearchResult: function(searchResult) { } | |
397 } | |
398 | |
399 /** | |
400 * @constructor | |
401 * @implements {WebInspector.ActionDelegate} | |
402 */ | |
403 WebInspector.AdvancedSearchController.ToggleDrawerViewActionDelegate = function(
) | |
404 { | |
405 } | |
406 | |
407 WebInspector.AdvancedSearchController.ToggleDrawerViewActionDelegate.prototype =
{ | |
408 /** | |
409 * @param {!Event} event | |
410 * @return {boolean} | |
411 */ | |
412 handleAction: function(event) | |
413 { | |
414 if (WebInspector.Dialog.currentInstance()) | |
415 return false; | |
416 var searchView = WebInspector.advancedSearchController._searchView; | |
417 if (!searchView || !searchView.isShowing() || searchView._search !== doc
ument.activeElement) { | |
418 WebInspector.inspectorView.showPanel("sources"); | |
419 WebInspector.advancedSearchController.show(); | |
420 } else { | |
421 WebInspector.inspectorView.closeDrawer(); | |
422 } | |
423 return true; | |
424 } | |
425 } | |
426 | |
427 | |
428 /** | |
429 * @constructor | |
430 * @param {!WebInspector.UISourceCode} uiSourceCode | |
431 * @param {!Array.<!Object>} searchMatches | |
432 */ | |
433 WebInspector.FileBasedSearchResult = function(uiSourceCode, searchMatches) { | |
434 this.uiSourceCode = uiSourceCode; | |
435 this.searchMatches = searchMatches; | |
436 } | |
437 | |
438 /** | |
439 * @interface | |
440 */ | |
441 WebInspector.SearchScope = function() | |
442 { | |
443 } | |
444 | |
445 WebInspector.SearchScope.prototype = { | |
446 /** | |
447 * @param {!WebInspector.SearchConfig} searchConfig | |
448 * @param {!WebInspector.Progress} progress | |
449 * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallba
ck | |
450 * @param {function(boolean)} searchFinishedCallback | |
451 */ | |
452 performSearch: function(searchConfig, progress, searchResultCallback, search
FinishedCallback) { }, | |
453 | |
454 /** | |
455 * @param {!WebInspector.Progress} progress | |
456 * @param {function(boolean)} callback | |
457 */ | |
458 performIndexing: function(progress, callback) { }, | |
459 | |
460 stopSearch: function() { }, | |
461 | |
462 /** | |
463 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
464 * @return {!WebInspector.SearchResultsPane} | |
465 */ | |
466 createSearchResultsPane: function(searchConfig) { } | |
467 } | |
468 | |
469 /** | |
470 * @type {!WebInspector.AdvancedSearchController} | |
471 */ | |
472 WebInspector.advancedSearchController = new WebInspector.AdvancedSearchControlle
r(); | |
473 | |
474 importScript("SearchConfig.js"); | |
475 importScript("FileBasedSearchResultsPane.js"); | |
476 importScript("SourcesSearchScope.js"); | |
OLD | NEW |