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

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

Issue 1427653002: DevTools: move ui messages from SourceFrame to UISourceCodeFrame (step1) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebaselined Created 5 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) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 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 * 1. Redistributions of source code must retain the above copyright 8 * 1. 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 * 10 *
(...skipping 18 matching lines...) Expand all
29 /** 29 /**
30 * @constructor 30 * @constructor
31 * @extends {WebInspector.SourceFrame} 31 * @extends {WebInspector.SourceFrame}
32 * @param {!WebInspector.UISourceCode} uiSourceCode 32 * @param {!WebInspector.UISourceCode} uiSourceCode
33 */ 33 */
34 WebInspector.UISourceCodeFrame = function(uiSourceCode) 34 WebInspector.UISourceCodeFrame = function(uiSourceCode)
35 { 35 {
36 this._uiSourceCode = uiSourceCode; 36 this._uiSourceCode = uiSourceCode;
37 WebInspector.SourceFrame.call(this, this._uiSourceCode); 37 WebInspector.SourceFrame.call(this, this._uiSourceCode);
38 this.textEditor.setAutocompleteDelegate(new WebInspector.SimpleAutocompleteD elegate()); 38 this.textEditor.setAutocompleteDelegate(new WebInspector.SimpleAutocompleteD elegate());
39 39 this._rowMessageBuckets = {};
40 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Working CopyChanged, this._onWorkingCopyChanged, this); 40 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Working CopyChanged, this._onWorkingCopyChanged, this);
41 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Working CopyCommitted, this._onWorkingCopyCommitted, this); 41 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Working CopyCommitted, this._onWorkingCopyCommitted, this);
42 this._updateStyle(); 42 this._updateStyle();
43
44 this._errorPopoverHelper = new WebInspector.PopoverHelper(this.element, this ._getErrorAnchor.bind(this), this._showErrorPopover.bind(this));
45 this._errorPopoverHelper.setTimeout(100, 100);
43 } 46 }
44 47
45 WebInspector.UISourceCodeFrame.prototype = { 48 WebInspector.UISourceCodeFrame.prototype = {
46 /** 49 /**
47 * @return {!WebInspector.UISourceCode} 50 * @return {!WebInspector.UISourceCode}
48 */ 51 */
49 uiSourceCode: function() 52 uiSourceCode: function()
50 { 53 {
51 return this._uiSourceCode; 54 return this._uiSourceCode;
52 }, 55 },
53 56
54 wasShown: function() 57 wasShown: function()
55 { 58 {
56 WebInspector.SourceFrame.prototype.wasShown.call(this); 59 WebInspector.SourceFrame.prototype.wasShown.call(this);
57 this._boundWindowFocused = this._windowFocused.bind(this); 60 this._boundWindowFocused = this._windowFocused.bind(this);
58 this.element.ownerDocument.defaultView.addEventListener("focus", this._b oundWindowFocused, false); 61 this.element.ownerDocument.defaultView.addEventListener("focus", this._b oundWindowFocused, false);
59 this._checkContentUpdated(); 62 this._checkContentUpdated();
63 // We need CodeMirrorTextEditor to be initialized prior to this call as it calls |cursorPositionToCoordinates| internally. @see crbug.com/506566
64 setImmediate(this._updateBucketDecorations.bind(this));
60 }, 65 },
61 66
62 willHide: function() 67 willHide: function()
63 { 68 {
64 WebInspector.SourceFrame.prototype.willHide.call(this); 69 WebInspector.SourceFrame.prototype.willHide.call(this);
65 this.element.ownerDocument.defaultView.removeEventListener("focus", this ._boundWindowFocused, false); 70 this.element.ownerDocument.defaultView.removeEventListener("focus", this ._boundWindowFocused, false);
66 delete this._boundWindowFocused; 71 delete this._boundWindowFocused;
67 this._uiSourceCode.removeWorkingCopyGetter(); 72 this._uiSourceCode.removeWorkingCopyGetter();
68 }, 73 },
69 74
(...skipping 29 matching lines...) Expand all
99 return; 104 return;
100 105
101 this._muteSourceCodeEvents = true; 106 this._muteSourceCodeEvents = true;
102 this._uiSourceCode.commitWorkingCopy(); 107 this._uiSourceCode.commitWorkingCopy();
103 delete this._muteSourceCodeEvents; 108 delete this._muteSourceCodeEvents;
104 }, 109 },
105 110
106 onTextChanged: function(oldRange, newRange) 111 onTextChanged: function(oldRange, newRange)
107 { 112 {
108 WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, ne wRange); 113 WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, ne wRange);
114 this.clearMessages();
109 if (this._isSettingContent) 115 if (this._isSettingContent)
110 return; 116 return;
111 this._muteSourceCodeEvents = true; 117 this._muteSourceCodeEvents = true;
112 if (this._textEditor.isClean()) 118 if (this._textEditor.isClean())
113 this._uiSourceCode.resetWorkingCopy(); 119 this._uiSourceCode.resetWorkingCopy();
114 else 120 else
115 this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(t his._textEditor)); 121 this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(t his._textEditor));
116 delete this._muteSourceCodeEvents; 122 delete this._muteSourceCodeEvents;
117 }, 123 },
118 124
125 onTextEditorContentLoaded: function()
126 {
127 WebInspector.SourceFrame.prototype.onTextEditorContentLoaded.call(this);
128 this.clearMessages();
129 },
130
119 /** 131 /**
120 * @param {!WebInspector.Event} event 132 * @param {!WebInspector.Event} event
121 */ 133 */
122 _onWorkingCopyChanged: function(event) 134 _onWorkingCopyChanged: function(event)
123 { 135 {
124 if (this._muteSourceCodeEvents) 136 if (this._muteSourceCodeEvents)
125 return; 137 return;
126 this._innerSetContent(this._uiSourceCode.workingCopy()); 138 this._innerSetContent(this._uiSourceCode.workingCopy());
127 this.onUISourceCodeContentChanged(); 139 this.onUISourceCodeContentChanged();
128 }, 140 },
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 } 205 }
194 this.doResize(); 206 this.doResize();
195 }, 207 },
196 208
197 dispose: function() 209 dispose: function()
198 { 210 {
199 this._textEditor.dispose(); 211 this._textEditor.dispose();
200 this.detach(); 212 this.detach();
201 }, 213 },
202 214
215 /**
216 * @param {!WebInspector.UISourceCode.Message} message
217 */
218 addMessageToSource: function(message)
219 {
220 var lineNumber = message.lineNumber();
221 if (lineNumber >= this._textEditor.linesCount)
222 lineNumber = this._textEditor.linesCount - 1;
223 if (lineNumber < 0)
224 lineNumber = 0;
225
226 if (!this._rowMessageBuckets[lineNumber])
227 this._rowMessageBuckets[lineNumber] = new WebInspector.UISourceCodeF rame.RowMessageBucket(this, this._textEditor, lineNumber);
228 var messageBucket = this._rowMessageBuckets[lineNumber];
229 messageBucket.addMessage(message);
230 },
231
232 /**
233 * @param {!WebInspector.UISourceCode.Message} message
234 */
235 removeMessageFromSource: function(message)
236 {
237 var lineNumber = message.lineNumber();
238 if (lineNumber >= this._textEditor.linesCount)
239 lineNumber = this._textEditor.linesCount - 1;
240 if (lineNumber < 0)
241 lineNumber = 0;
242
243 var messageBucket = this._rowMessageBuckets[lineNumber];
244 if (!messageBucket)
245 return;
246 messageBucket.removeMessage(message);
247 if (!messageBucket.uniqueMessagesCount()) {
248 messageBucket.detachFromEditor();
249 delete this._rowMessageBuckets[lineNumber];
250 }
251 },
252
253 clearMessages: function()
254 {
255 for (var line in this._rowMessageBuckets) {
256 var bubble = this._rowMessageBuckets[line];
257 bubble.detachFromEditor();
258 }
259
260 this._rowMessageBuckets = {};
261 this._errorPopoverHelper.hidePopover();
262 },
263
264 /**
265 * @param {!Element} target
266 * @param {!Event} event
267 * @return {(!Element|undefined)}
268 */
269 _getErrorAnchor: function(target, event)
270 {
271 var element = target.enclosingNodeOrSelfWithClass("text-editor-line-deco ration-icon")
272 || target.enclosingNodeOrSelfWithClass("text-editor-line-decoration- wave");
273 if (!element)
274 return;
275 this._errorWavePopoverAnchor = new AnchorBox(event.clientX, event.client Y, 1, 1);
276 return element;
277 },
278
279 /**
280 * @param {!Element} anchor
281 * @param {!WebInspector.Popover} popover
282 */
283 _showErrorPopover: function(anchor, popover)
284 {
285 var messageBucket = anchor.enclosingNodeOrSelfWithClass("text-editor-lin e-decoration")._messageBucket;
286 var messagesOutline = messageBucket.messagesDescription();
287 var popoverAnchor = anchor.enclosingNodeOrSelfWithClass("text-editor-lin e-decoration-icon") ? anchor : this._errorWavePopoverAnchor;
288 popover.showForAnchor(messagesOutline, popoverAnchor);
289 },
290
291 _updateBucketDecorations: function()
292 {
293 for (var line in this._rowMessageBuckets) {
294 var bucket = this._rowMessageBuckets[line];
295 bucket._updateDecoration();
296 }
297 },
298
203 __proto__: WebInspector.SourceFrame.prototype 299 __proto__: WebInspector.SourceFrame.prototype
204 } 300 }
205 301
206 /** 302 /**
207 * @constructor 303 * @constructor
208 * @extends {WebInspector.Infobar} 304 * @extends {WebInspector.Infobar}
209 * @param {!WebInspector.Infobar.Type} type 305 * @param {!WebInspector.Infobar.Type} type
210 * @param {string} message 306 * @param {string} message
211 * @param {!WebInspector.Setting=} disableSetting 307 * @param {!WebInspector.Setting=} disableSetting
212 */ 308 */
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 365
270 dispose: function() 366 dispose: function()
271 { 367 {
272 this.element.remove(); 368 this.element.remove();
273 this._onResize(); 369 this._onResize();
274 delete this._uiSourceCodeFrame; 370 delete this._uiSourceCodeFrame;
275 }, 371 },
276 372
277 __proto__: WebInspector.Infobar.prototype 373 __proto__: WebInspector.Infobar.prototype
278 } 374 }
375
376 /**
377 * @param {!WebInspector.ConsoleMessage} consoleMessage
378 * @param {number} lineNumber
379 * @param {number} columnNumber
380 * @return {!WebInspector.UISourceCode.Message}
381 */
382 WebInspector.UISourceCodeFrame.uiMessageFromConsoleMessage = function(consoleMes sage, lineNumber, columnNumber)
383 {
384 console.assert(consoleMessage.level === WebInspector.ConsoleMessage.MessageL evel.Error || consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel. Warning);
385 var level = consoleMessage.level === WebInspector.ConsoleMessage.MessageLeve l.Error ? WebInspector.UISourceCode.Message.Level.Error : WebInspector.UISourceC ode.Message.Level.Warning;
386 return new WebInspector.UISourceCode.Message(level, consoleMessage.messageTe xt, lineNumber, columnNumber);
387 }
388
389 WebInspector.UISourceCodeFrame._iconClassPerLevel = {};
390 WebInspector.UISourceCodeFrame._iconClassPerLevel[WebInspector.UISourceCode.Mess age.Level.Error] = "error-icon";
391 WebInspector.UISourceCodeFrame._iconClassPerLevel[WebInspector.UISourceCode.Mess age.Level.Warning] = "warning-icon";
392
393 WebInspector.UISourceCodeFrame._lineClassPerLevel = {};
394 WebInspector.UISourceCodeFrame._lineClassPerLevel[WebInspector.UISourceCode.Mess age.Level.Error] = "text-editor-line-with-error";
395 WebInspector.UISourceCodeFrame._lineClassPerLevel[WebInspector.UISourceCode.Mess age.Level.Warning] = "text-editor-line-with-warning";
396
397 /**
398 * @constructor
399 * @param {!WebInspector.UISourceCode.Message} message
400 */
401 WebInspector.UISourceCodeFrame.RowMessage = function(message)
402 {
403 this._message = message;
404 this._repeatCount = 1;
405 this.element = createElementWithClass("div", "text-editor-row-message");
406 this._icon = this.element.createChild("label", "", "dt-icon-label");
407 this._icon.type = WebInspector.UISourceCodeFrame._iconClassPerLevel[message. level()];
408 this._repeatCountElement = this.element.createChild("span", "bubble-repeat-c ount hidden error");
409 var linesContainer = this.element.createChild("div", "text-editor-row-messag e-lines");
410 var lines = this._message.text().split("\n");
411 for (var i = 0; i < lines.length; ++i) {
412 var messageLine = linesContainer.createChild("div");
413 messageLine.textContent = lines[i];
414 }
415 }
416
417 WebInspector.UISourceCodeFrame.RowMessage.prototype = {
418 /**
419 * @return {!WebInspector.UISourceCode.Message}
420 */
421 message: function()
422 {
423 return this._message;
424 },
425
426 /**
427 * @return {number}
428 */
429 repeatCount: function()
430 {
431 return this._repeatCount;
432 },
433
434 setRepeatCount: function(repeatCount)
435 {
436 if (this._repeatCount === repeatCount)
437 return;
438 this._repeatCount = repeatCount;
439 this._updateMessageRepeatCount();
440 },
441
442 _updateMessageRepeatCount: function()
443 {
444 this._repeatCountElement.textContent = this._repeatCount;
445 var showRepeatCount = this._repeatCount > 1;
446 this._repeatCountElement.classList.toggle("hidden", !showRepeatCount);
447 this._icon.classList.toggle("hidden", showRepeatCount);
448 }
449 }
450
451 /**
452 * @constructor
453 * @param {!WebInspector.UISourceCodeFrame} sourceFrame
454 * @param {!WebInspector.CodeMirrorTextEditor} textEditor
455 * @param {number} lineNumber
456 */
457 WebInspector.UISourceCodeFrame.RowMessageBucket = function(sourceFrame, textEdit or, lineNumber)
458 {
459 this._sourceFrame = sourceFrame;
460 this._textEditor = textEditor;
461 this._lineHandle = textEditor.textEditorPositionHandle(lineNumber, 0);
462 this._decoration = createElementWithClass("div", "text-editor-line-decoratio n");
463 this._decoration._messageBucket = this;
464 this._wave = this._decoration.createChild("div", "text-editor-line-decoratio n-wave");
465 this._icon = this._wave.createChild("label", "text-editor-line-decoration-ic on", "dt-icon-label");
466
467 this._textEditor.addDecoration(lineNumber, this._decoration);
468
469 this._messagesDescriptionElement = createElementWithClass("div", "text-edito r-messages-description-container");
470 /** @type {!Array.<!WebInspector.UISourceCodeFrame.RowMessage>} */
471 this._messages = [];
472
473 this._level = null;
474 }
475
476 WebInspector.UISourceCodeFrame.RowMessageBucket.prototype = {
477 /**
478 * @param {number} lineNumber
479 * @param {number} columnNumber
480 */
481 _updateWavePosition: function(lineNumber, columnNumber)
482 {
483 lineNumber = Math.min(lineNumber, this._textEditor.linesCount - 1);
484 var lineText = this._textEditor.line(lineNumber);
485 columnNumber = Math.min(columnNumber, lineText.length);
486 var lineIndent = WebInspector.TextUtils.lineIndent(lineText).length;
487 var base = this._textEditor.cursorPositionToCoordinates(lineNumber, 0);
488
489 var start = this._textEditor.cursorPositionToCoordinates(lineNumber, Mat h.max(columnNumber - 1, lineIndent));
490 var end = this._textEditor.cursorPositionToCoordinates(lineNumber, lineT ext.length);
491 /** @const */
492 var codeMirrorLinesLeftPadding = 4;
493 this._wave.style.left = (start.x - base.x + codeMirrorLinesLeftPadding) + "px";
494 this._wave.style.width = (end.x - start.x) + "px";
495 },
496
497 /**
498 * @return {!Element}
499 */
500 messagesDescription: function()
501 {
502 this._messagesDescriptionElement.removeChildren();
503 for (var i = 0; i < this._messages.length; ++i) {
504 this._messagesDescriptionElement.appendChild(this._messages[i].eleme nt);
505 }
506 return this._messagesDescriptionElement;
507 },
508
509 detachFromEditor: function()
510 {
511 var position = this._lineHandle.resolve();
512 if (!position)
513 return;
514 var lineNumber = position.lineNumber;
515 if (this._level)
516 this._textEditor.toggleLineClass(lineNumber, WebInspector.UISourceCo deFrame._lineClassPerLevel[this._level], false);
517 this._textEditor.removeDecoration(lineNumber, this._decoration);
518 },
519
520 /**
521 * @return {number}
522 */
523 uniqueMessagesCount: function()
524 {
525 return this._messages.length;
526 },
527
528 /**
529 * @param {!WebInspector.UISourceCode.Message} message
530 */
531 addMessage: function(message)
532 {
533 for (var i = 0; i < this._messages.length; ++i) {
534 var rowMessage = this._messages[i];
535 if (rowMessage.message().isEqual(message)) {
536 rowMessage.setRepeatCount(rowMessage.repeatCount() + 1);
537 return;
538 }
539 }
540
541 var rowMessage = new WebInspector.UISourceCodeFrame.RowMessage(message);
542 this._messages.push(rowMessage);
543 this._updateDecoration();
544 },
545
546 /**
547 * @param {!WebInspector.UISourceCode.Message} message
548 */
549 removeMessage: function(message)
550 {
551 for (var i = 0; i < this._messages.length; ++i) {
552 var rowMessage = this._messages[i];
553 if (!rowMessage.message().isEqual(message))
554 continue;
555 rowMessage.setRepeatCount(rowMessage.repeatCount() - 1);
556 if (!rowMessage.repeatCount())
557 this._messages.splice(i, 1);
558 this._updateDecoration();
559 return;
560 }
561 },
562
563 _updateDecoration: function()
564 {
565 if (!this._sourceFrame.isEditorShowing())
566 return;
567 if (!this._messages.length)
568 return;
569 var position = this._lineHandle.resolve();
570 if (!position)
571 return;
572
573 var lineNumber = position.lineNumber;
574 var columnNumber = Number.MAX_VALUE;
575 var maxMessage = null;
576 for (var i = 0; i < this._messages.length; ++i) {
577 var message = this._messages[i].message();
578 columnNumber = Math.min(columnNumber, message.columnNumber());
579 if (!maxMessage || WebInspector.UISourceCode.Message.messageLevelCom parator(maxMessage, message) < 0)
580 maxMessage = message;
581 }
582 this._updateWavePosition(lineNumber, columnNumber);
583
584 if (this._level) {
585 this._textEditor.toggleLineClass(lineNumber, WebInspector.UISourceCo deFrame._lineClassPerLevel[this._level], false);
586 this._icon.type = "";
587 }
588 this._level = maxMessage.level();
589 if (!this._level)
590 return;
591 this._textEditor.toggleLineClass(lineNumber, WebInspector.UISourceCodeFr ame._lineClassPerLevel[this._level], true);
592 this._icon.type = WebInspector.UISourceCodeFrame._iconClassPerLevel[this ._level];
593 }
594 }
595
596 WebInspector.UISourceCode.Message._messageLevelPriority = {
597 "Warning": 3,
598 "Error": 4
599 };
600
601 /**
602 * @param {!WebInspector.UISourceCode.Message} a
603 * @param {!WebInspector.UISourceCode.Message} b
604 * @return {number}
605 */
606 WebInspector.UISourceCode.Message.messageLevelComparator = function(a, b)
607 {
608 return WebInspector.UISourceCode.Message._messageLevelPriority[a.level()] - WebInspector.UISourceCode.Message._messageLevelPriority[b.level()];
609 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698