OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |