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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js

Issue 2608043002: DevTools: extract modules (with extensions) (Closed)
Patch Set: fix externs (PerfUI) Created 3 years, 11 months 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
(Empty)
1 /*
2 * Copyright (C) 2012 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 * @unrestricted
31 */
32 Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
33 /**
34 * @param {!Workspace.UISourceCode} uiSourceCode
35 */
36 constructor(uiSourceCode) {
37 super(uiSourceCode.contentURL(), workingCopy);
38 this._uiSourceCode = uiSourceCode;
39 this.setEditable(this._canEditSource());
40
41 if (Runtime.experiments.isEnabled('sourceDiff'))
42 this._diff = new Sources.SourceCodeDiff(uiSourceCode.requestOriginalConten t(), this.textEditor);
43
44 /** @type {?UI.AutocompleteConfig} */
45 this._autocompleteConfig = {isWordChar: Common.TextUtils.isWordChar};
46 Common.moduleSetting('textEditorAutocompletion').addChangeListener(this._upd ateAutocomplete, this);
47 this._updateAutocomplete();
48
49 /** @type {?Persistence.PersistenceBinding} */
50 this._persistenceBinding = Persistence.persistence.binding(uiSourceCode);
51
52 /** @type {!Map<number, !Sources.UISourceCodeFrame.RowMessageBucket>} */
53 this._rowMessageBuckets = new Map();
54 /** @type {!Set<string>} */
55 this._typeDecorationsPending = new Set();
56 this._uiSourceCode.addEventListener(
57 Workspace.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyCha nged, this);
58 this._uiSourceCode.addEventListener(
59 Workspace.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyC ommitted, this);
60
61 this._messageAndDecorationListeners = [];
62 this._installMessageAndDecorationListeners();
63
64 Persistence.persistence.subscribeForBindingEvent(this._uiSourceCode, this._o nBindingChanged.bind(this));
65
66 this.textEditor.addEventListener(
67 SourceFrame.SourcesTextEditor.Events.EditorBlurred,
68 () => UI.context.setFlavor(Sources.UISourceCodeFrame, null));
69 this.textEditor.addEventListener(
70 SourceFrame.SourcesTextEditor.Events.EditorFocused,
71 () => UI.context.setFlavor(Sources.UISourceCodeFrame, this));
72
73 this._updateStyle();
74
75 this._errorPopoverHelper = new UI.PopoverHelper(this.element);
76 this._errorPopoverHelper.initializeCallbacks(this._getErrorAnchor.bind(this) , this._showErrorPopover.bind(this));
77
78 this._errorPopoverHelper.setTimeout(100, 100);
79
80 /**
81 * @return {!Promise<?string>}
82 */
83 function workingCopy() {
84 if (uiSourceCode.isDirty())
85 return /** @type {!Promise<?string>} */ (Promise.resolve(uiSourceCode.wo rkingCopy()));
86 return uiSourceCode.requestContent();
87 }
88 }
89
90 _installMessageAndDecorationListeners() {
91 if (this._persistenceBinding) {
92 var networkSourceCode = this._persistenceBinding.network;
93 var fileSystemSourceCode = this._persistenceBinding.fileSystem;
94 this._messageAndDecorationListeners = [
95 networkSourceCode.addEventListener(Workspace.UISourceCode.Events.Message Added, this._onMessageAdded, this),
96 networkSourceCode.addEventListener(Workspace.UISourceCode.Events.Message Removed, this._onMessageRemoved, this),
97 networkSourceCode.addEventListener(
98 Workspace.UISourceCode.Events.LineDecorationAdded, this._onLineDecor ationAdded, this),
99 networkSourceCode.addEventListener(
100 Workspace.UISourceCode.Events.LineDecorationRemoved, this._onLineDec orationRemoved, this),
101
102 fileSystemSourceCode.addEventListener(Workspace.UISourceCode.Events.Mess ageAdded, this._onMessageAdded, this),
103 fileSystemSourceCode.addEventListener(
104 Workspace.UISourceCode.Events.MessageRemoved, this._onMessageRemoved , this),
105 ];
106 } else {
107 this._messageAndDecorationListeners = [
108 this._uiSourceCode.addEventListener(Workspace.UISourceCode.Events.Messag eAdded, this._onMessageAdded, this),
109 this._uiSourceCode.addEventListener(Workspace.UISourceCode.Events.Messag eRemoved, this._onMessageRemoved, this),
110 this._uiSourceCode.addEventListener(
111 Workspace.UISourceCode.Events.LineDecorationAdded, this._onLineDecor ationAdded, this),
112 this._uiSourceCode.addEventListener(
113 Workspace.UISourceCode.Events.LineDecorationRemoved, this._onLineDec orationRemoved, this)
114 ];
115 }
116 }
117
118 /**
119 * @return {!Workspace.UISourceCode}
120 */
121 uiSourceCode() {
122 return this._uiSourceCode;
123 }
124
125 /**
126 * @override
127 */
128 wasShown() {
129 super.wasShown();
130 // We need CodeMirrorTextEditor to be initialized prior to this call as it c alls |cursorPositionToCoordinates| internally. @see crbug.com/506566
131 setImmediate(this._updateBucketDecorations.bind(this));
132 }
133
134 /**
135 * @override
136 */
137 willHide() {
138 super.willHide();
139 UI.context.setFlavor(Sources.UISourceCodeFrame, null);
140 this._uiSourceCode.removeWorkingCopyGetter();
141 }
142
143 /**
144 * @return {boolean}
145 */
146 _canEditSource() {
147 if (Persistence.persistence.binding(this._uiSourceCode))
148 return true;
149 if (this._uiSourceCode.project().canSetFileContent())
150 return true;
151 if (this._uiSourceCode.project().isServiceProject())
152 return false;
153 return this._uiSourceCode.contentType() !== Common.resourceTypes.Document;
154 }
155
156 commitEditing() {
157 if (!this._uiSourceCode.isDirty())
158 return;
159
160 this._muteSourceCodeEvents = true;
161 this._uiSourceCode.commitWorkingCopy();
162 delete this._muteSourceCodeEvents;
163 }
164
165 /**
166 * @override
167 */
168 onTextEditorContentSet() {
169 if (this._diff)
170 this._diff.updateDiffMarkersImmediately();
171 super.onTextEditorContentSet();
172 for (var message of this._allMessages())
173 this._addMessageToSource(message);
174 this._decorateAllTypes();
175 }
176
177 /**
178 * @return {!Array<!Workspace.UISourceCode.Message>}
179 */
180 _allMessages() {
181 return this._persistenceBinding ?
182 this._persistenceBinding.network.messages().concat(this._persistenceBind ing.fileSystem.messages()) :
183 this._uiSourceCode.messages();
184 }
185
186 /**
187 * @override
188 * @param {!Common.TextRange} oldRange
189 * @param {!Common.TextRange} newRange
190 */
191 onTextChanged(oldRange, newRange) {
192 if (this._diff)
193 this._diff.updateDiffMarkersWhenPossible();
194 super.onTextChanged(oldRange, newRange);
195 this._errorPopoverHelper.hidePopover();
196 if (this._isSettingContent)
197 return;
198 this._muteSourceCodeEvents = true;
199 if (this.textEditor.isClean())
200 this._uiSourceCode.resetWorkingCopy();
201 else
202 this._uiSourceCode.setWorkingCopyGetter(this.textEditor.text.bind(this.tex tEditor));
203 delete this._muteSourceCodeEvents;
204 }
205
206 /**
207 * @param {!Common.Event} event
208 */
209 _onWorkingCopyChanged(event) {
210 if (this._muteSourceCodeEvents)
211 return;
212 this._innerSetContent(this._uiSourceCode.workingCopy());
213 this.onUISourceCodeContentChanged();
214 }
215
216 /**
217 * @param {!Common.Event} event
218 */
219 _onWorkingCopyCommitted(event) {
220 if (!this._muteSourceCodeEvents) {
221 this._innerSetContent(this._uiSourceCode.workingCopy());
222 this.onUISourceCodeContentChanged();
223 }
224 this.textEditor.markClean();
225 this._updateStyle();
226 }
227
228 _onBindingChanged() {
229 var binding = Persistence.persistence.binding(this._uiSourceCode);
230 if (binding === this._persistenceBinding)
231 return;
232 for (var message of this._allMessages())
233 this._removeMessageFromSource(message);
234 Common.EventTarget.removeEventListeners(this._messageAndDecorationListeners) ;
235
236 this._persistenceBinding = binding;
237
238 for (var message of this._allMessages())
239 this._addMessageToSource(message);
240 this._installMessageAndDecorationListeners();
241 this._updateStyle();
242 this._decorateAllTypes();
243 this.onBindingChanged();
244 }
245
246 /**
247 * @protected
248 */
249 onBindingChanged() {
250 // Overriden in subclasses.
251 }
252
253 _updateStyle() {
254 this.element.classList.toggle(
255 'source-frame-unsaved-committed-changes',
256 Persistence.persistence.hasUnsavedCommittedChanges(this._uiSourceCode));
257 this.setEditable(this._canEditSource());
258 }
259
260 onUISourceCodeContentChanged() {
261 }
262
263 _updateAutocomplete() {
264 this.textEditor.configureAutocomplete(
265 Common.moduleSetting('textEditorAutocompletion').get() ? this._autocompl eteConfig : null);
266 }
267
268 /**
269 * @param {?UI.AutocompleteConfig} config
270 */
271 configureAutocomplete(config) {
272 this._autocompleteConfig = config;
273 this._updateAutocomplete();
274 }
275
276 /**
277 * @param {string} content
278 */
279 _innerSetContent(content) {
280 this._isSettingContent = true;
281 if (this._diff) {
282 var oldContent = this.textEditor.text();
283 this.setContent(content);
284 this._diff.highlightModifiedLines(oldContent, content);
285 } else {
286 this.setContent(content);
287 }
288 delete this._isSettingContent;
289 }
290
291 /**
292 * @override
293 * @return {!Promise}
294 */
295 populateTextAreaContextMenu(contextMenu, lineNumber, columnNumber) {
296 /**
297 * @this {Sources.UISourceCodeFrame}
298 */
299 function appendItems() {
300 contextMenu.appendApplicableItems(this._uiSourceCode);
301 contextMenu.appendApplicableItems(new Workspace.UILocation(this._uiSourceC ode, lineNumber, columnNumber));
302 contextMenu.appendApplicableItems(this);
303 }
304
305 return super.populateTextAreaContextMenu(contextMenu, lineNumber, columnNumb er).then(appendItems.bind(this));
306 }
307
308 /**
309 * @param {!Array.<!UI.Infobar|undefined>} infobars
310 */
311 attachInfobars(infobars) {
312 for (var i = infobars.length - 1; i >= 0; --i) {
313 var infobar = infobars[i];
314 if (!infobar)
315 continue;
316 this.element.insertBefore(infobar.element, this.element.children[0]);
317 infobar.setParentView(this);
318 }
319 this.doResize();
320 }
321
322 dispose() {
323 this.textEditor.dispose();
324 Common.moduleSetting('textEditorAutocompletion').removeChangeListener(this._ updateAutocomplete, this);
325 this.detach();
326 }
327
328 /**
329 * @param {!Common.Event} event
330 */
331 _onMessageAdded(event) {
332 var message = /** @type {!Workspace.UISourceCode.Message} */ (event.data);
333 this._addMessageToSource(message);
334 }
335
336 /**
337 * @param {!Workspace.UISourceCode.Message} message
338 */
339 _addMessageToSource(message) {
340 if (!this.loaded)
341 return;
342 var lineNumber = message.lineNumber();
343 if (lineNumber >= this.textEditor.linesCount)
344 lineNumber = this.textEditor.linesCount - 1;
345 if (lineNumber < 0)
346 lineNumber = 0;
347
348 var messageBucket = this._rowMessageBuckets.get(lineNumber);
349 if (!messageBucket) {
350 messageBucket = new Sources.UISourceCodeFrame.RowMessageBucket(this, this. textEditor, lineNumber);
351 this._rowMessageBuckets.set(lineNumber, messageBucket);
352 }
353 messageBucket.addMessage(message);
354 }
355
356 /**
357 * @param {!Common.Event} event
358 */
359 _onMessageRemoved(event) {
360 var message = /** @type {!Workspace.UISourceCode.Message} */ (event.data);
361 this._removeMessageFromSource(message);
362 }
363
364 /**
365 * @param {!Workspace.UISourceCode.Message} message
366 */
367 _removeMessageFromSource(message) {
368 if (!this.loaded)
369 return;
370
371 var lineNumber = message.lineNumber();
372 if (lineNumber >= this.textEditor.linesCount)
373 lineNumber = this.textEditor.linesCount - 1;
374 if (lineNumber < 0)
375 lineNumber = 0;
376
377 var messageBucket = this._rowMessageBuckets.get(lineNumber);
378 if (!messageBucket)
379 return;
380 messageBucket.removeMessage(message);
381 if (!messageBucket.uniqueMessagesCount()) {
382 messageBucket.detachFromEditor();
383 this._rowMessageBuckets.delete(lineNumber);
384 }
385 }
386
387 /**
388 * @param {!Element} target
389 * @param {!Event} event
390 * @return {(!Element|undefined)}
391 */
392 _getErrorAnchor(target, event) {
393 var element = target.enclosingNodeOrSelfWithClass('text-editor-line-decorati on-icon') ||
394 target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-wave');
395 if (!element)
396 return;
397 this._errorWavePopoverAnchor = new AnchorBox(event.clientX, event.clientY, 1 , 1);
398 return element;
399 }
400
401 /**
402 * @param {!Element} anchor
403 * @param {!UI.Popover} popover
404 */
405 _showErrorPopover(anchor, popover) {
406 var messageBucket = anchor.enclosingNodeOrSelfWithClass('text-editor-line-de coration')._messageBucket;
407 var messagesOutline = messageBucket.messagesDescription();
408 var popoverAnchor =
409 anchor.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') ? anchor : this._errorWavePopoverAnchor;
410 popover.showForAnchor(messagesOutline, popoverAnchor);
411 }
412
413 _updateBucketDecorations() {
414 for (var bucket of this._rowMessageBuckets.values())
415 bucket._updateDecoration();
416 }
417
418 /**
419 * @param {!Common.Event} event
420 */
421 _onLineDecorationAdded(event) {
422 var marker = /** @type {!Workspace.UISourceCode.LineMarker} */ (event.data);
423 this._decorateTypeThrottled(marker.type());
424 }
425
426 /**
427 * @param {!Common.Event} event
428 */
429 _onLineDecorationRemoved(event) {
430 var marker = /** @type {!Workspace.UISourceCode.LineMarker} */ (event.data);
431 this._decorateTypeThrottled(marker.type());
432 }
433
434 /**
435 * @param {string} type
436 */
437 _decorateTypeThrottled(type) {
438 if (this._typeDecorationsPending.has(type))
439 return;
440 this._typeDecorationsPending.add(type);
441 self.runtime.extensions(Sources.UISourceCodeFrame.LineDecorator)
442 .find(extension => extension.descriptor()['decoratorType'] === type)
443 .instance()
444 .then(decorator => {
445 this._typeDecorationsPending.delete(type);
446 decorator.decorate(
447 this._persistenceBinding ? this._persistenceBinding.network : this .uiSourceCode(), this.textEditor);
448 });
449 }
450
451 _decorateAllTypes() {
452 var extensions = self.runtime.extensions(Sources.UISourceCodeFrame.LineDecor ator);
453 extensions.forEach(extension => this._decorateTypeThrottled(extension.descri ptor()['decoratorType']));
454 }
455 };
456
457 Sources.UISourceCodeFrame._iconClassPerLevel = {};
458 Sources.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Leve l.Error] = 'smallicon-error';
459 Sources.UISourceCodeFrame._iconClassPerLevel[Workspace.UISourceCode.Message.Leve l.Warning] = 'smallicon-warning';
460
461 Sources.UISourceCodeFrame._bubbleTypePerLevel = {};
462 Sources.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Lev el.Error] = 'error';
463 Sources.UISourceCodeFrame._bubbleTypePerLevel[Workspace.UISourceCode.Message.Lev el.Warning] = 'warning';
464
465 Sources.UISourceCodeFrame._lineClassPerLevel = {};
466 Sources.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Leve l.Error] =
467 'text-editor-line-with-error';
468 Sources.UISourceCodeFrame._lineClassPerLevel[Workspace.UISourceCode.Message.Leve l.Warning] =
469 'text-editor-line-with-warning';
470
471 /**
472 * @interface
473 */
474 Sources.UISourceCodeFrame.LineDecorator = function() {};
475
476 Sources.UISourceCodeFrame.LineDecorator.prototype = {
477 /**
478 * @param {!Workspace.UISourceCode} uiSourceCode
479 * @param {!TextEditor.CodeMirrorTextEditor} textEditor
480 */
481 decorate(uiSourceCode, textEditor) {}
482 };
483
484 /**
485 * @unrestricted
486 */
487 Sources.UISourceCodeFrame.RowMessage = class {
488 /**
489 * @param {!Workspace.UISourceCode.Message} message
490 */
491 constructor(message) {
492 this._message = message;
493 this._repeatCount = 1;
494 this.element = createElementWithClass('div', 'text-editor-row-message');
495 this._icon = this.element.createChild('label', '', 'dt-icon-label');
496 this._icon.type = Sources.UISourceCodeFrame._iconClassPerLevel[message.level ()];
497 this._repeatCountElement = this.element.createChild('label', 'message-repeat -count hidden', 'dt-small-bubble');
498 this._repeatCountElement.type = Sources.UISourceCodeFrame._bubbleTypePerLeve l[message.level()];
499 var linesContainer = this.element.createChild('div', 'text-editor-row-messag e-lines');
500 var lines = this._message.text().split('\n');
501 for (var i = 0; i < lines.length; ++i) {
502 var messageLine = linesContainer.createChild('div');
503 messageLine.textContent = lines[i];
504 }
505 }
506
507 /**
508 * @return {!Workspace.UISourceCode.Message}
509 */
510 message() {
511 return this._message;
512 }
513
514 /**
515 * @return {number}
516 */
517 repeatCount() {
518 return this._repeatCount;
519 }
520
521 setRepeatCount(repeatCount) {
522 if (this._repeatCount === repeatCount)
523 return;
524 this._repeatCount = repeatCount;
525 this._updateMessageRepeatCount();
526 }
527
528 _updateMessageRepeatCount() {
529 this._repeatCountElement.textContent = this._repeatCount;
530 var showRepeatCount = this._repeatCount > 1;
531 this._repeatCountElement.classList.toggle('hidden', !showRepeatCount);
532 this._icon.classList.toggle('hidden', showRepeatCount);
533 }
534 };
535
536 /**
537 * @unrestricted
538 */
539 Sources.UISourceCodeFrame.RowMessageBucket = class {
540 /**
541 * @param {!Sources.UISourceCodeFrame} sourceFrame
542 * @param {!TextEditor.CodeMirrorTextEditor} textEditor
543 * @param {number} lineNumber
544 */
545 constructor(sourceFrame, textEditor, lineNumber) {
546 this._sourceFrame = sourceFrame;
547 this.textEditor = textEditor;
548 this._lineHandle = textEditor.textEditorPositionHandle(lineNumber, 0);
549 this._decoration = createElementWithClass('div', 'text-editor-line-decoratio n');
550 this._decoration._messageBucket = this;
551 this._wave = this._decoration.createChild('div', 'text-editor-line-decoratio n-wave');
552 this._icon = this._wave.createChild('label', 'text-editor-line-decoration-ic on', 'dt-icon-label');
553 this._hasDecoration = false;
554
555 this._messagesDescriptionElement = createElementWithClass('div', 'text-edito r-messages-description-container');
556 /** @type {!Array.<!Sources.UISourceCodeFrame.RowMessage>} */
557 this._messages = [];
558
559 this._level = null;
560 }
561
562 /**
563 * @param {number} lineNumber
564 * @param {number} columnNumber
565 */
566 _updateWavePosition(lineNumber, columnNumber) {
567 lineNumber = Math.min(lineNumber, this.textEditor.linesCount - 1);
568 var lineText = this.textEditor.line(lineNumber);
569 columnNumber = Math.min(columnNumber, lineText.length);
570 var lineIndent = Common.TextUtils.lineIndent(lineText).length;
571 if (this._hasDecoration)
572 this.textEditor.removeDecoration(this._decoration, lineNumber);
573 this._hasDecoration = true;
574 this.textEditor.addDecoration(this._decoration, lineNumber, Math.max(columnN umber - 1, lineIndent));
575 }
576
577 /**
578 * @return {!Element}
579 */
580 messagesDescription() {
581 this._messagesDescriptionElement.removeChildren();
582 for (var i = 0; i < this._messages.length; ++i)
583 this._messagesDescriptionElement.appendChild(this._messages[i].element);
584
585 return this._messagesDescriptionElement;
586 }
587
588 detachFromEditor() {
589 var position = this._lineHandle.resolve();
590 if (!position)
591 return;
592 var lineNumber = position.lineNumber;
593 if (this._level)
594 this.textEditor.toggleLineClass(lineNumber, Sources.UISourceCodeFrame._lin eClassPerLevel[this._level], false);
595 if (this._hasDecoration)
596 this.textEditor.removeDecoration(this._decoration, lineNumber);
597 this._hasDecoration = false;
598 }
599
600 /**
601 * @return {number}
602 */
603 uniqueMessagesCount() {
604 return this._messages.length;
605 }
606
607 /**
608 * @param {!Workspace.UISourceCode.Message} message
609 */
610 addMessage(message) {
611 for (var i = 0; i < this._messages.length; ++i) {
612 var rowMessage = this._messages[i];
613 if (rowMessage.message().isEqual(message)) {
614 rowMessage.setRepeatCount(rowMessage.repeatCount() + 1);
615 return;
616 }
617 }
618
619 var rowMessage = new Sources.UISourceCodeFrame.RowMessage(message);
620 this._messages.push(rowMessage);
621 this._updateDecoration();
622 }
623
624 /**
625 * @param {!Workspace.UISourceCode.Message} message
626 */
627 removeMessage(message) {
628 for (var i = 0; i < this._messages.length; ++i) {
629 var rowMessage = this._messages[i];
630 if (!rowMessage.message().isEqual(message))
631 continue;
632 rowMessage.setRepeatCount(rowMessage.repeatCount() - 1);
633 if (!rowMessage.repeatCount())
634 this._messages.splice(i, 1);
635 this._updateDecoration();
636 return;
637 }
638 }
639
640 _updateDecoration() {
641 if (!this._sourceFrame.isEditorShowing())
642 return;
643 if (!this._messages.length)
644 return;
645 var position = this._lineHandle.resolve();
646 if (!position)
647 return;
648
649 var lineNumber = position.lineNumber;
650 var columnNumber = Number.MAX_VALUE;
651 var maxMessage = null;
652 for (var i = 0; i < this._messages.length; ++i) {
653 var message = this._messages[i].message();
654 columnNumber = Math.min(columnNumber, message.columnNumber());
655 if (!maxMessage || Workspace.UISourceCode.Message.messageLevelComparator(m axMessage, message) < 0)
656 maxMessage = message;
657 }
658 this._updateWavePosition(lineNumber, columnNumber);
659
660 if (this._level) {
661 this.textEditor.toggleLineClass(lineNumber, Sources.UISourceCodeFrame._lin eClassPerLevel[this._level], false);
662 this._icon.type = '';
663 }
664 this._level = maxMessage.level();
665 if (!this._level)
666 return;
667 this.textEditor.toggleLineClass(lineNumber, Sources.UISourceCodeFrame._lineC lassPerLevel[this._level], true);
668 this._icon.type = Sources.UISourceCodeFrame._iconClassPerLevel[this._level];
669 }
670 };
671
672 Workspace.UISourceCode.Message._messageLevelPriority = {
673 'Warning': 3,
674 'Error': 4
675 };
676
677 /**
678 * @param {!Workspace.UISourceCode.Message} a
679 * @param {!Workspace.UISourceCode.Message} b
680 * @return {number}
681 */
682 Workspace.UISourceCode.Message.messageLevelComparator = function(a, b) {
683 return Workspace.UISourceCode.Message._messageLevelPriority[a.level()] -
684 Workspace.UISourceCode.Message._messageLevelPriority[b.level()];
685 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698