| 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 |