blob: 67f3f3c50ccda8aa32040533683e52d6b698e775 [file] [log] [blame]
Ben Murdoch07a852d2014-03-31 11:51:52 +01001// 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";
Ben Murdochaafa69c2014-04-03 12:30:15 +010019 this.setMinimumAndPreferredSizes(50, 25, 150, 100);
Ben Murdoch07a852d2014-03-31 11:51:52 +010020
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.SourceFrame>} */
29 this._sourceFramesByUISourceCode = new Map();
30
31 var tabbedEditorPlaceholderText = WebInspector.isMac() ? WebInspector.UIString("Hit Cmd+O to open a file") : WebInspector.UIString("Hit Ctrl+O 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.ProjectWillReset, this._projectWillReset.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.panels.sources.showUISourceCode(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.ShortcutsScreen.SourcesPanelShortcuts.ToggleBreakpoint, this._toggleBreakpoint.bind(this));
116 registerShortcut.call(this, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.Save, this._save.bind(this));
117 },
118
119 /**
120 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} keys
121 * @param {function(?Event=):boolean} handler
122 */
123 _registerShortcuts: function(keys, handler)
124 {
125 for (var i = 0; i < keys.length; ++i)
126 this._shortcuts[keys[i].key] = handler;
127 },
128
129 _handleKeyDown: function(event)
130 {
131 var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
132 var handler = this._shortcuts[shortcutKey];
133 if (handler && handler())
134 event.consume(true);
135 },
136
137 /**
138 * @return {!Element}
139 */
140 statusBarContainerElement: function()
141 {
142 return this._statusBarContainerElement;
143 },
144
145 /**
146 * @return {!Element}
147 */
148 defaultFocusedElement: function()
149 {
150 return this._editorContainer.view.defaultFocusedElement();
151 },
152
153 /**
154 * @return {!WebInspector.SearchableView}
155 */
156 searchableView: function()
157 {
158 return this._searchableView;
159 },
160
161 /**
162 * @return {!WebInspector.View}
163 */
164 visibleView: function()
165 {
166 return this._editorContainer.visibleView;
167 },
168
169 /**
170 * @return {?WebInspector.SourceFrame}
171 */
172 currentSourceFrame: function()
173 {
174 var view = this.visibleView();
175 if (!(view instanceof WebInspector.SourceFrame))
176 return null;
177 return /** @type {!WebInspector.SourceFrame} */ (view);
178 },
179
180 /**
181 * @return {?WebInspector.UISourceCode}
182 */
183 currentUISourceCode: function()
184 {
185 return this._currentUISourceCode;
186 },
187
188 /**
189 * @param {?Event=} event
190 */
191 _onCloseEditorTab: function(event)
192 {
193 var uiSourceCode = this.currentUISourceCode();
194 if (!uiSourceCode)
195 return false;
196 this._editorContainer.closeFile(uiSourceCode);
197 return true;
198 },
199
200 /**
201 * @param {?Event=} event
202 */
203 _onJumpToPreviousLocation: function(event)
204 {
205 this._historyManager.rollback();
206 return true;
207 },
208
209 /**
210 * @param {?Event=} event
211 */
212 _onJumpToNextLocation: function(event)
213 {
214 this._historyManager.rollover();
215 return true;
216 },
217
218 /**
219 * @param {!WebInspector.Event} event
220 */
221 _uiSourceCodeAdded: function(event)
222 {
223 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
224 this._addUISourceCode(uiSourceCode);
225 },
226
227 /**
228 * @param {!WebInspector.UISourceCode} uiSourceCode
229 */
230 _addUISourceCode: function(uiSourceCode)
231 {
232 if (uiSourceCode.project().isServiceProject())
233 return;
234 this._editorContainer.addUISourceCode(uiSourceCode);
235 // Replace debugger script-based uiSourceCode with a network-based one.
236 var currentUISourceCode = this._currentUISourceCode;
237 if (currentUISourceCode && currentUISourceCode.project().isServiceProject() && currentUISourceCode !== uiSourceCode && currentUISourceCode.url === uiSourceCode.url) {
238 this._showFile(uiSourceCode);
239 this._editorContainer.removeUISourceCode(currentUISourceCode);
240 }
241 },
242
243 _uiSourceCodeRemoved: function(event)
244 {
245 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
246 this._removeUISourceCodes([uiSourceCode]);
247 },
248
249 /**
250 * @param {!Array.<!WebInspector.UISourceCode>} uiSourceCodes
251 */
252 _removeUISourceCodes: function(uiSourceCodes)
253 {
254 for (var i = 0; i < uiSourceCodes.length; ++i) {
255 this._removeSourceFrame(uiSourceCodes[i]);
256 this._historyManager.removeHistoryForSourceCode(uiSourceCodes[i]);
257 }
258 this._editorContainer.removeUISourceCodes(uiSourceCodes);
259 },
260
261 _projectWillReset: function(event)
262 {
263 var project = event.data;
264 var uiSourceCodes = project.uiSourceCodes();
265 this._removeUISourceCodes(uiSourceCodes);
266 if (project.type() === WebInspector.projectTypes.Network)
267 this._editorContainer.reset();
268 },
269
270 _updateScriptViewStatusBarItems: function()
271 {
272 this._scriptViewStatusBarItemsContainer.removeChildren();
273 this._scriptViewStatusBarTextContainer.removeChildren();
274 var sourceFrame = this.currentSourceFrame();
275 if (!sourceFrame)
276 return;
277
278 var statusBarItems = sourceFrame.statusBarItems() || [];
279 for (var i = 0; i < statusBarItems.length; ++i)
280 this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
281 var statusBarText = sourceFrame.statusBarText();
282 if (statusBarText)
283 this._scriptViewStatusBarTextContainer.appendChild(statusBarText);
284 },
285
286 /**
287 * @param {!WebInspector.UISourceCode} uiSourceCode
288 * @param {number=} lineNumber
289 * @param {number=} columnNumber
290 * @param {boolean=} omitFocus
291 * @param {boolean=} omitHighlight
292 */
293 showSourceLocation: function(uiSourceCode, lineNumber, columnNumber, omitFocus, omitHighlight)
294 {
295 this._historyManager.updateCurrentState();
296 var sourceFrame = this._showFile(uiSourceCode);
297 if (typeof lineNumber === "number")
298 sourceFrame.revealPosition(lineNumber, columnNumber, !omitHighlight);
299 this._historyManager.pushNewState();
300 if (!omitFocus)
301 sourceFrame.focus();
302 WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
303 action: WebInspector.UserMetrics.UserActionNames.OpenSourceLink,
304 url: uiSourceCode.originURL(),
305 lineNumber: lineNumber
306 });
307 },
308
309 /**
310 * @param {!WebInspector.UISourceCode} uiSourceCode
311 * @return {!WebInspector.SourceFrame}
312 */
313 _showFile: function(uiSourceCode)
314 {
315 var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode);
316 if (this._currentUISourceCode === uiSourceCode)
317 return sourceFrame;
318
319 this._currentUISourceCode = uiSourceCode;
320 this._editorContainer.showFile(uiSourceCode);
321 this._updateScriptViewStatusBarItems();
322 return sourceFrame;
323 },
324
325 /**
326 * @param {!WebInspector.UISourceCode} uiSourceCode
327 * @return {!WebInspector.SourceFrame}
328 */
329 _createSourceFrame: function(uiSourceCode)
330 {
331 var sourceFrame;
332 switch (uiSourceCode.contentType()) {
333 case WebInspector.resourceTypes.Script:
334 sourceFrame = new WebInspector.JavaScriptSourceFrame(this._sourcesPanel, uiSourceCode);
335 break;
336 case WebInspector.resourceTypes.Document:
337 sourceFrame = new WebInspector.JavaScriptSourceFrame(this._sourcesPanel, uiSourceCode);
338 break;
339 case WebInspector.resourceTypes.Stylesheet:
340 sourceFrame = new WebInspector.CSSSourceFrame(uiSourceCode);
341 break;
342 default:
343 sourceFrame = new WebInspector.UISourceCodeFrame(uiSourceCode);
344 break;
345 }
346 sourceFrame.setHighlighterType(uiSourceCode.highlighterType());
347 this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame);
348 this._historyManager.trackSourceFrameCursorJumps(sourceFrame);
349 return sourceFrame;
350 },
351
352 /**
353 * @param {!WebInspector.UISourceCode} uiSourceCode
354 * @return {!WebInspector.SourceFrame}
355 */
356 _getOrCreateSourceFrame: function(uiSourceCode)
357 {
358 return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode);
359 },
360
361 /**
362 * @param {!WebInspector.SourceFrame} sourceFrame
363 * @param {!WebInspector.UISourceCode} uiSourceCode
364 * @return {boolean}
365 */
366 _sourceFrameMatchesUISourceCode: function(sourceFrame, uiSourceCode)
367 {
368 switch (uiSourceCode.contentType()) {
369 case WebInspector.resourceTypes.Script:
370 case WebInspector.resourceTypes.Document:
371 return sourceFrame instanceof WebInspector.JavaScriptSourceFrame;
372 case WebInspector.resourceTypes.Stylesheet:
373 return sourceFrame instanceof WebInspector.CSSSourceFrame;
374 default:
375 return !(sourceFrame instanceof WebInspector.JavaScriptSourceFrame);
376 }
377 },
378
379 /**
380 * @param {!WebInspector.UISourceCode} uiSourceCode
381 */
382 _recreateSourceFrameIfNeeded: function(uiSourceCode)
383 {
384 var oldSourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
385 if (!oldSourceFrame)
386 return;
387 if (this._sourceFrameMatchesUISourceCode(oldSourceFrame, uiSourceCode)) {
388 oldSourceFrame.setHighlighterType(uiSourceCode.highlighterType());
389 } else {
390 this._editorContainer.removeUISourceCode(uiSourceCode);
391 this._removeSourceFrame(uiSourceCode);
392 }
393 },
394
395 /**
396 * @param {!WebInspector.UISourceCode} uiSourceCode
397 * @return {!WebInspector.SourceFrame}
398 */
399 viewForFile: function(uiSourceCode)
400 {
401 return this._getOrCreateSourceFrame(uiSourceCode);
402 },
403
404 /**
405 * @param {!WebInspector.UISourceCode} uiSourceCode
406 */
407 _removeSourceFrame: function(uiSourceCode)
408 {
409 var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
410 if (!sourceFrame)
411 return;
412 this._sourceFramesByUISourceCode.remove(uiSourceCode);
413 sourceFrame.dispose();
414 },
415
416 clearCurrentExecutionLine: function()
417 {
418 if (this._executionSourceFrame)
419 this._executionSourceFrame.clearExecutionLine();
420 delete this._executionSourceFrame;
421 },
422
423 setExecutionLine: function(uiLocation)
424 {
425 var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode);
426 sourceFrame.setExecutionLine(uiLocation.lineNumber);
427 this._executionSourceFrame = sourceFrame;
428 },
429
430 _editorClosed: function(event)
431 {
432 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
433 this._historyManager.removeHistoryForSourceCode(uiSourceCode);
434
435 var wasSelected = false;
436 if (this._currentUISourceCode === uiSourceCode) {
437 delete this._currentUISourceCode;
438 wasSelected = true;
439 }
440
441 // SourcesNavigator does not need to update on EditorClosed.
442 this._updateScriptViewStatusBarItems();
443 this._searchableView.resetSearch();
444
445 var data = {};
446 data.uiSourceCode = uiSourceCode;
447 data.wasSelected = wasSelected;
448 this.dispatchEventToListeners(WebInspector.SourcesView.Events.EditorClosed, data);
449 },
450
451 _editorSelected: function(event)
452 {
453 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.currentFile);
454 var shouldUseHistoryManager = uiSourceCode !== this._currentUISourceCode && event.data.userGesture;
455 if (shouldUseHistoryManager)
456 this._historyManager.updateCurrentState();
457 var sourceFrame = this._showFile(uiSourceCode);
458 if (shouldUseHistoryManager)
459 this._historyManager.pushNewState();
460
461 this._searchableView.setReplaceable(!!sourceFrame && sourceFrame.canEditSource());
462 this._searchableView.resetSearch();
463
464 this.dispatchEventToListeners(WebInspector.SourcesView.Events.EditorSelected, uiSourceCode);
465 },
466
467 /**
468 * @param {!WebInspector.UISourceCode} uiSourceCode
469 */
470 sourceRenamed: function(uiSourceCode)
471 {
472 this._recreateSourceFrameIfNeeded(uiSourceCode);
473 },
474
475 searchCanceled: function()
476 {
477 if (this._searchView)
478 this._searchView.searchCanceled();
479
480 delete this._searchView;
481 delete this._searchQuery;
482 },
483
484 /**
485 * @param {string} query
486 * @param {boolean} shouldJump
487 */
488 performSearch: function(query, shouldJump)
489 {
490 this._searchableView.updateSearchMatchesCount(0);
491
492 var sourceFrame = this.currentSourceFrame();
493 if (!sourceFrame)
494 return;
495
496 this._searchView = sourceFrame;
497 this._searchQuery = query;
498
499 /**
500 * @param {!WebInspector.View} view
501 * @param {number} searchMatches
502 * @this {WebInspector.SourcesView}
503 */
504 function finishedCallback(view, searchMatches)
505 {
506 if (!searchMatches)
507 return;
508
509 this._searchableView.updateSearchMatchesCount(searchMatches);
510 }
511
512 /**
513 * @param {number} currentMatchIndex
514 * @this {WebInspector.SourcesView}
515 */
516 function currentMatchChanged(currentMatchIndex)
517 {
518 this._searchableView.updateCurrentMatchIndex(currentMatchIndex);
519 }
520
521 /**
522 * @this {WebInspector.SourcesView}
523 */
524 function searchResultsChanged()
525 {
526 this._searchableView.cancelSearch();
527 }
528
529 this._searchView.performSearch(query, shouldJump, finishedCallback.bind(this), currentMatchChanged.bind(this), searchResultsChanged.bind(this));
530 },
531
532 jumpToNextSearchResult: function()
533 {
534 if (!this._searchView)
535 return;
536
537 if (this._searchView !== this.currentSourceFrame()) {
538 this.performSearch(this._searchQuery, true);
539 return;
540 }
541
542 this._searchView.jumpToNextSearchResult();
543 },
544
545 jumpToPreviousSearchResult: function()
546 {
547 if (!this._searchView)
548 return;
549
550 if (this._searchView !== this.currentSourceFrame()) {
551 this.performSearch(this._searchQuery, true);
552 if (this._searchView)
553 this._searchView.jumpToLastSearchResult();
554 return;
555 }
556
557 this._searchView.jumpToPreviousSearchResult();
558 },
559
560 /**
561 * @param {string} text
562 */
563 replaceSelectionWith: function(text)
564 {
565 var sourceFrame = this.currentSourceFrame();
566 if (!sourceFrame) {
567 console.assert(sourceFrame);
568 return;
569 }
570 sourceFrame.replaceSelectionWith(text);
571 },
572
573 /**
574 * @param {string} query
575 * @param {string} text
576 */
577 replaceAllWith: function(query, text)
578 {
579 var sourceFrame = this.currentSourceFrame();
580 if (!sourceFrame) {
581 console.assert(sourceFrame);
582 return;
583 }
584 sourceFrame.replaceAllWith(query, text);
585 },
586
587 /**
588 * @param {?Event=} event
589 * @return {boolean}
590 */
591 _showOutlineDialog: function(event)
592 {
593 var uiSourceCode = this._editorContainer.currentFile();
594 if (!uiSourceCode)
595 return false;
596
597 switch (uiSourceCode.contentType()) {
598 case WebInspector.resourceTypes.Document:
599 case WebInspector.resourceTypes.Script:
600 WebInspector.JavaScriptOutlineDialog.show(this, uiSourceCode, this.showSourceLocation.bind(this, uiSourceCode));
601 return true;
602 case WebInspector.resourceTypes.Stylesheet:
603 WebInspector.StyleSheetOutlineDialog.show(this, uiSourceCode, this.showSourceLocation.bind(this, uiSourceCode));
604 return true;
605 }
606 return false;
607 },
608
609 /**
610 * @param {string=} query
611 */
612 showOpenResourceDialog: function(query)
613 {
614 var uiSourceCodes = this._editorContainer.historyUISourceCodes();
615 /** @type {!Map.<!WebInspector.UISourceCode, number>} */
616 var defaultScores = new Map();
617 for (var i = 1; i < uiSourceCodes.length; ++i) // Skip current element
618 defaultScores.put(uiSourceCodes[i], uiSourceCodes.length - i);
619 WebInspector.OpenResourceDialog.show(this, this.element, query, defaultScores);
620 },
621
622 /**
623 * @param {?Event=} event
624 * @return {boolean}
625 */
626 _showGoToLineDialog: function(event)
627 {
628 this.showOpenResourceDialog(":");
629 return true;
630 },
631
632 /**
633 * @return {boolean}
634 */
635 _save: function()
636 {
637 var sourceFrame = this.currentSourceFrame();
638 if (!sourceFrame)
639 return true;
640 if (!(sourceFrame instanceof WebInspector.UISourceCodeFrame))
641 return true;
642 var uiSourceCodeFrame = /** @type {!WebInspector.UISourceCodeFrame} */ (sourceFrame);
643 uiSourceCodeFrame.commitEditing();
644 return true;
645 },
646
647 /**
648 * @return {boolean}
649 */
650 _toggleBreakpoint: function()
651 {
652 var sourceFrame = this.currentSourceFrame();
653 if (!sourceFrame)
654 return false;
655
656 if (sourceFrame instanceof WebInspector.JavaScriptSourceFrame) {
657 var javaScriptSourceFrame = /** @type {!WebInspector.JavaScriptSourceFrame} */ (sourceFrame);
658 javaScriptSourceFrame.toggleBreakpointOnCurrentLine();
659 return true;
660 }
661 return false;
662 },
663
664 /**
665 * @param {boolean} active
666 */
667 toggleBreakpointsActiveState: function(active)
668 {
669 this._editorContainer.view.element.classList.toggle("breakpoints-deactivated", !active);
670 },
671
672 __proto__: WebInspector.VBox.prototype
673}
674
675/**
676 * @interface
677 */
678WebInspector.SourcesView.EditorAction = function()
679{
680}
681
682WebInspector.SourcesView.EditorAction.prototype = {
683 /**
684 * @param {!WebInspector.SourcesView} sourcesView
685 * @return {!Element}
686 */
687 button: function(sourcesView) { }
688}