Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1152)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/source_frame/SourceFrame.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer 11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the 12 * in the documentation and/or other materials provided with the
13 * distribution. 13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its 14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from 15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission. 16 * this software without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30
31 /** 30 /**
32 * @constructor
33 * @extends {WebInspector.SimpleView}
34 * @implements {WebInspector.Searchable} 31 * @implements {WebInspector.Searchable}
35 * @implements {WebInspector.Replaceable} 32 * @implements {WebInspector.Replaceable}
36 * @implements {WebInspector.SourcesTextEditorDelegate} 33 * @implements {WebInspector.SourcesTextEditorDelegate}
37 * @param {string} url 34 * @unrestricted
38 * @param {function(): !Promise<?string>} lazyContent
39 */ 35 */
40 WebInspector.SourceFrame = function(url, lazyContent) 36 WebInspector.SourceFrame = class extends WebInspector.SimpleView {
41 { 37 /**
42 WebInspector.SimpleView.call(this, WebInspector.UIString("Source")); 38 * @param {string} url
39 * @param {function(): !Promise<?string>} lazyContent
40 */
41 constructor(url, lazyContent) {
42 super(WebInspector.UIString('Source'));
43 43
44 this._url = url; 44 this._url = url;
45 this._lazyContent = lazyContent; 45 this._lazyContent = lazyContent;
46 46
47 this._textEditor = new WebInspector.SourcesTextEditor(this); 47 this._textEditor = new WebInspector.SourcesTextEditor(this);
48 48
49 this._currentSearchResultIndex = -1; 49 this._currentSearchResultIndex = -1;
50 this._searchResults = []; 50 this._searchResults = [];
51 51
52 this._textEditor.addEventListener(WebInspector.SourcesTextEditor.Events.Edit orFocused, this._resetCurrentSearchResultIndex, this); 52 this._textEditor.addEventListener(
53 this._textEditor.addEventListener(WebInspector.SourcesTextEditor.Events.Sele ctionChanged, this._updateSourcePosition, this); 53 WebInspector.SourcesTextEditor.Events.EditorFocused, this._resetCurrentS earchResultIndex, this);
54 this._textEditor.addEventListener(WebInspector.SourcesTextEditor.Events.Text Changed, event => this.onTextChanged(event.data.oldRange, event.data.newRange)); 54 this._textEditor.addEventListener(
55 WebInspector.SourcesTextEditor.Events.SelectionChanged, this._updateSour cePosition, this);
56 this._textEditor.addEventListener(
57 WebInspector.SourcesTextEditor.Events.TextChanged,
58 event => this.onTextChanged(event.data.oldRange, event.data.newRange));
55 59
56 this._shortcuts = {}; 60 this._shortcuts = {};
57 this.element.addEventListener("keydown", this._handleKeyDown.bind(this), fal se); 61 this.element.addEventListener('keydown', this._handleKeyDown.bind(this), fal se);
58 62
59 this._sourcePosition = new WebInspector.ToolbarText(); 63 this._sourcePosition = new WebInspector.ToolbarText();
60 64
61 /** 65 /**
62 * @type {?WebInspector.SearchableView} 66 * @type {?WebInspector.SearchableView}
63 */ 67 */
64 this._searchableView = null; 68 this._searchableView = null;
65 this._editable = false; 69 this._editable = false;
70 }
71
72 /**
73 * @param {boolean} editable
74 */
75 setEditable(editable) {
76 this._editable = editable;
77 this._textEditor.setReadOnly(editable);
78 }
79
80 /**
81 * @param {number} key
82 * @param {function():boolean} handler
83 */
84 addShortcut(key, handler) {
85 this._shortcuts[key] = handler;
86 }
87
88 /**
89 * @override
90 */
91 wasShown() {
92 this._ensureContentLoaded();
93 this._textEditor.show(this.element);
94 this._editorAttached = true;
95 this._wasShownOrLoaded();
96 }
97
98 /**
99 * @return {boolean}
100 */
101 isEditorShowing() {
102 return this.isShowing() && this._editorAttached;
103 }
104
105 /**
106 * @override
107 */
108 willHide() {
109 super.willHide();
110
111 this._clearPositionToReveal();
112 }
113
114 /**
115 * @override
116 * @return {!Array<!WebInspector.ToolbarItem>}
117 */
118 syncToolbarItems() {
119 return [this._sourcePosition];
120 }
121
122 get loaded() {
123 return this._loaded;
124 }
125
126 get textEditor() {
127 return this._textEditor;
128 }
129
130 _ensureContentLoaded() {
131 if (!this._contentRequested) {
132 this._contentRequested = true;
133 this._lazyContent().then(this.setContent.bind(this));
134 }
135 }
136
137 /**
138 * @param {number} line 0-based
139 * @param {number=} column
140 * @param {boolean=} shouldHighlight
141 */
142 revealPosition(line, column, shouldHighlight) {
143 this._clearLineToScrollTo();
144 this._clearSelectionToSet();
145 this._positionToReveal = {line: line, column: column, shouldHighlight: shoul dHighlight};
146 this._innerRevealPositionIfNeeded();
147 }
148
149 _innerRevealPositionIfNeeded() {
150 if (!this._positionToReveal)
151 return;
152
153 if (!this.loaded || !this.isEditorShowing())
154 return;
155
156 this._textEditor.revealPosition(
157 this._positionToReveal.line, this._positionToReveal.column, this._positi onToReveal.shouldHighlight);
158 delete this._positionToReveal;
159 }
160
161 _clearPositionToReveal() {
162 this._textEditor.clearPositionHighlight();
163 delete this._positionToReveal;
164 }
165
166 /**
167 * @param {number} line
168 */
169 scrollToLine(line) {
170 this._clearPositionToReveal();
171 this._lineToScrollTo = line;
172 this._innerScrollToLineIfNeeded();
173 }
174
175 _innerScrollToLineIfNeeded() {
176 if (typeof this._lineToScrollTo === 'number') {
177 if (this.loaded && this.isEditorShowing()) {
178 this._textEditor.scrollToLine(this._lineToScrollTo);
179 delete this._lineToScrollTo;
180 }
181 }
182 }
183
184 _clearLineToScrollTo() {
185 delete this._lineToScrollTo;
186 }
187
188 /**
189 * @return {!WebInspector.TextRange}
190 */
191 selection() {
192 return this.textEditor.selection();
193 }
194
195 /**
196 * @param {!WebInspector.TextRange} textRange
197 */
198 setSelection(textRange) {
199 this._selectionToSet = textRange;
200 this._innerSetSelectionIfNeeded();
201 }
202
203 _innerSetSelectionIfNeeded() {
204 if (this._selectionToSet && this.loaded && this.isEditorShowing()) {
205 this._textEditor.setSelection(this._selectionToSet);
206 delete this._selectionToSet;
207 }
208 }
209
210 _clearSelectionToSet() {
211 delete this._selectionToSet;
212 }
213
214 _wasShownOrLoaded() {
215 this._innerRevealPositionIfNeeded();
216 this._innerSetSelectionIfNeeded();
217 this._innerScrollToLineIfNeeded();
218 }
219
220 /**
221 * @param {!WebInspector.TextRange} oldRange
222 * @param {!WebInspector.TextRange} newRange
223 */
224 onTextChanged(oldRange, newRange) {
225 if (this._searchConfig && this._searchableView)
226 this.performSearch(this._searchConfig, false, false);
227 }
228
229 /**
230 * @param {string} content
231 * @param {string} mimeType
232 * @return {string}
233 */
234 _simplifyMimeType(content, mimeType) {
235 if (!mimeType)
236 return '';
237 if (mimeType.indexOf('javascript') >= 0 || mimeType.indexOf('jscript') >= 0 || mimeType.indexOf('ecmascript') >= 0)
238 return 'text/javascript';
239 // A hack around the fact that files with "php" extension might be either st andalone or html embedded php scripts.
240 if (mimeType === 'text/x-php' && content.match(/\<\?.*\?\>/g))
241 return 'application/x-httpd-php';
242 return mimeType;
243 }
244
245 /**
246 * @param {string} highlighterType
247 */
248 setHighlighterType(highlighterType) {
249 this._highlighterType = highlighterType;
250 this._updateHighlighterType('');
251 }
252
253 /**
254 * @param {string} content
255 */
256 _updateHighlighterType(content) {
257 this._textEditor.setMimeType(this._simplifyMimeType(content, this._highlight erType));
258 }
259
260 /**
261 * @param {?string} content
262 */
263 setContent(content) {
264 if (!this._loaded) {
265 this._loaded = true;
266 this._textEditor.setText(content || '');
267 this._textEditor.markClean();
268 } else {
269 var scrollTop = this._textEditor.scrollTop();
270 var selection = this._textEditor.selection();
271 this._textEditor.setText(content || '');
272 this._textEditor.setScrollTop(scrollTop);
273 this._textEditor.setSelection(selection);
274 }
275
276 this._updateHighlighterType(content || '');
277 this._wasShownOrLoaded();
278
279 if (this._delayedFindSearchMatches) {
280 this._delayedFindSearchMatches();
281 delete this._delayedFindSearchMatches;
282 }
283 this.onTextEditorContentSet();
284 }
285
286 onTextEditorContentSet() {
287 }
288
289 /**
290 * @param {?WebInspector.SearchableView} view
291 */
292 setSearchableView(view) {
293 this._searchableView = view;
294 }
295
296 /**
297 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
298 * @param {boolean} shouldJump
299 * @param {boolean} jumpBackwards
300 */
301 _doFindSearchMatches(searchConfig, shouldJump, jumpBackwards) {
302 this._currentSearchResultIndex = -1;
303 this._searchResults = [];
304
305 var regex = searchConfig.toSearchRegex();
306 this._searchRegex = regex;
307 this._searchResults = this._collectRegexMatches(regex);
308
309 if (this._searchableView)
310 this._searchableView.updateSearchMatchesCount(this._searchResults.length);
311
312 if (!this._searchResults.length)
313 this._textEditor.cancelSearchResultsHighlight();
314 else if (shouldJump && jumpBackwards)
315 this.jumpToPreviousSearchResult();
316 else if (shouldJump)
317 this.jumpToNextSearchResult();
318 else
319 this._textEditor.highlightSearchResults(regex, null);
320 }
321
322 /**
323 * @override
324 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
325 * @param {boolean} shouldJump
326 * @param {boolean=} jumpBackwards
327 */
328 performSearch(searchConfig, shouldJump, jumpBackwards) {
329 if (this._searchableView)
330 this._searchableView.updateSearchMatchesCount(0);
331
332 this._resetSearch();
333 this._searchConfig = searchConfig;
334 if (this.loaded)
335 this._doFindSearchMatches(searchConfig, shouldJump, !!jumpBackwards);
336 else
337 this._delayedFindSearchMatches = this._doFindSearchMatches.bind(this, sear chConfig, shouldJump, !!jumpBackwards);
338
339 this._ensureContentLoaded();
340 }
341
342 _resetCurrentSearchResultIndex() {
343 if (!this._searchResults.length)
344 return;
345 this._currentSearchResultIndex = -1;
346 if (this._searchableView)
347 this._searchableView.updateCurrentMatchIndex(this._currentSearchResultInde x);
348 this._textEditor.highlightSearchResults(this._searchRegex, null);
349 }
350
351 _resetSearch() {
352 delete this._searchConfig;
353 delete this._delayedFindSearchMatches;
354 this._currentSearchResultIndex = -1;
355 this._searchResults = [];
356 delete this._searchRegex;
357 }
358
359 /**
360 * @override
361 */
362 searchCanceled() {
363 var range = this._currentSearchResultIndex !== -1 ? this._searchResults[this ._currentSearchResultIndex] : null;
364 this._resetSearch();
365 if (!this.loaded)
366 return;
367 this._textEditor.cancelSearchResultsHighlight();
368 if (range)
369 this.setSelection(range);
370 }
371
372 /**
373 * @return {boolean}
374 */
375 hasSearchResults() {
376 return this._searchResults.length > 0;
377 }
378
379 jumpToFirstSearchResult() {
380 this.jumpToSearchResult(0);
381 }
382
383 jumpToLastSearchResult() {
384 this.jumpToSearchResult(this._searchResults.length - 1);
385 }
386
387 /**
388 * @return {number}
389 */
390 _searchResultIndexForCurrentSelection() {
391 return this._searchResults.lowerBound(
392 this._textEditor.selection().collapseToEnd(), WebInspector.TextRange.com parator);
393 }
394
395 /**
396 * @override
397 */
398 jumpToNextSearchResult() {
399 var currentIndex = this._searchResultIndexForCurrentSelection();
400 var nextIndex = this._currentSearchResultIndex === -1 ? currentIndex : curre ntIndex + 1;
401 this.jumpToSearchResult(nextIndex);
402 }
403
404 /**
405 * @override
406 */
407 jumpToPreviousSearchResult() {
408 var currentIndex = this._searchResultIndexForCurrentSelection();
409 this.jumpToSearchResult(currentIndex - 1);
410 }
411
412 /**
413 * @override
414 * @return {boolean}
415 */
416 supportsCaseSensitiveSearch() {
417 return true;
418 }
419
420 /**
421 * @override
422 * @return {boolean}
423 */
424 supportsRegexSearch() {
425 return true;
426 }
427
428 get currentSearchResultIndex() {
429 return this._currentSearchResultIndex;
430 }
431
432 jumpToSearchResult(index) {
433 if (!this.loaded || !this._searchResults.length)
434 return;
435 this._currentSearchResultIndex = (index + this._searchResults.length) % this ._searchResults.length;
436 if (this._searchableView)
437 this._searchableView.updateCurrentMatchIndex(this._currentSearchResultInde x);
438 this._textEditor.highlightSearchResults(this._searchRegex, this._searchResul ts[this._currentSearchResultIndex]);
439 }
440
441 /**
442 * @override
443 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
444 * @param {string} replacement
445 */
446 replaceSelectionWith(searchConfig, replacement) {
447 var range = this._searchResults[this._currentSearchResultIndex];
448 if (!range)
449 return;
450 this._textEditor.highlightSearchResults(this._searchRegex, null);
451
452 var oldText = this._textEditor.text(range);
453 var regex = searchConfig.toSearchRegex();
454 var text;
455 if (regex.__fromRegExpQuery)
456 text = oldText.replace(regex, replacement);
457 else
458 text = oldText.replace(regex, function() {
459 return replacement;
460 });
461
462 var newRange = this._textEditor.editRange(range, text);
463 this._textEditor.setSelection(newRange.collapseToEnd());
464 }
465
466 /**
467 * @override
468 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
469 * @param {string} replacement
470 */
471 replaceAllWith(searchConfig, replacement) {
472 this._resetCurrentSearchResultIndex();
473
474 var text = this._textEditor.text();
475 var range = this._textEditor.fullRange();
476
477 var regex = searchConfig.toSearchRegex(true);
478 if (regex.__fromRegExpQuery)
479 text = text.replace(regex, replacement);
480 else
481 text = text.replace(regex, function() {
482 return replacement;
483 });
484
485 var ranges = this._collectRegexMatches(regex);
486 if (!ranges.length)
487 return;
488
489 // Calculate the position of the end of the last range to be edited.
490 var currentRangeIndex = ranges.lowerBound(this._textEditor.selection(), WebI nspector.TextRange.comparator);
491 var lastRangeIndex = mod(currentRangeIndex - 1, ranges.length);
492 var lastRange = ranges[lastRangeIndex];
493 var replacementLineEndings = replacement.computeLineEndings();
494 var replacementLineCount = replacementLineEndings.length;
495 var lastLineNumber = lastRange.startLine + replacementLineEndings.length - 1 ;
496 var lastColumnNumber = lastRange.startColumn;
497 if (replacementLineEndings.length > 1)
498 lastColumnNumber =
499 replacementLineEndings[replacementLineCount - 1] - replacementLineEndi ngs[replacementLineCount - 2] - 1;
500
501 this._textEditor.editRange(range, text);
502 this._textEditor.revealPosition(lastLineNumber, lastColumnNumber);
503 this._textEditor.setSelection(WebInspector.TextRange.createFromLocation(last LineNumber, lastColumnNumber));
504 }
505
506 _collectRegexMatches(regexObject) {
507 var ranges = [];
508 for (var i = 0; i < this._textEditor.linesCount; ++i) {
509 var line = this._textEditor.line(i);
510 var offset = 0;
511 do {
512 var match = regexObject.exec(line);
513 if (match) {
514 var matchEndIndex = match.index + Math.max(match[0].length, 1);
515 if (match[0].length)
516 ranges.push(new WebInspector.TextRange(i, offset + match.index, i, o ffset + matchEndIndex));
517 offset += matchEndIndex;
518 line = line.substring(matchEndIndex);
519 }
520 } while (match && line);
521 }
522 return ranges;
523 }
524
525 /**
526 * @override
527 * @return {!Promise}
528 */
529 populateLineGutterContextMenu(contextMenu, lineNumber) {
530 return Promise.resolve();
531 }
532
533 /**
534 * @override
535 * @return {!Promise}
536 */
537 populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) {
538 return Promise.resolve();
539 }
540
541 /**
542 * @return {boolean}
543 */
544 canEditSource() {
545 return this._editable;
546 }
547
548 _updateSourcePosition() {
549 var selections = this._textEditor.selections();
550 if (!selections.length)
551 return;
552 if (selections.length > 1) {
553 this._sourcePosition.setText(WebInspector.UIString('%d selection regions', selections.length));
554 return;
555 }
556 var textRange = selections[0];
557 if (textRange.isEmpty()) {
558 this._sourcePosition.setText(
559 WebInspector.UIString('Line %d, Column %d', textRange.endLine + 1, tex tRange.endColumn + 1));
560 return;
561 }
562 textRange = textRange.normalize();
563
564 var selectedText = this._textEditor.text(textRange);
565 if (textRange.startLine === textRange.endLine)
566 this._sourcePosition.setText(WebInspector.UIString('%d characters selected ', selectedText.length));
567 else
568 this._sourcePosition.setText(WebInspector.UIString(
569 '%d lines, %d characters selected', textRange.endLine - textRange.star tLine + 1, selectedText.length));
570 }
571
572 _handleKeyDown(e) {
573 var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e);
574 var handler = this._shortcuts[shortcutKey];
575 if (handler && handler())
576 e.consume(true);
577 }
66 }; 578 };
67
68 WebInspector.SourceFrame.prototype = {
69 /**
70 * @param {boolean} editable
71 */
72 setEditable: function(editable)
73 {
74 this._editable = editable;
75 this._textEditor.setReadOnly(editable);
76 },
77
78 /**
79 * @param {number} key
80 * @param {function():boolean} handler
81 */
82 addShortcut: function(key, handler)
83 {
84 this._shortcuts[key] = handler;
85 },
86
87 /**
88 * @override
89 */
90 wasShown: function()
91 {
92 this._ensureContentLoaded();
93 this._textEditor.show(this.element);
94 this._editorAttached = true;
95 this._wasShownOrLoaded();
96 },
97
98 /**
99 * @return {boolean}
100 */
101 isEditorShowing: function()
102 {
103 return this.isShowing() && this._editorAttached;
104 },
105
106 willHide: function()
107 {
108 WebInspector.Widget.prototype.willHide.call(this);
109
110 this._clearPositionToReveal();
111 },
112
113 /**
114 * @override
115 * @return {!Array<!WebInspector.ToolbarItem>}
116 */
117 syncToolbarItems: function()
118 {
119 return [this._sourcePosition];
120 },
121
122 get loaded()
123 {
124 return this._loaded;
125 },
126
127 get textEditor()
128 {
129 return this._textEditor;
130 },
131
132 _ensureContentLoaded: function()
133 {
134 if (!this._contentRequested) {
135 this._contentRequested = true;
136 this._lazyContent().then(this.setContent.bind(this));
137 }
138 },
139
140 /**
141 * @param {number} line 0-based
142 * @param {number=} column
143 * @param {boolean=} shouldHighlight
144 */
145 revealPosition: function(line, column, shouldHighlight)
146 {
147 this._clearLineToScrollTo();
148 this._clearSelectionToSet();
149 this._positionToReveal = { line: line, column: column, shouldHighlight: shouldHighlight };
150 this._innerRevealPositionIfNeeded();
151 },
152
153 _innerRevealPositionIfNeeded: function()
154 {
155 if (!this._positionToReveal)
156 return;
157
158 if (!this.loaded || !this.isEditorShowing())
159 return;
160
161 this._textEditor.revealPosition(this._positionToReveal.line, this._posit ionToReveal.column, this._positionToReveal.shouldHighlight);
162 delete this._positionToReveal;
163 },
164
165 _clearPositionToReveal: function()
166 {
167 this._textEditor.clearPositionHighlight();
168 delete this._positionToReveal;
169 },
170
171 /**
172 * @param {number} line
173 */
174 scrollToLine: function(line)
175 {
176 this._clearPositionToReveal();
177 this._lineToScrollTo = line;
178 this._innerScrollToLineIfNeeded();
179 },
180
181 _innerScrollToLineIfNeeded: function()
182 {
183 if (typeof this._lineToScrollTo === "number") {
184 if (this.loaded && this.isEditorShowing()) {
185 this._textEditor.scrollToLine(this._lineToScrollTo);
186 delete this._lineToScrollTo;
187 }
188 }
189 },
190
191 _clearLineToScrollTo: function()
192 {
193 delete this._lineToScrollTo;
194 },
195
196 /**
197 * @return {!WebInspector.TextRange}
198 */
199 selection: function()
200 {
201 return this.textEditor.selection();
202 },
203
204 /**
205 * @param {!WebInspector.TextRange} textRange
206 */
207 setSelection: function(textRange)
208 {
209 this._selectionToSet = textRange;
210 this._innerSetSelectionIfNeeded();
211 },
212
213 _innerSetSelectionIfNeeded: function()
214 {
215 if (this._selectionToSet && this.loaded && this.isEditorShowing()) {
216 this._textEditor.setSelection(this._selectionToSet);
217 delete this._selectionToSet;
218 }
219 },
220
221 _clearSelectionToSet: function()
222 {
223 delete this._selectionToSet;
224 },
225
226 _wasShownOrLoaded: function()
227 {
228 this._innerRevealPositionIfNeeded();
229 this._innerSetSelectionIfNeeded();
230 this._innerScrollToLineIfNeeded();
231 },
232
233 /**
234 * @param {!WebInspector.TextRange} oldRange
235 * @param {!WebInspector.TextRange} newRange
236 */
237 onTextChanged: function(oldRange, newRange)
238 {
239 if (this._searchConfig && this._searchableView)
240 this.performSearch(this._searchConfig, false, false);
241 },
242
243 /**
244 * @param {string} content
245 * @param {string} mimeType
246 * @return {string}
247 */
248 _simplifyMimeType: function(content, mimeType)
249 {
250 if (!mimeType)
251 return "";
252 if (mimeType.indexOf("javascript") >= 0 ||
253 mimeType.indexOf("jscript") >= 0 ||
254 mimeType.indexOf("ecmascript") >= 0)
255 return "text/javascript";
256 // A hack around the fact that files with "php" extension might be eithe r standalone or html embedded php scripts.
257 if (mimeType === "text/x-php" && content.match(/\<\?.*\?\>/g))
258 return "application/x-httpd-php";
259 return mimeType;
260 },
261
262 /**
263 * @param {string} highlighterType
264 */
265 setHighlighterType: function(highlighterType)
266 {
267 this._highlighterType = highlighterType;
268 this._updateHighlighterType("");
269 },
270
271 /**
272 * @param {string} content
273 */
274 _updateHighlighterType: function(content)
275 {
276 this._textEditor.setMimeType(this._simplifyMimeType(content, this._highl ighterType));
277 },
278
279 /**
280 * @param {?string} content
281 */
282 setContent: function(content)
283 {
284 if (!this._loaded) {
285 this._loaded = true;
286 this._textEditor.setText(content || "");
287 this._textEditor.markClean();
288 } else {
289 var scrollTop = this._textEditor.scrollTop();
290 var selection = this._textEditor.selection();
291 this._textEditor.setText(content || "");
292 this._textEditor.setScrollTop(scrollTop);
293 this._textEditor.setSelection(selection);
294 }
295
296 this._updateHighlighterType(content || "");
297 this._wasShownOrLoaded();
298
299 if (this._delayedFindSearchMatches) {
300 this._delayedFindSearchMatches();
301 delete this._delayedFindSearchMatches;
302 }
303 this.onTextEditorContentSet();
304 },
305
306 onTextEditorContentSet: function() {},
307
308 /**
309 * @param {?WebInspector.SearchableView} view
310 */
311 setSearchableView: function(view)
312 {
313 this._searchableView = view;
314 },
315
316 /**
317 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
318 * @param {boolean} shouldJump
319 * @param {boolean} jumpBackwards
320 */
321 _doFindSearchMatches: function(searchConfig, shouldJump, jumpBackwards)
322 {
323 this._currentSearchResultIndex = -1;
324 this._searchResults = [];
325
326 var regex = searchConfig.toSearchRegex();
327 this._searchRegex = regex;
328 this._searchResults = this._collectRegexMatches(regex);
329
330 if (this._searchableView)
331 this._searchableView.updateSearchMatchesCount(this._searchResults.le ngth);
332
333 if (!this._searchResults.length)
334 this._textEditor.cancelSearchResultsHighlight();
335 else if (shouldJump && jumpBackwards)
336 this.jumpToPreviousSearchResult();
337 else if (shouldJump)
338 this.jumpToNextSearchResult();
339 else
340 this._textEditor.highlightSearchResults(regex, null);
341 },
342
343 /**
344 * @override
345 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
346 * @param {boolean} shouldJump
347 * @param {boolean=} jumpBackwards
348 */
349 performSearch: function(searchConfig, shouldJump, jumpBackwards)
350 {
351 if (this._searchableView)
352 this._searchableView.updateSearchMatchesCount(0);
353
354 this._resetSearch();
355 this._searchConfig = searchConfig;
356 if (this.loaded)
357 this._doFindSearchMatches(searchConfig, shouldJump, !!jumpBackwards) ;
358 else
359 this._delayedFindSearchMatches = this._doFindSearchMatches.bind(this , searchConfig, shouldJump, !!jumpBackwards);
360
361 this._ensureContentLoaded();
362 },
363
364 _resetCurrentSearchResultIndex: function()
365 {
366 if (!this._searchResults.length)
367 return;
368 this._currentSearchResultIndex = -1;
369 if (this._searchableView)
370 this._searchableView.updateCurrentMatchIndex(this._currentSearchResu ltIndex);
371 this._textEditor.highlightSearchResults(this._searchRegex, null);
372 },
373
374 _resetSearch: function()
375 {
376 delete this._searchConfig;
377 delete this._delayedFindSearchMatches;
378 this._currentSearchResultIndex = -1;
379 this._searchResults = [];
380 delete this._searchRegex;
381 },
382
383 /**
384 * @override
385 */
386 searchCanceled: function()
387 {
388 var range = this._currentSearchResultIndex !== -1 ? this._searchResults[ this._currentSearchResultIndex] : null;
389 this._resetSearch();
390 if (!this.loaded)
391 return;
392 this._textEditor.cancelSearchResultsHighlight();
393 if (range)
394 this.setSelection(range);
395 },
396
397 /**
398 * @return {boolean}
399 */
400 hasSearchResults: function()
401 {
402 return this._searchResults.length > 0;
403 },
404
405 jumpToFirstSearchResult: function()
406 {
407 this.jumpToSearchResult(0);
408 },
409
410 jumpToLastSearchResult: function()
411 {
412 this.jumpToSearchResult(this._searchResults.length - 1);
413 },
414
415 /**
416 * @return {number}
417 */
418 _searchResultIndexForCurrentSelection: function()
419 {
420 return this._searchResults.lowerBound(this._textEditor.selection().colla pseToEnd(), WebInspector.TextRange.comparator);
421 },
422
423 /**
424 * @override
425 */
426 jumpToNextSearchResult: function()
427 {
428 var currentIndex = this._searchResultIndexForCurrentSelection();
429 var nextIndex = this._currentSearchResultIndex === -1 ? currentIndex : c urrentIndex + 1;
430 this.jumpToSearchResult(nextIndex);
431 },
432
433 /**
434 * @override
435 */
436 jumpToPreviousSearchResult: function()
437 {
438 var currentIndex = this._searchResultIndexForCurrentSelection();
439 this.jumpToSearchResult(currentIndex - 1);
440 },
441
442 /**
443 * @override
444 * @return {boolean}
445 */
446 supportsCaseSensitiveSearch: function()
447 {
448 return true;
449 },
450
451 /**
452 * @override
453 * @return {boolean}
454 */
455 supportsRegexSearch: function()
456 {
457 return true;
458 },
459
460 get currentSearchResultIndex()
461 {
462 return this._currentSearchResultIndex;
463 },
464
465 jumpToSearchResult: function(index)
466 {
467 if (!this.loaded || !this._searchResults.length)
468 return;
469 this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
470 if (this._searchableView)
471 this._searchableView.updateCurrentMatchIndex(this._currentSearchResu ltIndex);
472 this._textEditor.highlightSearchResults(this._searchRegex, this._searchR esults[this._currentSearchResultIndex]);
473 },
474
475 /**
476 * @override
477 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
478 * @param {string} replacement
479 */
480 replaceSelectionWith: function(searchConfig, replacement)
481 {
482 var range = this._searchResults[this._currentSearchResultIndex];
483 if (!range)
484 return;
485 this._textEditor.highlightSearchResults(this._searchRegex, null);
486
487 var oldText = this._textEditor.text(range);
488 var regex = searchConfig.toSearchRegex();
489 var text;
490 if (regex.__fromRegExpQuery)
491 text = oldText.replace(regex, replacement);
492 else
493 text = oldText.replace(regex, function() { return replacement; });
494
495 var newRange = this._textEditor.editRange(range, text);
496 this._textEditor.setSelection(newRange.collapseToEnd());
497 },
498
499 /**
500 * @override
501 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
502 * @param {string} replacement
503 */
504 replaceAllWith: function(searchConfig, replacement)
505 {
506 this._resetCurrentSearchResultIndex();
507
508 var text = this._textEditor.text();
509 var range = this._textEditor.fullRange();
510
511 var regex = searchConfig.toSearchRegex(true);
512 if (regex.__fromRegExpQuery)
513 text = text.replace(regex, replacement);
514 else
515 text = text.replace(regex, function() { return replacement; });
516
517 var ranges = this._collectRegexMatches(regex);
518 if (!ranges.length)
519 return;
520
521 // Calculate the position of the end of the last range to be edited.
522 var currentRangeIndex = ranges.lowerBound(this._textEditor.selection(), WebInspector.TextRange.comparator);
523 var lastRangeIndex = mod(currentRangeIndex - 1, ranges.length);
524 var lastRange = ranges[lastRangeIndex];
525 var replacementLineEndings = replacement.computeLineEndings();
526 var replacementLineCount = replacementLineEndings.length;
527 var lastLineNumber = lastRange.startLine + replacementLineEndings.length - 1;
528 var lastColumnNumber = lastRange.startColumn;
529 if (replacementLineEndings.length > 1)
530 lastColumnNumber = replacementLineEndings[replacementLineCount - 1] - replacementLineEndings[replacementLineCount - 2] - 1;
531
532 this._textEditor.editRange(range, text);
533 this._textEditor.revealPosition(lastLineNumber, lastColumnNumber);
534 this._textEditor.setSelection(WebInspector.TextRange.createFromLocation( lastLineNumber, lastColumnNumber));
535 },
536
537 _collectRegexMatches: function(regexObject)
538 {
539 var ranges = [];
540 for (var i = 0; i < this._textEditor.linesCount; ++i) {
541 var line = this._textEditor.line(i);
542 var offset = 0;
543 do {
544 var match = regexObject.exec(line);
545 if (match) {
546 var matchEndIndex = match.index + Math.max(match[0].length, 1);
547 if (match[0].length)
548 ranges.push(new WebInspector.TextRange(i, offset + match .index, i, offset + matchEndIndex));
549 offset += matchEndIndex;
550 line = line.substring(matchEndIndex);
551 }
552 } while (match && line);
553 }
554 return ranges;
555 },
556
557 /**
558 * @override
559 * @return {!Promise}
560 */
561 populateLineGutterContextMenu: function(contextMenu, lineNumber)
562 {
563 return Promise.resolve();
564 },
565
566 /**
567 * @override
568 * @return {!Promise}
569 */
570 populateTextAreaContextMenu: function(contextMenu, lineNumber, columnNumber)
571 {
572 return Promise.resolve();
573 },
574
575 /**
576 * @return {boolean}
577 */
578 canEditSource: function()
579 {
580 return this._editable;
581 },
582
583 _updateSourcePosition: function()
584 {
585 var selections = this._textEditor.selections();
586 if (!selections.length)
587 return;
588 if (selections.length > 1) {
589 this._sourcePosition.setText(WebInspector.UIString("%d selection reg ions", selections.length));
590 return;
591 }
592 var textRange = selections[0];
593 if (textRange.isEmpty()) {
594 this._sourcePosition.setText(WebInspector.UIString("Line %d, Column %d", textRange.endLine + 1, textRange.endColumn + 1));
595 return;
596 }
597 textRange = textRange.normalize();
598
599 var selectedText = this._textEditor.text(textRange);
600 if (textRange.startLine === textRange.endLine)
601 this._sourcePosition.setText(WebInspector.UIString("%d characters se lected", selectedText.length));
602 else
603 this._sourcePosition.setText(WebInspector.UIString("%d lines, %d cha racters selected", textRange.endLine - textRange.startLine + 1, selectedText.len gth));
604 },
605
606 _handleKeyDown: function(e)
607 {
608 var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e);
609 var handler = this._shortcuts[shortcutKey];
610 if (handler && handler())
611 e.consume(true);
612 },
613
614 __proto__: WebInspector.SimpleView.prototype
615 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698