1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** 6 * @constructor 7 * @implements {WebInspector.TabbedEditorContainerDelegate} 8 * @implements {WebInspector.Searchable} 9 * @implements {WebInspector.Replaceable} 10 * @extends {WebInspector.VBox} 11 * @param {!WebInspector.Workspace} workspace 12 * @param {!WebInspector.SourcesPanel} sourcesPanel 13 */ 14WebInspector.SourcesView = function(workspace, sourcesPanel) 15{ 16 WebInspector.VBox.call(this); 17 this.registerRequiredCSS("sourcesView.css"); 18 this.element.id = "sources-panel-sources-view"; 19 this.setMinimumAndPreferredSizes(50, 25, 150, 100); 20 21 this._workspace = workspace; 22 this._sourcesPanel = sourcesPanel; 23 24 this._searchableView = new WebInspector.SearchableView(this); 25 this._searchableView.setMinimalSearchQuerySize(0); 26 this._searchableView.show(this.element); 27 28 /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.UISourceCodeFrame>} */ 29 this._sourceFramesByUISourceCode = new Map(); 30 31 var tabbedEditorPlaceholderText = WebInspector.isMac() ? WebInspector.UIString("Hit Cmd+P to open a file") : WebInspector.UIString("Hit Ctrl+P to open a file"); 32 this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedFiles", tabbedEditorPlaceholderText); 33 this._editorContainer.show(this._searchableView.element); 34 this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this); 35 this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorClosed, this._editorClosed, this); 36 37 this._historyManager = new WebInspector.EditingLocationHistoryManager(this, this.currentSourceFrame.bind(this)); 38 39 this._scriptViewStatusBarItemsContainer = document.createElement("div"); 40 this._scriptViewStatusBarItemsContainer.className = "inline-block"; 41 42 this._scriptViewStatusBarTextContainer = document.createElement("div"); 43 this._scriptViewStatusBarTextContainer.className = "hbox"; 44 45 this._statusBarContainerElement = this.element.createChild("div", "sources-status-bar"); 46 47 /** 48 * @this {WebInspector.SourcesView} 49 * @param {!WebInspector.SourcesView.EditorAction} EditorAction 50 */ 51 function appendButtonForExtension(EditorAction) 52 { 53 this._statusBarContainerElement.appendChild(EditorAction.button(this)); 54 } 55 var editorActions = /** @type {!Array.<!WebInspector.SourcesView.EditorAction>} */ (WebInspector.moduleManager.instances(WebInspector.SourcesView.EditorAction)); 56 editorActions.forEach(appendButtonForExtension.bind(this)); 57 58 this._statusBarContainerElement.appendChild(this._scriptViewStatusBarItemsContainer); 59 this._statusBarContainerElement.appendChild(this._scriptViewStatusBarTextContainer); 60 61 WebInspector.startBatchUpdate(); 62 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)); 63 WebInspector.endBatchUpdate(); 64 65 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this); 66 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this); 67 this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved.bind(this), this); 68 69 function handleBeforeUnload(event) 70 { 71 if (event.returnValue) 72 return; 73 var unsavedSourceCodes = WebInspector.workspace.unsavedSourceCodes(); 74 if (!unsavedSourceCodes.length) 75 return; 76 77 event.returnValue = WebInspector.UIString("DevTools have unsaved changes that will be permanently lost."); 78 WebInspector.inspectorView.showPanel("sources"); 79 for (var i = 0; i < unsavedSourceCodes.length; ++i) 80 WebInspector.Revealer.reveal(unsavedSourceCodes[i]); 81 } 82 window.addEventListener("beforeunload", handleBeforeUnload, true); 83 84 this._shortcuts = {}; 85 this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); 86} 87 88WebInspector.SourcesView.Events = { 89 EditorClosed: "EditorClosed", 90 EditorSelected: "EditorSelected", 91} 92 93WebInspector.SourcesView.prototype = { 94 /** 95 * @param {function(!Array.<!WebInspector.KeyboardShortcut.Descriptor>, function(?Event=):boolean)} registerShortcutDelegate 96 */ 97 registerShortcuts: function(registerShortcutDelegate) 98 { 99 /** 100 * @this {WebInspector.SourcesView} 101 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts 102 * @param {function(?Event=):boolean} handler 103 */ 104 function registerShortcut(shortcuts, handler) 105 { 106 registerShortcutDelegate(shortcuts, handler); 107 this._registerShortcuts(shortcuts, handler); 108 } 109 110 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.JumpToPreviousLocation, this._onJumpToPreviousLocation.bind(this)); 111 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.JumpToNextLocation, this._onJumpToNextLocation.bind(this)); 112 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.CloseEditorTab, this._onCloseEditorTab.bind(this)); 113 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.GoToLine, this._showGoToLineDialog.bind(this)); 114 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.GoToMember, this._showOutlineDialog.bind(this)); 115 registerShortcut.call(this, [WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift)], this._showOutlineDialog.bind(this)); 116 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.ToggleBreakpoint, this._toggleBreakpoint.bind(this)); 117 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.Save, this._save.bind(this)); 118 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.SaveAll, this._saveAll.bind(this)); 119 }, 120 121 /** 122 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} keys 123 * @param {function(?Event=):boolean} handler 124 */ 125 _registerShortcuts: function(keys, handler) 126 { 127 for (var i = 0; i < keys.length; ++i) 128 this._shortcuts[keys[i].key] = handler; 129 }, 130 131 _handleKeyDown: function(event) 132 { 133 var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); 134 var handler = this._shortcuts[shortcutKey]; 135 if (handler && handler()) 136 event.consume(true); 137 }, 138 139 /** 140 * @return {!Element} 141 */ 142 statusBarContainerElement: function() 143 { 144 return this._statusBarContainerElement; 145 }, 146 147 /** 148 * @return {!Element} 149 */ 150 defaultFocusedElement: function() 151 { 152 return this._editorContainer.view.defaultFocusedElement(); 153 }, 154 155 /** 156 * @return {!WebInspector.SearchableView} 157 */ 158 searchableView: function() 159 { 160 return this._searchableView; 161 }, 162 163 /** 164 * @return {!WebInspector.View} 165 */ 166 visibleView: function() 167 { 168 return this._editorContainer.visibleView; 169 }, 170 171 /** 172 * @return {?WebInspector.SourceFrame} 173 */ 174 currentSourceFrame: function() 175 { 176 var view = this.visibleView(); 177 if (!(view instanceof WebInspector.SourceFrame)) 178 return null; 179 return /** @type {!WebInspector.SourceFrame} */ (view); 180 }, 181 182 /** 183 * @return {?WebInspector.UISourceCode} 184 */ 185 currentUISourceCode: function() 186 { 187 return this._currentUISourceCode; 188 }, 189 190 /** 191 * @param {?Event=} event 192 */ 193 _onCloseEditorTab: function(event) 194 { 195 var uiSourceCode = this.currentUISourceCode(); 196 if (!uiSourceCode) 197 return false; 198 this._editorContainer.closeFile(uiSourceCode); 199 return true; 200 }, 201 202 /** 203 * @param {?Event=} event 204 */ 205 _onJumpToPreviousLocation: function(event) 206 { 207 this._historyManager.rollback(); 208 return true; 209 }, 210 211 /** 212 * @param {?Event=} event 213 */ 214 _onJumpToNextLocation: function(event) 215 { 216 this._historyManager.rollover(); 217 return true; 218 }, 219 220 /** 221 * @param {!WebInspector.Event} event 222 */ 223 _uiSourceCodeAdded: function(event) 224 { 225 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); 226 this._addUISourceCode(uiSourceCode); 227 }, 228 229 /** 230 * @param {!WebInspector.UISourceCode} uiSourceCode 231 */ 232 _addUISourceCode: function(uiSourceCode) 233 { 234 if (uiSourceCode.project().isServiceProject()) 235 return; 236 this._editorContainer.addUISourceCode(uiSourceCode); 237 // Replace debugger script-based uiSourceCode with a network-based one. 238 var currentUISourceCode = this._currentUISourceCode; 239 if (currentUISourceCode && currentUISourceCode.project().isServiceProject() && currentUISourceCode !== uiSourceCode && currentUISourceCode.url === uiSourceCode.url) { 240 this._showFile(uiSourceCode); 241 this._editorContainer.removeUISourceCode(currentUISourceCode); 242 } 243 }, 244 245 _uiSourceCodeRemoved: function(event) 246 { 247 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); 248 this._removeUISourceCodes([uiSourceCode]); 249 }, 250 251 /** 252 * @param {!Array.<!WebInspector.UISourceCode>} uiSourceCodes 253 */ 254 _removeUISourceCodes: function(uiSourceCodes) 255 { 256 this._editorContainer.removeUISourceCodes(uiSourceCodes); 257 for (var i = 0; i < uiSourceCodes.length; ++i) { 258 this._removeSourceFrame(uiSourceCodes[i]); 259 this._historyManager.removeHistoryForSourceCode(uiSourceCodes[i]); 260 } 261 }, 262 263 _projectRemoved: function(event) 264 { 265 var project = event.data; 266 var uiSourceCodes = project.uiSourceCodes(); 267 this._removeUISourceCodes(uiSourceCodes); 268 if (project.type() === WebInspector.projectTypes.Network) 269 this._editorContainer.reset(); 270 }, 271 272 _updateScriptViewStatusBarItems: function() 273 { 274 this._scriptViewStatusBarItemsContainer.removeChildren(); 275 this._scriptViewStatusBarTextContainer.removeChildren(); 276 var sourceFrame = this.currentSourceFrame(); 277 if (!sourceFrame) 278 return; 279 280 var statusBarItems = sourceFrame.statusBarItems() || []; 281 for (var i = 0; i < statusBarItems.length; ++i) 282 this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]); 283 var statusBarText = sourceFrame.statusBarText(); 284 if (statusBarText) 285 this._scriptViewStatusBarTextContainer.appendChild(statusBarText); 286 }, 287 288 /** 289 * @param {!WebInspector.UISourceCode} uiSourceCode 290 * @param {number=} lineNumber 291 * @param {number=} columnNumber 292 * @param {boolean=} omitFocus 293 * @param {boolean=} omitHighlight 294 */ 295 showSourceLocation: function(uiSourceCode, lineNumber, columnNumber, omitFocus, omitHighlight) 296 { 297 this._historyManager.updateCurrentState(); 298 var sourceFrame = this._showFile(uiSourceCode); 299 if (typeof lineNumber === "number") 300 sourceFrame.revealPosition(lineNumber, columnNumber, !omitHighlight); 301 this._historyManager.pushNewState(); 302 if (!omitFocus) 303 sourceFrame.focus(); 304 WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, { 305 action: WebInspector.UserMetrics.UserActionNames.OpenSourceLink, 306 url: uiSourceCode.originURL(), 307 lineNumber: lineNumber 308 }); 309 }, 310 311 /** 312 * @param {!WebInspector.UISourceCode} uiSourceCode 313 * @return {!WebInspector.SourceFrame} 314 */ 315 _showFile: function(uiSourceCode) 316 { 317 var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode); 318 if (this._currentUISourceCode === uiSourceCode) 319 return sourceFrame; 320 321 this._currentUISourceCode = uiSourceCode; 322 this._editorContainer.showFile(uiSourceCode); 323 this._updateScriptViewStatusBarItems(); 324 return sourceFrame; 325 }, 326 327 /** 328 * @param {!WebInspector.UISourceCode} uiSourceCode 329 * @return {!WebInspector.UISourceCodeFrame} 330 */ 331 _createSourceFrame: function(uiSourceCode) 332 { 333 var sourceFrame; 334 switch (uiSourceCode.contentType()) { 335 case WebInspector.resourceTypes.Script: 336 sourceFrame = new WebInspector.JavaScriptSourceFrame(this._sourcesPanel, uiSourceCode); 337 break; 338 case WebInspector.resourceTypes.Document: 339 sourceFrame = new WebInspector.JavaScriptSourceFrame(this._sourcesPanel, uiSourceCode); 340 break; 341 case WebInspector.resourceTypes.Stylesheet: 342 sourceFrame = new WebInspector.CSSSourceFrame(uiSourceCode); 343 break; 344 default: 345 sourceFrame = new WebInspector.UISourceCodeFrame(uiSourceCode); 346 break; 347 } 348 sourceFrame.setHighlighterType(uiSourceCode.highlighterType()); 349 this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame); 350 this._historyManager.trackSourceFrameCursorJumps(sourceFrame); 351 return sourceFrame; 352 }, 353 354 /** 355 * @param {!WebInspector.UISourceCode} uiSourceCode 356 * @return {!WebInspector.UISourceCodeFrame} 357 */ 358 _getOrCreateSourceFrame: function(uiSourceCode) 359 { 360 return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode); 361 }, 362 363 /** 364 * @param {!WebInspector.SourceFrame} sourceFrame 365 * @param {!WebInspector.UISourceCode} uiSourceCode 366 * @return {boolean} 367 */ 368 _sourceFrameMatchesUISourceCode: function(sourceFrame, uiSourceCode) 369 { 370 switch (uiSourceCode.contentType()) { 371 case WebInspector.resourceTypes.Script: 372 case WebInspector.resourceTypes.Document: 373 return sourceFrame instanceof WebInspector.JavaScriptSourceFrame; 374 case WebInspector.resourceTypes.Stylesheet: 375 return sourceFrame instanceof WebInspector.CSSSourceFrame; 376 default: 377 return !(sourceFrame instanceof WebInspector.JavaScriptSourceFrame); 378 } 379 }, 380 381 /** 382 * @param {!WebInspector.UISourceCode} uiSourceCode 383 */ 384 _recreateSourceFrameIfNeeded: function(uiSourceCode) 385 { 386 var oldSourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode); 387 if (!oldSourceFrame) 388 return; 389 if (this._sourceFrameMatchesUISourceCode(oldSourceFrame, uiSourceCode)) { 390 oldSourceFrame.setHighlighterType(uiSourceCode.highlighterType()); 391 } else { 392 this._editorContainer.removeUISourceCode(uiSourceCode); 393 this._removeSourceFrame(uiSourceCode); 394 } 395 }, 396 397 /** 398 * @param {!WebInspector.UISourceCode} uiSourceCode 399 * @return {!WebInspector.SourceFrame} 400 */ 401 viewForFile: function(uiSourceCode) 402 { 403 return this._getOrCreateSourceFrame(uiSourceCode); 404 }, 405 406 /** 407 * @param {!WebInspector.UISourceCode} uiSourceCode 408 */ 409 _removeSourceFrame: function(uiSourceCode) 410 { 411 var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode); 412 if (!sourceFrame) 413 return; 414 this._sourceFramesByUISourceCode.remove(uiSourceCode); 415 sourceFrame.dispose(); 416 }, 417 418 clearCurrentExecutionLine: function() 419 { 420 if (this._executionSourceFrame) 421 this._executionSourceFrame.clearExecutionLine(); 422 delete this._executionSourceFrame; 423 }, 424 425 setExecutionLine: function(uiLocation) 426 { 427 var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode); 428 sourceFrame.setExecutionLine(uiLocation.lineNumber); 429 this._executionSourceFrame = sourceFrame; 430 }, 431 432 _editorClosed: function(event) 433 { 434 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); 435 this._historyManager.removeHistoryForSourceCode(uiSourceCode); 436 437 var wasSelected = false; 438 if (this._currentUISourceCode === uiSourceCode) { 439 delete this._currentUISourceCode; 440 wasSelected = true; 441 } 442 443 // SourcesNavigator does not need to update on EditorClosed. 444 this._updateScriptViewStatusBarItems(); 445 this._searchableView.resetSearch(); 446 447 var data = {}; 448 data.uiSourceCode = uiSourceCode; 449 data.wasSelected = wasSelected; 450 this.dispatchEventToListeners(WebInspector.SourcesView.Events.EditorClosed, data); 451 }, 452 453 _editorSelected: function(event) 454 { 455 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.currentFile); 456 var shouldUseHistoryManager = uiSourceCode !== this._currentUISourceCode && event.data.userGesture; 457 if (shouldUseHistoryManager) 458 this._historyManager.updateCurrentState(); 459 var sourceFrame = this._showFile(uiSourceCode); 460 if (shouldUseHistoryManager) 461 this._historyManager.pushNewState(); 462 463 this._searchableView.setReplaceable(!!sourceFrame && sourceFrame.canEditSource()); 464 this._searchableView.resetSearch(); 465 466 this.dispatchEventToListeners(WebInspector.SourcesView.Events.EditorSelected, uiSourceCode); 467 }, 468 469 /** 470 * @param {!WebInspector.UISourceCode} uiSourceCode 471 */ 472 sourceRenamed: function(uiSourceCode) 473 { 474 this._recreateSourceFrameIfNeeded(uiSourceCode); 475 }, 476 477 searchCanceled: function() 478 { 479 if (this._searchView) 480 this._searchView.searchCanceled(); 481 482 delete this._searchView; 483 delete this._searchQuery; 484 }, 485 486 /** 487 * @param {string} query 488 * @param {boolean} shouldJump 489 * @param {boolean=} jumpBackwards 490 */ 491 performSearch: function(query, shouldJump, jumpBackwards) 492 { 493 this._searchableView.updateSearchMatchesCount(0); 494 495 var sourceFrame = this.currentSourceFrame(); 496 if (!sourceFrame) 497 return; 498 499 this._searchView = sourceFrame; 500 this._searchQuery = query; 501 502 /** 503 * @param {!WebInspector.View} view 504 * @param {number} searchMatches 505 * @this {WebInspector.SourcesView} 506 */ 507 function finishedCallback(view, searchMatches) 508 { 509 if (!searchMatches) 510 return; 511 512 this._searchableView.updateSearchMatchesCount(searchMatches); 513 } 514 515 /** 516 * @param {number} currentMatchIndex 517 * @this {WebInspector.SourcesView} 518 */ 519 function currentMatchChanged(currentMatchIndex) 520 { 521 this._searchableView.updateCurrentMatchIndex(currentMatchIndex); 522 } 523 524 /** 525 * @this {WebInspector.SourcesView} 526 */ 527 function searchResultsChanged() 528 { 529 this._searchableView.cancelSearch(); 530 } 531 532 this._searchView.performSearch(query, shouldJump, !!jumpBackwards, finishedCallback.bind(this), currentMatchChanged.bind(this), searchResultsChanged.bind(this)); 533 }, 534 535 jumpToNextSearchResult: function() 536 { 537 if (!this._searchView) 538 return; 539 540 if (this._searchView !== this.currentSourceFrame()) { 541 this.performSearch(this._searchQuery, true); 542 return; 543 } 544 545 this._searchView.jumpToNextSearchResult(); 546 }, 547 548 jumpToPreviousSearchResult: function() 549 { 550 if (!this._searchView) 551 return; 552 553 if (this._searchView !== this.currentSourceFrame()) { 554 this.performSearch(this._searchQuery, true); 555 if (this._searchView) 556 this._searchView.jumpToLastSearchResult(); 557 return; 558 } 559 560 this._searchView.jumpToPreviousSearchResult(); 561 }, 562 563 /** 564 * @param {string} text 565 */ 566 replaceSelectionWith: function(text) 567 { 568 var sourceFrame = this.currentSourceFrame(); 569 if (!sourceFrame) { 570 console.assert(sourceFrame); 571 return; 572 } 573 sourceFrame.replaceSelectionWith(text); 574 }, 575 576 /** 577 * @param {string} query 578 * @param {string} text 579 */ 580 replaceAllWith: function(query, text) 581 { 582 var sourceFrame = this.currentSourceFrame(); 583 if (!sourceFrame) { 584 console.assert(sourceFrame); 585 return; 586 } 587 sourceFrame.replaceAllWith(query, text); 588 }, 589 590 /** 591 * @param {?Event=} event 592 * @return {boolean} 593 */ 594 _showOutlineDialog: function(event) 595 { 596 var uiSourceCode = this._editorContainer.currentFile(); 597 if (!uiSourceCode) 598 return false; 599 600 switch (uiSourceCode.contentType()) { 601 case WebInspector.resourceTypes.Document: 602 case WebInspector.resourceTypes.Script: 603 WebInspector.JavaScriptOutlineDialog.show(this, uiSourceCode, this.showSourceLocation.bind(this, uiSourceCode)); 604 return true; 605 case WebInspector.resourceTypes.Stylesheet: 606 WebInspector.StyleSheetOutlineDialog.show(this, uiSourceCode, this.showSourceLocation.bind(this, uiSourceCode)); 607 return true; 608 } 609 return false; 610 }, 611 612 /** 613 * @param {string=} query 614 */ 615 showOpenResourceDialog: function(query) 616 { 617 var uiSourceCodes = this._editorContainer.historyUISourceCodes(); 618 /** @type {!Map.<!WebInspector.UISourceCode, number>} */ 619 var defaultScores = new Map(); 620 for (var i = 1; i < uiSourceCodes.length; ++i) // Skip current element 621 defaultScores.put(uiSourceCodes[i], uiSourceCodes.length - i); 622 WebInspector.OpenResourceDialog.show(this, this.element, query, defaultScores); 623 }, 624 625 /** 626 * @param {?Event=} event 627 * @return {boolean} 628 */ 629 _showGoToLineDialog: function(event) 630 { 631 if (this._currentUISourceCode) 632 this.showOpenResourceDialog(":"); 633 return true; 634 }, 635 636 /** 637 * @return {boolean} 638 */ 639 _save: function() 640 { 641 this._saveSourceFrame(this.currentSourceFrame()); 642 return true; 643 }, 644 645 /** 646 * @return {boolean} 647 */ 648 _saveAll: function() 649 { 650 var sourceFrames = this._editorContainer.fileViews(); 651 sourceFrames.forEach(this._saveSourceFrame.bind(this)); 652 return true; 653 }, 654 655 /** 656 * @param {?WebInspector.SourceFrame} sourceFrame 657 */ 658 _saveSourceFrame: function(sourceFrame) 659 { 660 if (!sourceFrame) 661 return; 662 if (!(sourceFrame instanceof WebInspector.UISourceCodeFrame)) 663 return; 664 var uiSourceCodeFrame = /** @type {!WebInspector.UISourceCodeFrame} */ (sourceFrame); 665 uiSourceCodeFrame.commitEditing(); 666 }, 667 /** 668 * @return {boolean} 669 */ 670 _toggleBreakpoint: function() 671 { 672 var sourceFrame = this.currentSourceFrame(); 673 if (!sourceFrame) 674 return false; 675 676 if (sourceFrame instanceof WebInspector.JavaScriptSourceFrame) { 677 var javaScriptSourceFrame = /** @type {!WebInspector.JavaScriptSourceFrame} */ (sourceFrame); 678 javaScriptSourceFrame.toggleBreakpointOnCurrentLine(); 679 return true; 680 } 681 return false; 682 }, 683 684 /** 685 * @param {boolean} active 686 */ 687 toggleBreakpointsActiveState: function(active) 688 { 689 this._editorContainer.view.element.classList.toggle("breakpoints-deactivated", !active); 690 }, 691 692 __proto__: WebInspector.VBox.prototype 693} 694 695/** 696 * @interface 697 */ 698WebInspector.SourcesView.EditorAction = function() 699{ 700} 701 702WebInspector.SourcesView.EditorAction.prototype = { 703 /** 704 * @param {!WebInspector.SourcesView} sourcesView 705 * @return {!Element} 706 */ 707 button: function(sourcesView) { } 708} 709