OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | |
5 /** | 4 /** |
6 * @constructor | 5 * @unrestricted |
7 * @extends {WebInspector.SearchResultsPane} | |
8 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
9 */ | 6 */ |
10 WebInspector.FileBasedSearchResultsPane = function(searchConfig) | 7 WebInspector.FileBasedSearchResultsPane = class extends WebInspector.SearchResul
tsPane { |
11 { | 8 /** |
12 WebInspector.SearchResultsPane.call(this, searchConfig); | 9 * @param {!WebInspector.ProjectSearchConfig} searchConfig |
| 10 */ |
| 11 constructor(searchConfig) { |
| 12 super(searchConfig); |
13 | 13 |
14 this._searchResults = []; | 14 this._searchResults = []; |
15 this._treeOutline = new TreeOutlineInShadow(); | 15 this._treeOutline = new TreeOutlineInShadow(); |
16 this._treeOutline.registerRequiredCSS("sources/fileBasedSearchResultsPane.cs
s"); | 16 this._treeOutline.registerRequiredCSS('sources/fileBasedSearchResultsPane.cs
s'); |
17 this.element.appendChild(this._treeOutline.element); | 17 this.element.appendChild(this._treeOutline.element); |
18 | 18 |
19 this._matchesExpandedCount = 0; | 19 this._matchesExpandedCount = 0; |
| 20 } |
| 21 |
| 22 /** |
| 23 * @override |
| 24 * @param {!WebInspector.FileBasedSearchResult} searchResult |
| 25 */ |
| 26 addSearchResult(searchResult) { |
| 27 this._searchResults.push(searchResult); |
| 28 var uiSourceCode = searchResult.uiSourceCode; |
| 29 if (!uiSourceCode) |
| 30 return; |
| 31 this._addFileTreeElement(searchResult); |
| 32 } |
| 33 |
| 34 /** |
| 35 * @param {!WebInspector.FileBasedSearchResult} searchResult |
| 36 */ |
| 37 _addFileTreeElement(searchResult) { |
| 38 var fileTreeElement = new WebInspector.FileBasedSearchResultsPane.FileTreeEl
ement(this._searchConfig, searchResult); |
| 39 this._treeOutline.appendChild(fileTreeElement); |
| 40 // Expand until at least a certain number of matches is expanded. |
| 41 if (this._matchesExpandedCount < WebInspector.FileBasedSearchResultsPane.mat
chesExpandedByDefaultCount) |
| 42 fileTreeElement.expand(); |
| 43 this._matchesExpandedCount += searchResult.searchMatches.length; |
| 44 } |
20 }; | 45 }; |
21 | 46 |
22 WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount = 20; | 47 WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount = 20; |
23 WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce = 20; | 48 WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce = 20; |
24 | 49 |
25 WebInspector.FileBasedSearchResultsPane.prototype = { | |
26 /** | |
27 * @override | |
28 * @param {!WebInspector.FileBasedSearchResult} searchResult | |
29 */ | |
30 addSearchResult: function(searchResult) | |
31 { | |
32 this._searchResults.push(searchResult); | |
33 var uiSourceCode = searchResult.uiSourceCode; | |
34 if (!uiSourceCode) | |
35 return; | |
36 this._addFileTreeElement(searchResult); | |
37 }, | |
38 | |
39 /** | |
40 * @param {!WebInspector.FileBasedSearchResult} searchResult | |
41 */ | |
42 _addFileTreeElement: function(searchResult) | |
43 { | |
44 var fileTreeElement = new WebInspector.FileBasedSearchResultsPane.FileTr
eeElement(this._searchConfig, searchResult); | |
45 this._treeOutline.appendChild(fileTreeElement); | |
46 // Expand until at least a certain number of matches is expanded. | |
47 if (this._matchesExpandedCount < WebInspector.FileBasedSearchResultsPane
.matchesExpandedByDefaultCount) | |
48 fileTreeElement.expand(); | |
49 this._matchesExpandedCount += searchResult.searchMatches.length; | |
50 }, | |
51 | |
52 __proto__: WebInspector.SearchResultsPane.prototype | |
53 }; | |
54 | |
55 /** | 50 /** |
56 * @constructor | 51 * @unrestricted |
57 * @extends {TreeElement} | |
58 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
59 * @param {!WebInspector.FileBasedSearchResult} searchResult | |
60 */ | 52 */ |
61 WebInspector.FileBasedSearchResultsPane.FileTreeElement = function(searchConfig,
searchResult) | 53 WebInspector.FileBasedSearchResultsPane.FileTreeElement = class extends TreeElem
ent { |
62 { | 54 /** |
63 TreeElement.call(this, "", true); | 55 * @param {!WebInspector.ProjectSearchConfig} searchConfig |
| 56 * @param {!WebInspector.FileBasedSearchResult} searchResult |
| 57 */ |
| 58 constructor(searchConfig, searchResult) { |
| 59 super('', true); |
64 this._searchConfig = searchConfig; | 60 this._searchConfig = searchConfig; |
65 this._searchResult = searchResult; | 61 this._searchResult = searchResult; |
66 | 62 |
67 this.toggleOnClick = true; | 63 this.toggleOnClick = true; |
68 this.selectable = false; | 64 this.selectable = false; |
| 65 } |
| 66 |
| 67 /** |
| 68 * @override |
| 69 */ |
| 70 onexpand() { |
| 71 if (this._initialized) |
| 72 return; |
| 73 |
| 74 this._updateMatchesUI(); |
| 75 this._initialized = true; |
| 76 } |
| 77 |
| 78 _updateMatchesUI() { |
| 79 this.removeChildren(); |
| 80 var toIndex = Math.min( |
| 81 this._searchResult.searchMatches.length, WebInspector.FileBasedSearchRes
ultsPane.fileMatchesShownAtOnce); |
| 82 if (toIndex < this._searchResult.searchMatches.length) { |
| 83 this._appendSearchMatches(0, toIndex - 1); |
| 84 this._appendShowMoreMatchesElement(toIndex - 1); |
| 85 } else { |
| 86 this._appendSearchMatches(0, toIndex); |
| 87 } |
| 88 } |
| 89 |
| 90 /** |
| 91 * @override |
| 92 */ |
| 93 onattach() { |
| 94 this._updateSearchMatches(); |
| 95 } |
| 96 |
| 97 _updateSearchMatches() { |
| 98 this.listItemElement.classList.add('search-result'); |
| 99 |
| 100 var fileNameSpan = createElement('span'); |
| 101 fileNameSpan.className = 'search-result-file-name'; |
| 102 fileNameSpan.textContent = this._searchResult.uiSourceCode.fullDisplayName()
; |
| 103 this.listItemElement.appendChild(fileNameSpan); |
| 104 |
| 105 var matchesCountSpan = createElement('span'); |
| 106 matchesCountSpan.className = 'search-result-matches-count'; |
| 107 |
| 108 var searchMatchesCount = this._searchResult.searchMatches.length; |
| 109 if (searchMatchesCount === 1) |
| 110 matchesCountSpan.textContent = WebInspector.UIString('(%d match)', searchM
atchesCount); |
| 111 else |
| 112 matchesCountSpan.textContent = WebInspector.UIString('(%d matches)', searc
hMatchesCount); |
| 113 |
| 114 this.listItemElement.appendChild(matchesCountSpan); |
| 115 if (this.expanded) |
| 116 this._updateMatchesUI(); |
| 117 } |
| 118 |
| 119 /** |
| 120 * @param {number} fromIndex |
| 121 * @param {number} toIndex |
| 122 */ |
| 123 _appendSearchMatches(fromIndex, toIndex) { |
| 124 var searchResult = this._searchResult; |
| 125 var uiSourceCode = searchResult.uiSourceCode; |
| 126 var searchMatches = searchResult.searchMatches; |
| 127 |
| 128 var queries = this._searchConfig.queries(); |
| 129 var regexes = []; |
| 130 for (var i = 0; i < queries.length; ++i) |
| 131 regexes.push(createSearchRegex(queries[i], !this._searchConfig.ignoreCase(
), this._searchConfig.isRegex())); |
| 132 |
| 133 for (var i = fromIndex; i < toIndex; ++i) { |
| 134 var lineNumber = searchMatches[i].lineNumber; |
| 135 var lineContent = searchMatches[i].lineContent; |
| 136 var matchRanges = []; |
| 137 for (var j = 0; j < regexes.length; ++j) |
| 138 matchRanges = matchRanges.concat(this._regexMatchRanges(lineContent, reg
exes[j])); |
| 139 |
| 140 var anchor = this._createAnchor(uiSourceCode, lineNumber, matchRanges[0].o
ffset); |
| 141 |
| 142 var numberString = numberToStringWithSpacesPadding(lineNumber + 1, 4); |
| 143 var lineNumberSpan = createElement('span'); |
| 144 lineNumberSpan.classList.add('search-match-line-number'); |
| 145 lineNumberSpan.textContent = numberString; |
| 146 anchor.appendChild(lineNumberSpan); |
| 147 |
| 148 var contentSpan = this._createContentSpan(lineContent, matchRanges); |
| 149 anchor.appendChild(contentSpan); |
| 150 |
| 151 var searchMatchElement = new TreeElement(); |
| 152 searchMatchElement.selectable = false; |
| 153 this.appendChild(searchMatchElement); |
| 154 searchMatchElement.listItemElement.className = 'search-match source-code'; |
| 155 searchMatchElement.listItemElement.appendChild(anchor); |
| 156 } |
| 157 } |
| 158 |
| 159 /** |
| 160 * @param {number} startMatchIndex |
| 161 */ |
| 162 _appendShowMoreMatchesElement(startMatchIndex) { |
| 163 var matchesLeftCount = this._searchResult.searchMatches.length - startMatchI
ndex; |
| 164 var showMoreMatchesText = WebInspector.UIString('Show all matches (%d more).
', matchesLeftCount); |
| 165 this._showMoreMatchesTreeElement = new TreeElement(showMoreMatchesText); |
| 166 this.appendChild(this._showMoreMatchesTreeElement); |
| 167 this._showMoreMatchesTreeElement.listItemElement.classList.add('show-more-ma
tches'); |
| 168 this._showMoreMatchesTreeElement.onselect = this._showMoreMatchesElementSele
cted.bind(this, startMatchIndex); |
| 169 } |
| 170 |
| 171 /** |
| 172 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 173 * @param {number} lineNumber |
| 174 * @param {number} columnNumber |
| 175 * @return {!Element} |
| 176 */ |
| 177 _createAnchor(uiSourceCode, lineNumber, columnNumber) { |
| 178 return WebInspector.Linkifier.linkifyUsingRevealer(uiSourceCode.uiLocation(l
ineNumber, columnNumber), ''); |
| 179 } |
| 180 |
| 181 /** |
| 182 * @param {string} lineContent |
| 183 * @param {!Array.<!WebInspector.SourceRange>} matchRanges |
| 184 */ |
| 185 _createContentSpan(lineContent, matchRanges) { |
| 186 var contentSpan = createElement('span'); |
| 187 contentSpan.className = 'search-match-content'; |
| 188 contentSpan.textContent = lineContent; |
| 189 WebInspector.highlightRangesWithStyleClass(contentSpan, matchRanges, 'highli
ghted-match'); |
| 190 return contentSpan; |
| 191 } |
| 192 |
| 193 /** |
| 194 * @param {string} lineContent |
| 195 * @param {!RegExp} regex |
| 196 * @return {!Array.<!WebInspector.SourceRange>} |
| 197 */ |
| 198 _regexMatchRanges(lineContent, regex) { |
| 199 regex.lastIndex = 0; |
| 200 var match; |
| 201 var matchRanges = []; |
| 202 while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lineCon
tent))) |
| 203 matchRanges.push(new WebInspector.SourceRange(match.index, match[0].length
)); |
| 204 |
| 205 return matchRanges; |
| 206 } |
| 207 |
| 208 /** |
| 209 * @param {number} startMatchIndex |
| 210 * @return {boolean} |
| 211 */ |
| 212 _showMoreMatchesElementSelected(startMatchIndex) { |
| 213 this.removeChild(this._showMoreMatchesTreeElement); |
| 214 this._appendSearchMatches(startMatchIndex, this._searchResult.searchMatches.
length); |
| 215 return false; |
| 216 } |
69 }; | 217 }; |
70 | |
71 WebInspector.FileBasedSearchResultsPane.FileTreeElement.prototype = { | |
72 onexpand: function() | |
73 { | |
74 if (this._initialized) | |
75 return; | |
76 | |
77 this._updateMatchesUI(); | |
78 this._initialized = true; | |
79 }, | |
80 | |
81 _updateMatchesUI: function() | |
82 { | |
83 this.removeChildren(); | |
84 var toIndex = Math.min(this._searchResult.searchMatches.length, WebInspe
ctor.FileBasedSearchResultsPane.fileMatchesShownAtOnce); | |
85 if (toIndex < this._searchResult.searchMatches.length) { | |
86 this._appendSearchMatches(0, toIndex - 1); | |
87 this._appendShowMoreMatchesElement(toIndex - 1); | |
88 } else { | |
89 this._appendSearchMatches(0, toIndex); | |
90 } | |
91 }, | |
92 | |
93 onattach: function() | |
94 { | |
95 this._updateSearchMatches(); | |
96 }, | |
97 | |
98 _updateSearchMatches: function() | |
99 { | |
100 this.listItemElement.classList.add("search-result"); | |
101 | |
102 var fileNameSpan = createElement("span"); | |
103 fileNameSpan.className = "search-result-file-name"; | |
104 fileNameSpan.textContent = this._searchResult.uiSourceCode.fullDisplayNa
me(); | |
105 this.listItemElement.appendChild(fileNameSpan); | |
106 | |
107 var matchesCountSpan = createElement("span"); | |
108 matchesCountSpan.className = "search-result-matches-count"; | |
109 | |
110 var searchMatchesCount = this._searchResult.searchMatches.length; | |
111 if (searchMatchesCount === 1) | |
112 matchesCountSpan.textContent = WebInspector.UIString("(%d match)", s
earchMatchesCount); | |
113 else | |
114 matchesCountSpan.textContent = WebInspector.UIString("(%d matches)",
searchMatchesCount); | |
115 | |
116 this.listItemElement.appendChild(matchesCountSpan); | |
117 if (this.expanded) | |
118 this._updateMatchesUI(); | |
119 }, | |
120 | |
121 /** | |
122 * @param {number} fromIndex | |
123 * @param {number} toIndex | |
124 */ | |
125 _appendSearchMatches: function(fromIndex, toIndex) | |
126 { | |
127 var searchResult = this._searchResult; | |
128 var uiSourceCode = searchResult.uiSourceCode; | |
129 var searchMatches = searchResult.searchMatches; | |
130 | |
131 var queries = this._searchConfig.queries(); | |
132 var regexes = []; | |
133 for (var i = 0; i < queries.length; ++i) | |
134 regexes.push(createSearchRegex(queries[i], !this._searchConfig.ignor
eCase(), this._searchConfig.isRegex())); | |
135 | |
136 for (var i = fromIndex; i < toIndex; ++i) { | |
137 var lineNumber = searchMatches[i].lineNumber; | |
138 var lineContent = searchMatches[i].lineContent; | |
139 var matchRanges = []; | |
140 for (var j = 0; j < regexes.length; ++j) | |
141 matchRanges = matchRanges.concat(this._regexMatchRanges(lineCont
ent, regexes[j])); | |
142 | |
143 var anchor = this._createAnchor(uiSourceCode, lineNumber, matchRange
s[0].offset); | |
144 | |
145 var numberString = numberToStringWithSpacesPadding(lineNumber + 1, 4
); | |
146 var lineNumberSpan = createElement("span"); | |
147 lineNumberSpan.classList.add("search-match-line-number"); | |
148 lineNumberSpan.textContent = numberString; | |
149 anchor.appendChild(lineNumberSpan); | |
150 | |
151 var contentSpan = this._createContentSpan(lineContent, matchRanges); | |
152 anchor.appendChild(contentSpan); | |
153 | |
154 var searchMatchElement = new TreeElement(); | |
155 searchMatchElement.selectable = false; | |
156 this.appendChild(searchMatchElement); | |
157 searchMatchElement.listItemElement.className = "search-match source-
code"; | |
158 searchMatchElement.listItemElement.appendChild(anchor); | |
159 } | |
160 }, | |
161 | |
162 /** | |
163 * @param {number} startMatchIndex | |
164 */ | |
165 _appendShowMoreMatchesElement: function(startMatchIndex) | |
166 { | |
167 var matchesLeftCount = this._searchResult.searchMatches.length - startMa
tchIndex; | |
168 var showMoreMatchesText = WebInspector.UIString("Show all matches (%d mo
re).", matchesLeftCount); | |
169 this._showMoreMatchesTreeElement = new TreeElement(showMoreMatchesText); | |
170 this.appendChild(this._showMoreMatchesTreeElement); | |
171 this._showMoreMatchesTreeElement.listItemElement.classList.add("show-mor
e-matches"); | |
172 this._showMoreMatchesTreeElement.onselect = this._showMoreMatchesElement
Selected.bind(this, startMatchIndex); | |
173 }, | |
174 | |
175 /** | |
176 * @param {!WebInspector.UISourceCode} uiSourceCode | |
177 * @param {number} lineNumber | |
178 * @param {number} columnNumber | |
179 * @return {!Element} | |
180 */ | |
181 _createAnchor: function(uiSourceCode, lineNumber, columnNumber) | |
182 { | |
183 return WebInspector.Linkifier.linkifyUsingRevealer(uiSourceCode.uiLocati
on(lineNumber, columnNumber), ""); | |
184 }, | |
185 | |
186 /** | |
187 * @param {string} lineContent | |
188 * @param {!Array.<!WebInspector.SourceRange>} matchRanges | |
189 */ | |
190 _createContentSpan: function(lineContent, matchRanges) | |
191 { | |
192 var contentSpan = createElement("span"); | |
193 contentSpan.className = "search-match-content"; | |
194 contentSpan.textContent = lineContent; | |
195 WebInspector.highlightRangesWithStyleClass(contentSpan, matchRanges, "hi
ghlighted-match"); | |
196 return contentSpan; | |
197 }, | |
198 | |
199 /** | |
200 * @param {string} lineContent | |
201 * @param {!RegExp} regex | |
202 * @return {!Array.<!WebInspector.SourceRange>} | |
203 */ | |
204 _regexMatchRanges: function(lineContent, regex) | |
205 { | |
206 regex.lastIndex = 0; | |
207 var match; | |
208 var matchRanges = []; | |
209 while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lin
eContent))) | |
210 matchRanges.push(new WebInspector.SourceRange(match.index, match[0].
length)); | |
211 | |
212 return matchRanges; | |
213 }, | |
214 | |
215 /** | |
216 * @param {number} startMatchIndex | |
217 * @return {boolean} | |
218 */ | |
219 _showMoreMatchesElementSelected: function(startMatchIndex) | |
220 { | |
221 this.removeChild(this._showMoreMatchesTreeElement); | |
222 this._appendSearchMatches(startMatchIndex, this._searchResult.searchMatc
hes.length); | |
223 return false; | |
224 }, | |
225 | |
226 __proto__: TreeElement.prototype | |
227 }; | |
OLD | NEW |