Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / sources / AdvancedSearchView.js
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6  * @constructor
7  * @extends {WebInspector.VBox}
8  */
9 WebInspector.AdvancedSearchView = function()
10 {
11     WebInspector.VBox.call(this);
12
13     this._searchId = 0;
14
15     this.element.classList.add("search-view");
16
17     this._searchPanelElement = this.element.createChild("div", "search-drawer-header");
18     this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(this), false);
19
20     this._searchResultsElement = this.element.createChild("div");
21     this._searchResultsElement.className = "search-results";
22
23     this._search = this._searchPanelElement.createChild("input");
24     this._search.placeholder = WebInspector.UIString("Search sources");
25     this._search.setAttribute("type", "text");
26     this._search.classList.add("search-config-search");
27     this._search.setAttribute("results", "0");
28     this._search.setAttribute("size", 30);
29
30     this._ignoreCaseLabel = this._searchPanelElement.createChild("label");
31     this._ignoreCaseLabel.classList.add("search-config-label");
32     this._ignoreCaseCheckbox = this._ignoreCaseLabel.createChild("input");
33     this._ignoreCaseCheckbox.setAttribute("type", "checkbox");
34     this._ignoreCaseCheckbox.classList.add("search-config-checkbox");
35     this._ignoreCaseLabel.createTextChild(WebInspector.UIString("Ignore case"));
36
37     this._regexLabel = this._searchPanelElement.createChild("label");
38     this._regexLabel.classList.add("search-config-label");
39     this._regexCheckbox = this._regexLabel.createChild("input");
40     this._regexCheckbox.setAttribute("type", "checkbox");
41     this._regexCheckbox.classList.add("search-config-checkbox");
42     this._regexLabel.createTextChild(WebInspector.UIString("Regular expression"));
43
44     this._searchStatusBarElement = this.element.createChild("div", "search-status-bar-summary");
45     this._searchMessageElement = this._searchStatusBarElement.createChild("div", "search-message");
46     this._searchProgressPlaceholderElement = this._searchStatusBarElement.createChild("div");
47     this._searchStatusBarElement.createChild("div", "search-message-spacer");
48     this._searchResultsMessageElement = this._searchStatusBarElement.createChild("div", "search-message");
49
50     WebInspector.settings.advancedSearchConfig = WebInspector.settings.createSetting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false).toPlainObject());
51     this._load();
52     WebInspector.AdvancedSearchView._instance = this;
53     /** @type {!WebInspector.SearchScope} */
54     this._searchScope = new WebInspector.SourcesSearchScope();
55     if (WebInspector.AdvancedSearchView._pendingQuery) {
56         this._toggle(WebInspector.AdvancedSearchView._pendingQuery);
57         delete WebInspector.AdvancedSearchView._pendingQuery;
58     }
59 }
60
61 WebInspector.AdvancedSearchView.prototype = {
62     /**
63      * @return {!WebInspector.SearchConfig}
64      */
65     _buildSearchConfig: function()
66     {
67         return new WebInspector.SearchConfig(this._search.value, this._ignoreCaseCheckbox.checked, this._regexCheckbox.checked);
68     },
69
70     /**
71      * @param {string} queryCandidate
72      */
73     _toggle: function(queryCandidate)
74     {
75         if (queryCandidate)
76             this._search.value = queryCandidate;
77         this.focus();
78
79         this._startIndexing();
80     },
81
82     /**
83      * @param {boolean} finished
84      */
85     _onIndexingFinished: function(finished)
86     {
87         delete this._isIndexing;
88         this._indexingFinished(finished);
89         if (!finished)
90             delete this._pendingSearchConfig;
91         if (!this._pendingSearchConfig)
92             return;
93         var searchConfig = this._pendingSearchConfig;
94         delete this._pendingSearchConfig;
95         this._innerStartSearch(searchConfig);
96     },
97
98     _startIndexing: function()
99     {
100         this._isIndexing = true;
101         if (this._progressIndicator)
102             this._progressIndicator.done();
103         this._progressIndicator = new WebInspector.ProgressIndicator();
104         this._indexingStarted(this._progressIndicator);
105         this._searchScope.performIndexing(this._progressIndicator, this._onIndexingFinished.bind(this));
106     },
107
108     /**
109      * @param {number} searchId
110      * @param {!WebInspector.FileBasedSearchResult} searchResult
111      */
112     _onSearchResult: function(searchId, searchResult)
113     {
114         if (searchId !== this._searchId)
115             return;
116         this._addSearchResult(searchResult);
117         if (!searchResult.searchMatches.length)
118             return;
119         if (!this._searchResultsPane)
120             this._searchResultsPane = this._searchScope.createSearchResultsPane(this._searchConfig);
121         this._resetResults();
122         this._searchResultsElement.appendChild(this._searchResultsPane.element);
123         this._searchResultsPane.addSearchResult(searchResult);
124     },
125
126     /**
127      * @param {number} searchId
128      * @param {boolean} finished
129      */
130     _onSearchFinished: function(searchId, finished)
131     {
132         if (searchId !== this._searchId)
133             return;
134         if (!this._searchResultsPane)
135             this._nothingFound();
136         this._searchFinished(finished);
137         delete this._searchConfig;
138     },
139
140     /**
141      * @param {!WebInspector.SearchConfig} searchConfig
142      */
143     _startSearch: function(searchConfig)
144     {
145         this._resetSearch();
146         ++this._searchId;
147         if (!this._isIndexing)
148             this._startIndexing();
149         this._pendingSearchConfig = searchConfig;
150     },
151
152     /**
153      * @param {!WebInspector.SearchConfig} searchConfig
154      */
155     _innerStartSearch: function(searchConfig)
156     {
157         this._searchConfig = searchConfig;
158         if (this._progressIndicator)
159             this._progressIndicator.done();
160         this._progressIndicator = new WebInspector.ProgressIndicator();
161         this._searchStarted(this._progressIndicator);
162         this._searchScope.performSearch(searchConfig, this._progressIndicator, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bind(this, this._searchId));
163     },
164
165     _resetSearch: function()
166     {
167         this._stopSearch();
168
169         if (this._searchResultsPane) {
170             this._resetResults();
171             delete this._searchResultsPane;
172         }
173     },
174
175     _stopSearch: function()
176     {
177         if (this._progressIndicator)
178             this._progressIndicator.cancel();
179         if (this._searchScope)
180             this._searchScope.stopSearch();
181         delete this._searchConfig;
182     },
183
184     /**
185      * @param {!WebInspector.ProgressIndicator} progressIndicator
186      */
187     _searchStarted: function(progressIndicator)
188     {
189         this._resetResults();
190         this._resetCounters();
191
192         this._searchMessageElement.textContent = WebInspector.UIString("Searching\u2026");
193         progressIndicator.show(this._searchProgressPlaceholderElement);
194         this._updateSearchResultsMessage();
195
196         if (!this._searchingView)
197             this._searchingView = new WebInspector.EmptyView(WebInspector.UIString("Searching\u2026"));
198         this._searchingView.show(this._searchResultsElement);
199     },
200
201     /**
202      * @param {!WebInspector.ProgressIndicator} progressIndicator
203      */
204     _indexingStarted: function(progressIndicator)
205     {
206         this._searchMessageElement.textContent = WebInspector.UIString("Indexing\u2026");
207         progressIndicator.show(this._searchProgressPlaceholderElement);
208     },
209
210     /**
211      * @param {boolean} finished
212      */
213     _indexingFinished: function(finished)
214     {
215         this._searchMessageElement.textContent = finished ? "" : WebInspector.UIString("Indexing interrupted.");
216     },
217
218     _updateSearchResultsMessage: function()
219     {
220         if (this._searchMatchesCount && this._searchResultsCount)
221             this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount);
222         else
223             this._searchResultsMessageElement.textContent = "";
224     },
225
226     _resetResults: function()
227     {
228         if (this._searchingView)
229             this._searchingView.detach();
230         if (this._notFoundView)
231             this._notFoundView.detach();
232         this._searchResultsElement.removeChildren();
233     },
234
235     _resetCounters: function()
236     {
237         this._searchMatchesCount = 0;
238         this._searchResultsCount = 0;
239         this._nonEmptySearchResultsCount = 0;
240     },
241
242     _nothingFound: function()
243     {
244         this._resetResults();
245
246         if (!this._notFoundView)
247             this._notFoundView = new WebInspector.EmptyView(WebInspector.UIString("No matches found."));
248         this._notFoundView.show(this._searchResultsElement);
249         this._searchResultsMessageElement.textContent = WebInspector.UIString("No matches found.");
250     },
251
252     /**
253      * @param {!WebInspector.FileBasedSearchResult} searchResult
254      */
255     _addSearchResult: function(searchResult)
256     {
257         this._searchMatchesCount += searchResult.searchMatches.length;
258         this._searchResultsCount++;
259         if (searchResult.searchMatches.length)
260             this._nonEmptySearchResultsCount++;
261         this._updateSearchResultsMessage();
262     },
263
264     /**
265      * @param {boolean} finished
266      */
267     _searchFinished: function(finished)
268     {
269         this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted.");
270     },
271
272     focus: function()
273     {
274         WebInspector.setCurrentFocusElement(this._search);
275         this._search.select();
276     },
277
278     willHide: function()
279     {
280         this._stopSearch();
281     },
282
283     /**
284      * @param {!Event} event
285      */
286     _onKeyDown: function(event)
287     {
288         switch (event.keyCode) {
289         case WebInspector.KeyboardShortcut.Keys.Enter.code:
290             this._onAction();
291             break;
292         }
293     },
294
295     _save: function()
296     {
297         WebInspector.settings.advancedSearchConfig.set(this._buildSearchConfig().toPlainObject());
298     },
299
300     _load: function()
301     {
302         var searchConfig = WebInspector.SearchConfig.fromPlainObject(WebInspector.settings.advancedSearchConfig.get());
303         this._search.value = searchConfig.query();
304         this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase();
305         this._regexCheckbox.checked = searchConfig.isRegex();
306     },
307
308     _onAction: function()
309     {
310         var searchConfig = this._buildSearchConfig();
311         if (!searchConfig.query() || !searchConfig.query().length)
312             return;
313
314         this._save();
315         this._startSearch(searchConfig);
316     },
317
318     __proto__: WebInspector.VBox.prototype
319 }
320
321 /**
322  * @constructor
323  * @param {!WebInspector.ProjectSearchConfig} searchConfig
324  */
325 WebInspector.SearchResultsPane = function(searchConfig)
326 {
327     this._searchConfig = searchConfig;
328     this.element = createElement("div");
329 }
330
331 WebInspector.SearchResultsPane.prototype = {
332     /**
333      * @return {!WebInspector.ProjectSearchConfig}
334      */
335     get searchConfig()
336     {
337         return this._searchConfig;
338     },
339
340     /**
341      * @param {!WebInspector.FileBasedSearchResult} searchResult
342      */
343     addSearchResult: function(searchResult) { }
344 }
345
346 /**
347  * @constructor
348  * @implements {WebInspector.ActionDelegate}
349  */
350 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate = function()
351 {
352 }
353
354 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate.prototype = {
355     /**
356      * @return {boolean}
357      * // FIXME: remove this suppression.
358      * @suppressGlobalPropertiesCheck
359      */
360     handleAction: function()
361     {
362         var searchView = WebInspector.AdvancedSearchView._instance;
363         if (!searchView || !searchView.isShowing() || searchView._search !== document.activeElement) {
364             var selection = window.getSelection();
365             var queryCandidate = "";
366             if (selection.rangeCount)
367                 queryCandidate = selection.toString().replace(/\r?\n.*/, "");
368
369             WebInspector.inspectorView.setCurrentPanel(WebInspector.SourcesPanel.instance());
370             WebInspector.inspectorView.showViewInDrawer("sources.search");
371             if (WebInspector.AdvancedSearchView._instance)
372                 WebInspector.AdvancedSearchView._instance._toggle(queryCandidate);
373             else
374                 WebInspector.AdvancedSearchView._pendingQuery = queryCandidate;
375         } else {
376             WebInspector.inspectorView.closeDrawer();
377         }
378         return true;
379     }
380 }
381
382 /**
383  * @constructor
384  * @param {!WebInspector.UISourceCode} uiSourceCode
385  * @param {!Array.<!Object>} searchMatches
386  */
387 WebInspector.FileBasedSearchResult = function(uiSourceCode, searchMatches) {
388     this.uiSourceCode = uiSourceCode;
389     this.searchMatches = searchMatches;
390 }
391
392 /**
393  * @interface
394  */
395 WebInspector.SearchScope = function()
396 {
397 }
398
399 WebInspector.SearchScope.prototype = {
400     /**
401      * @param {!WebInspector.SearchConfig} searchConfig
402      * @param {!WebInspector.Progress} progress
403      * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallback
404      * @param {function(boolean)} searchFinishedCallback
405      */
406     performSearch: function(searchConfig, progress, searchResultCallback, searchFinishedCallback) { },
407
408     /**
409      * @param {!WebInspector.Progress} progress
410      * @param {function(boolean)} callback
411      */
412     performIndexing: function(progress, callback) { },
413
414     stopSearch: function() { },
415
416     /**
417      * @param {!WebInspector.ProjectSearchConfig} searchConfig
418      * @return {!WebInspector.SearchResultsPane}
419      */
420     createSearchResultsPane: function(searchConfig) { }
421 }