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

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

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 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) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 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 *
11 * 2. Redistributions in binary form must reproduce the above 11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer 12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the 13 * in the documentation and/or other materials provided with the
14 * distribution. 14 * distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28
29 /** 28 /**
30 * @interface 29 * @interface
31 */ 30 */
32 WebInspector.TabbedEditorContainerDelegate = function() { }; 31 WebInspector.TabbedEditorContainerDelegate = function() {};
33 32
34 WebInspector.TabbedEditorContainerDelegate.prototype = { 33 WebInspector.TabbedEditorContainerDelegate.prototype = {
35 /** 34 /**
36 * @param {!WebInspector.UISourceCode} uiSourceCode 35 * @param {!WebInspector.UISourceCode} uiSourceCode
37 * @return {!WebInspector.Widget} 36 * @return {!WebInspector.Widget}
38 */ 37 */
39 viewForFile: function(uiSourceCode) { }, 38 viewForFile: function(uiSourceCode) {},
40 }; 39 };
41 40
42 /** 41 /**
43 * @constructor 42 * @unrestricted
44 * @extends {WebInspector.Object}
45 * @param {!WebInspector.TabbedEditorContainerDelegate} delegate
46 * @param {!WebInspector.Setting} setting
47 * @param {string} placeholderText
48 */ 43 */
49 WebInspector.TabbedEditorContainer = function(delegate, setting, placeholderText ) 44 WebInspector.TabbedEditorContainer = class extends WebInspector.Object {
50 { 45 /**
51 WebInspector.Object.call(this); 46 * @param {!WebInspector.TabbedEditorContainerDelegate} delegate
47 * @param {!WebInspector.Setting} setting
48 * @param {string} placeholderText
49 */
50 constructor(delegate, setting, placeholderText) {
51 super();
52 this._delegate = delegate; 52 this._delegate = delegate;
53 53
54 this._tabbedPane = new WebInspector.TabbedPane(); 54 this._tabbedPane = new WebInspector.TabbedPane();
55 this._tabbedPane.setPlaceholderText(placeholderText); 55 this._tabbedPane.setPlaceholderText(placeholderText);
56 this._tabbedPane.setTabDelegate(new WebInspector.EditorContainerTabDelegate( this)); 56 this._tabbedPane.setTabDelegate(new WebInspector.EditorContainerTabDelegate( this));
57 57
58 this._tabbedPane.setCloseableTabs(true); 58 this._tabbedPane.setCloseableTabs(true);
59 this._tabbedPane.setAllowTabReorder(true, true); 59 this._tabbedPane.setAllowTabReorder(true, true);
60 60
61 this._tabbedPane.addEventListener(WebInspector.TabbedPane.Events.TabClosed, this._tabClosed, this); 61 this._tabbedPane.addEventListener(WebInspector.TabbedPane.Events.TabClosed, this._tabClosed, this);
62 this._tabbedPane.addEventListener(WebInspector.TabbedPane.Events.TabSelected , this._tabSelected, this); 62 this._tabbedPane.addEventListener(WebInspector.TabbedPane.Events.TabSelected , this._tabSelected, this);
63 63
64 WebInspector.persistence.addEventListener(WebInspector.Persistence.Events.Bi ndingCreated, this._onBindingCreated, this); 64 WebInspector.persistence.addEventListener(
65 WebInspector.persistence.addEventListener(WebInspector.Persistence.Events.Bi ndingRemoved, this._onBindingRemoved, this); 65 WebInspector.Persistence.Events.BindingCreated, this._onBindingCreated, this);
66 WebInspector.persistence.addEventListener(
67 WebInspector.Persistence.Events.BindingRemoved, this._onBindingRemoved, this);
66 68
67 this._tabIds = new Map(); 69 this._tabIds = new Map();
68 this._files = {}; 70 this._files = {};
69 71
70 this._previouslyViewedFilesSetting = setting; 72 this._previouslyViewedFilesSetting = setting;
71 this._history = WebInspector.TabbedEditorContainer.History.fromObject(this._ previouslyViewedFilesSetting.get()); 73 this._history = WebInspector.TabbedEditorContainer.History.fromObject(this._ previouslyViewedFilesSetting.get());
74 }
75
76 /**
77 * @param {!WebInspector.Event} event
78 */
79 _onBindingCreated(event) {
80 var binding = /** @type {!WebInspector.PersistenceBinding} */ (event.data);
81 var networkTabId = this._tabIds.get(binding.network);
82 var fileSystemTabId = this._tabIds.get(binding.fileSystem);
83
84 if (networkTabId)
85 this._tabbedPane.changeTabTitle(
86 networkTabId, this._titleForFile(binding.fileSystem), this._tooltipFor File(binding.fileSystem));
87 if (!fileSystemTabId)
88 return;
89
90 var wasSelectedInFileSystem = this._currentFile === binding.fileSystem;
91 var currentSelectionRange = this._history.selectionRange(binding.fileSystem. url());
92 var currentScrollLineNumber = this._history.scrollLineNumber(binding.fileSys tem.url());
93
94 var tabIndex = this._tabbedPane.tabIndex(fileSystemTabId);
95 var tabsToClose = [fileSystemTabId];
96 if (networkTabId)
97 tabsToClose.push(networkTabId);
98 this._closeTabs(tabsToClose, true);
99 networkTabId = this._appendFileTab(binding.network, false, tabIndex);
100 this._updateHistory();
101
102 if (wasSelectedInFileSystem)
103 this._tabbedPane.selectTab(networkTabId, false);
104
105 var networkTabView = /** @type {!WebInspector.Widget} */ (this._tabbedPane.t abView(networkTabId));
106 this._restoreEditorProperties(networkTabView, currentSelectionRange, current ScrollLineNumber);
107 }
108
109 /**
110 * @param {!WebInspector.Event} event
111 */
112 _onBindingRemoved(event) {
113 var binding = /** @type {!WebInspector.PersistenceBinding} */ (event.data);
114 var networkTabId = this._tabIds.get(binding.network);
115 if (!networkTabId)
116 return;
117 var tabIndex = this._tabbedPane.tabIndex(networkTabId);
118 var wasSelected = this._currentFile === binding.network;
119 var fileSystemTabId = this._appendFileTab(binding.fileSystem, false, tabInde x);
120 this._updateHistory();
121
122 if (wasSelected)
123 this._tabbedPane.selectTab(fileSystemTabId, false);
124
125 var fileSystemTabView = /** @type {!WebInspector.Widget} */ (this._tabbedPan e.tabView(fileSystemTabId));
126 var savedSelectionRange = this._history.selectionRange(binding.network.url() );
127 var savedScrollLineNumber = this._history.scrollLineNumber(binding.network.u rl());
128 this._restoreEditorProperties(fileSystemTabView, savedSelectionRange, savedS crollLineNumber);
129 }
130
131 /**
132 * @return {!WebInspector.Widget}
133 */
134 get view() {
135 return this._tabbedPane;
136 }
137
138 /**
139 * @return {?WebInspector.Widget}
140 */
141 get visibleView() {
142 return this._tabbedPane.visibleView;
143 }
144
145 /**
146 * @return {!Array.<!WebInspector.Widget>}
147 */
148 fileViews() {
149 return /** @type {!Array.<!WebInspector.Widget>} */ (this._tabbedPane.tabVie ws());
150 }
151
152 /**
153 * @return {!WebInspector.Toolbar}
154 */
155 leftToolbar() {
156 return this._tabbedPane.leftToolbar();
157 }
158
159 /**
160 * @return {!WebInspector.Toolbar}
161 */
162 rightToolbar() {
163 return this._tabbedPane.rightToolbar();
164 }
165
166 /**
167 * @param {!Element} parentElement
168 */
169 show(parentElement) {
170 this._tabbedPane.show(parentElement);
171 }
172
173 /**
174 * @param {!WebInspector.UISourceCode} uiSourceCode
175 */
176 showFile(uiSourceCode) {
177 this._innerShowFile(uiSourceCode, true);
178 }
179
180 /**
181 * @param {!WebInspector.UISourceCode} uiSourceCode
182 */
183 closeFile(uiSourceCode) {
184 var tabId = this._tabIds.get(uiSourceCode);
185 if (!tabId)
186 return;
187 this._closeTabs([tabId]);
188 }
189
190 closeAllFiles() {
191 this._closeTabs(this._tabbedPane.allTabs());
192 }
193
194 /**
195 * @return {!Array.<!WebInspector.UISourceCode>}
196 */
197 historyUISourceCodes() {
198 // FIXME: there should be a way to fetch UISourceCode for its uri.
199 var uriToUISourceCode = {};
200 for (var id in this._files) {
201 var uiSourceCode = this._files[id];
202 uriToUISourceCode[uiSourceCode.url()] = uiSourceCode;
203 }
204
205 var result = [];
206 var uris = this._history._urls();
207 for (var i = 0; i < uris.length; ++i) {
208 var uiSourceCode = uriToUISourceCode[uris[i]];
209 if (uiSourceCode)
210 result.push(uiSourceCode);
211 }
212 return result;
213 }
214
215 _addViewListeners() {
216 if (!this._currentView || !this._currentView.textEditor)
217 return;
218 this._currentView.textEditor.addEventListener(
219 WebInspector.SourcesTextEditor.Events.ScrollChanged, this._scrollChanged , this);
220 this._currentView.textEditor.addEventListener(
221 WebInspector.SourcesTextEditor.Events.SelectionChanged, this._selectionC hanged, this);
222 }
223
224 _removeViewListeners() {
225 if (!this._currentView || !this._currentView.textEditor)
226 return;
227 this._currentView.textEditor.removeEventListener(
228 WebInspector.SourcesTextEditor.Events.ScrollChanged, this._scrollChanged , this);
229 this._currentView.textEditor.removeEventListener(
230 WebInspector.SourcesTextEditor.Events.SelectionChanged, this._selectionC hanged, this);
231 }
232
233 /**
234 * @param {!WebInspector.Event} event
235 */
236 _scrollChanged(event) {
237 if (this._scrollTimer)
238 clearTimeout(this._scrollTimer);
239 var lineNumber = /** @type {number} */ (event.data);
240 this._scrollTimer = setTimeout(saveHistory.bind(this), 100);
241 this._history.updateScrollLineNumber(this._currentFile.url(), lineNumber);
242
243 /**
244 * @this {WebInspector.TabbedEditorContainer}
245 */
246 function saveHistory() {
247 this._history.save(this._previouslyViewedFilesSetting);
248 }
249 }
250
251 /**
252 * @param {!WebInspector.Event} event
253 */
254 _selectionChanged(event) {
255 var range = /** @type {!WebInspector.TextRange} */ (event.data);
256 this._history.updateSelectionRange(this._currentFile.url(), range);
257 this._history.save(this._previouslyViewedFilesSetting);
258 }
259
260 /**
261 * @param {!WebInspector.UISourceCode} uiSourceCode
262 * @param {boolean=} userGesture
263 */
264 _innerShowFile(uiSourceCode, userGesture) {
265 var binding = WebInspector.persistence.binding(uiSourceCode);
266 uiSourceCode = binding ? binding.network : uiSourceCode;
267 if (this._currentFile === uiSourceCode)
268 return;
269
270 this._removeViewListeners();
271 this._currentFile = uiSourceCode;
272
273 var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCo de, userGesture);
274
275 this._tabbedPane.selectTab(tabId, userGesture);
276 if (userGesture)
277 this._editorSelectedByUserAction();
278
279 var previousView = this._currentView;
280 this._currentView = this.visibleView;
281 this._addViewListeners();
282
283 var eventData = {
284 currentFile: this._currentFile,
285 currentView: this._currentView,
286 previousView: previousView,
287 userGesture: userGesture
288 };
289 this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events.Edit orSelected, eventData);
290 }
291
292 /**
293 * @param {!WebInspector.UISourceCode} uiSourceCode
294 * @return {string}
295 */
296 _titleForFile(uiSourceCode) {
297 var binding = WebInspector.persistence.binding(uiSourceCode);
298 var titleUISourceCode = binding ? binding.fileSystem : uiSourceCode;
299 var maxDisplayNameLength = 30;
300 var title = titleUISourceCode.displayName(true).trimMiddle(maxDisplayNameLen gth);
301 if (uiSourceCode.isDirty() || WebInspector.persistence.hasUnsavedCommittedCh anges(uiSourceCode))
302 title += '*';
303 return title;
304 }
305
306 /**
307 * @param {string} id
308 * @param {string} nextTabId
309 */
310 _maybeCloseTab(id, nextTabId) {
311 var uiSourceCode = this._files[id];
312 var shouldPrompt = uiSourceCode.isDirty() && uiSourceCode.project().canSetFi leContent();
313 // FIXME: this should be replaced with common Save/Discard/Cancel dialog.
314 if (!shouldPrompt ||
315 confirm(WebInspector.UIString('Are you sure you want to close unsaved fi le: %s?', uiSourceCode.name()))) {
316 uiSourceCode.resetWorkingCopy();
317 var previousView = this._currentView;
318 if (nextTabId)
319 this._tabbedPane.selectTab(nextTabId, true);
320 this._tabbedPane.closeTab(id, true);
321 return true;
322 }
323 return false;
324 }
325
326 /**
327 * @param {!Array.<string>} ids
328 * @param {boolean=} forceCloseDirtyTabs
329 */
330 _closeTabs(ids, forceCloseDirtyTabs) {
331 var dirtyTabs = [];
332 var cleanTabs = [];
333 for (var i = 0; i < ids.length; ++i) {
334 var id = ids[i];
335 var uiSourceCode = this._files[id];
336 if (!forceCloseDirtyTabs && uiSourceCode.isDirty())
337 dirtyTabs.push(id);
338 else
339 cleanTabs.push(id);
340 }
341 if (dirtyTabs.length)
342 this._tabbedPane.selectTab(dirtyTabs[0], true);
343 this._tabbedPane.closeTabs(cleanTabs, true);
344 for (var i = 0; i < dirtyTabs.length; ++i) {
345 var nextTabId = i + 1 < dirtyTabs.length ? dirtyTabs[i + 1] : null;
346 if (!this._maybeCloseTab(dirtyTabs[i], nextTabId))
347 break;
348 }
349 }
350
351 /**
352 * @param {string} tabId
353 * @param {!WebInspector.ContextMenu} contextMenu
354 */
355 _onContextMenu(tabId, contextMenu) {
356 var uiSourceCode = this._files[tabId];
357 if (uiSourceCode)
358 contextMenu.appendApplicableItems(uiSourceCode);
359 }
360
361 /**
362 * @param {!WebInspector.UISourceCode} uiSourceCode
363 */
364 addUISourceCode(uiSourceCode) {
365 var uri = uiSourceCode.url();
366 var index = this._history.index(uri);
367 if (index === -1)
368 return;
369
370 if (!this._tabIds.has(uiSourceCode))
371 this._appendFileTab(uiSourceCode, false);
372
373 // Select tab if this file was the last to be shown.
374 if (!index) {
375 this._innerShowFile(uiSourceCode, false);
376 return;
377 }
378
379 if (!this._currentFile)
380 return;
381 var currentProjectType = this._currentFile.project().type();
382 var addedProjectType = uiSourceCode.project().type();
383 var snippetsProjectType = WebInspector.projectTypes.Snippets;
384 if (this._history.index(this._currentFile.url()) && currentProjectType === s nippetsProjectType &&
385 addedProjectType !== snippetsProjectType)
386 this._innerShowFile(uiSourceCode, false);
387 }
388
389 /**
390 * @param {!WebInspector.UISourceCode} uiSourceCode
391 */
392 removeUISourceCode(uiSourceCode) {
393 this.removeUISourceCodes([uiSourceCode]);
394 }
395
396 /**
397 * @param {!Array.<!WebInspector.UISourceCode>} uiSourceCodes
398 */
399 removeUISourceCodes(uiSourceCodes) {
400 var tabIds = [];
401 for (var i = 0; i < uiSourceCodes.length; ++i) {
402 var uiSourceCode = uiSourceCodes[i];
403 var tabId = this._tabIds.get(uiSourceCode);
404 if (tabId)
405 tabIds.push(tabId);
406 }
407 this._tabbedPane.closeTabs(tabIds);
408 }
409
410 /**
411 * @param {!WebInspector.UISourceCode} uiSourceCode
412 */
413 _editorClosedByUserAction(uiSourceCode) {
414 this._history.remove(uiSourceCode.url());
415 this._updateHistory();
416 }
417
418 _editorSelectedByUserAction() {
419 this._updateHistory();
420 }
421
422 _updateHistory() {
423 var tabIds =
424 this._tabbedPane.lastOpenedTabIds(WebInspector.TabbedEditorContainer.max imalPreviouslyViewedFilesCount);
425
426 /**
427 * @param {string} tabId
428 * @this {WebInspector.TabbedEditorContainer}
429 */
430 function tabIdToURI(tabId) {
431 return this._files[tabId].url();
432 }
433
434 this._history.update(tabIds.map(tabIdToURI.bind(this)));
435 this._history.save(this._previouslyViewedFilesSetting);
436 }
437
438 /**
439 * @param {!WebInspector.UISourceCode} uiSourceCode
440 * @return {string}
441 */
442 _tooltipForFile(uiSourceCode) {
443 uiSourceCode = WebInspector.persistence.fileSystem(uiSourceCode) || uiSource Code;
444 return uiSourceCode.url();
445 }
446
447 /**
448 * @param {!WebInspector.UISourceCode} uiSourceCode
449 * @param {boolean=} userGesture
450 * @param {number=} index
451 * @return {string}
452 */
453 _appendFileTab(uiSourceCode, userGesture, index) {
454 var view = this._delegate.viewForFile(uiSourceCode);
455 var title = this._titleForFile(uiSourceCode);
456 var tooltip = this._tooltipForFile(uiSourceCode);
457
458 var tabId = this._generateTabId();
459 this._tabIds.set(uiSourceCode, tabId);
460 this._files[tabId] = uiSourceCode;
461
462 var savedSelectionRange = this._history.selectionRange(uiSourceCode.url());
463 var savedScrollLineNumber = this._history.scrollLineNumber(uiSourceCode.url( ));
464 this._restoreEditorProperties(view, savedSelectionRange, savedScrollLineNumb er);
465
466 this._tabbedPane.appendTab(tabId, title, view, tooltip, userGesture, undefin ed, index);
467
468 this._updateFileTitle(uiSourceCode);
469 this._addUISourceCodeListeners(uiSourceCode);
470 return tabId;
471 }
472
473 /**
474 * @param {!WebInspector.Widget} editorView
475 * @param {!WebInspector.TextRange=} selection
476 * @param {number=} firstLineNumber
477 */
478 _restoreEditorProperties(editorView, selection, firstLineNumber) {
479 var sourceFrame =
480 editorView instanceof WebInspector.SourceFrame ? /** @type {!WebInspecto r.SourceFrame} */ (editorView) : null;
481 if (!sourceFrame)
482 return;
483 if (selection)
484 sourceFrame.setSelection(selection);
485 if (typeof firstLineNumber === 'number')
486 sourceFrame.scrollToLine(firstLineNumber);
487 }
488
489 /**
490 * @param {!WebInspector.Event} event
491 */
492 _tabClosed(event) {
493 var tabId = /** @type {string} */ (event.data.tabId);
494 var userGesture = /** @type {boolean} */ (event.data.isUserGesture);
495
496 var uiSourceCode = this._files[tabId];
497 if (this._currentFile === uiSourceCode) {
498 this._removeViewListeners();
499 delete this._currentView;
500 delete this._currentFile;
501 }
502 this._tabIds.remove(uiSourceCode);
503 delete this._files[tabId];
504
505 this._removeUISourceCodeListeners(uiSourceCode);
506
507 this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events.Edit orClosed, uiSourceCode);
508
509 if (userGesture)
510 this._editorClosedByUserAction(uiSourceCode);
511 }
512
513 /**
514 * @param {!WebInspector.Event} event
515 */
516 _tabSelected(event) {
517 var tabId = /** @type {string} */ (event.data.tabId);
518 var userGesture = /** @type {boolean} */ (event.data.isUserGesture);
519
520 var uiSourceCode = this._files[tabId];
521 this._innerShowFile(uiSourceCode, userGesture);
522 }
523
524 /**
525 * @param {!WebInspector.UISourceCode} uiSourceCode
526 */
527 _addUISourceCodeListeners(uiSourceCode) {
528 uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._uiSourceCodeTitleChanged, this);
529 uiSourceCode.addEventListener(
530 WebInspector.UISourceCode.Events.WorkingCopyChanged, this._uiSourceCodeW orkingCopyChanged, this);
531 uiSourceCode.addEventListener(
532 WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._uiSourceCod eWorkingCopyCommitted, this);
533 }
534
535 /**
536 * @param {!WebInspector.UISourceCode} uiSourceCode
537 */
538 _removeUISourceCodeListeners(uiSourceCode) {
539 uiSourceCode.removeEventListener(
540 WebInspector.UISourceCode.Events.TitleChanged, this._uiSourceCodeTitleCh anged, this);
541 uiSourceCode.removeEventListener(
542 WebInspector.UISourceCode.Events.WorkingCopyChanged, this._uiSourceCodeW orkingCopyChanged, this);
543 uiSourceCode.removeEventListener(
544 WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._uiSourceCod eWorkingCopyCommitted, this);
545 }
546
547 /**
548 * @param {!WebInspector.UISourceCode} uiSourceCode
549 */
550 _updateFileTitle(uiSourceCode) {
551 var tabId = this._tabIds.get(uiSourceCode);
552 if (tabId) {
553 var title = this._titleForFile(uiSourceCode);
554 this._tabbedPane.changeTabTitle(tabId, title);
555 if (WebInspector.persistence.hasUnsavedCommittedChanges(uiSourceCode))
556 this._tabbedPane.setTabIcon(
557 tabId, 'warning-icon', WebInspector.UIString('Changes to this file w ere not saved to file system.'));
558 else
559 this._tabbedPane.setTabIcon(tabId, '');
560 }
561 }
562
563 _uiSourceCodeTitleChanged(event) {
564 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.target);
565 this._updateFileTitle(uiSourceCode);
566 this._updateHistory();
567 }
568
569 _uiSourceCodeWorkingCopyChanged(event) {
570 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.target);
571 this._updateFileTitle(uiSourceCode);
572 }
573
574 _uiSourceCodeWorkingCopyCommitted(event) {
575 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.target);
576 this._updateFileTitle(uiSourceCode);
577 }
578
579 /**
580 * @return {string}
581 */
582 _generateTabId() {
583 return 'tab_' + (WebInspector.TabbedEditorContainer._tabId++);
584 }
585
586 /**
587 * @return {?WebInspector.UISourceCode} uiSourceCode
588 */
589 currentFile() {
590 return this._currentFile || null;
591 }
72 }; 592 };
73 593
74 /** @enum {symbol} */ 594 /** @enum {symbol} */
75 WebInspector.TabbedEditorContainer.Events = { 595 WebInspector.TabbedEditorContainer.Events = {
76 EditorSelected: Symbol("EditorSelected"), 596 EditorSelected: Symbol('EditorSelected'),
77 EditorClosed: Symbol("EditorClosed") 597 EditorClosed: Symbol('EditorClosed')
78 }; 598 };
79 599
80 WebInspector.TabbedEditorContainer._tabId = 0; 600 WebInspector.TabbedEditorContainer._tabId = 0;
81 601
82 WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount = 30; 602 WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount = 30;
83 603
84 WebInspector.TabbedEditorContainer.prototype = {
85 /**
86 * @param {!WebInspector.Event} event
87 */
88 _onBindingCreated: function(event)
89 {
90 var binding = /** @type {!WebInspector.PersistenceBinding} */(event.data );
91 var networkTabId = this._tabIds.get(binding.network);
92 var fileSystemTabId = this._tabIds.get(binding.fileSystem);
93
94 if (networkTabId)
95 this._tabbedPane.changeTabTitle(networkTabId, this._titleForFile(bin ding.fileSystem), this._tooltipForFile(binding.fileSystem));
96 if (!fileSystemTabId)
97 return;
98
99 var wasSelectedInFileSystem = this._currentFile === binding.fileSystem;
100 var currentSelectionRange = this._history.selectionRange(binding.fileSys tem.url());
101 var currentScrollLineNumber = this._history.scrollLineNumber(binding.fil eSystem.url());
102
103 var tabIndex = this._tabbedPane.tabIndex(fileSystemTabId);
104 var tabsToClose = [fileSystemTabId];
105 if (networkTabId)
106 tabsToClose.push(networkTabId);
107 this._closeTabs(tabsToClose, true);
108 networkTabId = this._appendFileTab(binding.network, false, tabIndex);
109 this._updateHistory();
110
111 if (wasSelectedInFileSystem)
112 this._tabbedPane.selectTab(networkTabId, false);
113
114 var networkTabView = /** @type {!WebInspector.Widget} */(this._tabbedPan e.tabView(networkTabId));
115 this._restoreEditorProperties(networkTabView, currentSelectionRange, cur rentScrollLineNumber);
116 },
117
118 /**
119 * @param {!WebInspector.Event} event
120 */
121 _onBindingRemoved: function(event)
122 {
123 var binding = /** @type {!WebInspector.PersistenceBinding} */(event.data );
124 var networkTabId = this._tabIds.get(binding.network);
125 if (!networkTabId)
126 return;
127 var tabIndex = this._tabbedPane.tabIndex(networkTabId);
128 var wasSelected = this._currentFile === binding.network;
129 var fileSystemTabId = this._appendFileTab(binding.fileSystem, false, tab Index);
130 this._updateHistory();
131
132 if (wasSelected)
133 this._tabbedPane.selectTab(fileSystemTabId, false);
134
135 var fileSystemTabView = /** @type {!WebInspector.Widget} */(this._tabbed Pane.tabView(fileSystemTabId));
136 var savedSelectionRange = this._history.selectionRange(binding.network.u rl());
137 var savedScrollLineNumber = this._history.scrollLineNumber(binding.netwo rk.url());
138 this._restoreEditorProperties(fileSystemTabView, savedSelectionRange, sa vedScrollLineNumber);
139 },
140
141 /**
142 * @return {!WebInspector.Widget}
143 */
144 get view()
145 {
146 return this._tabbedPane;
147 },
148
149 /**
150 * @type {!WebInspector.Widget}
151 */
152 get visibleView()
153 {
154 return this._tabbedPane.visibleView;
155 },
156
157 /**
158 * @return {!Array.<!WebInspector.Widget>}
159 */
160 fileViews: function()
161 {
162 return /** @type {!Array.<!WebInspector.Widget>} */ (this._tabbedPane.ta bViews());
163 },
164
165 /**
166 * @return {!WebInspector.Toolbar}
167 */
168 leftToolbar: function()
169 {
170 return this._tabbedPane.leftToolbar();
171 },
172
173 /**
174 * @return {!WebInspector.Toolbar}
175 */
176 rightToolbar: function()
177 {
178 return this._tabbedPane.rightToolbar();
179 },
180
181 /**
182 * @param {!Element} parentElement
183 */
184 show: function(parentElement)
185 {
186 this._tabbedPane.show(parentElement);
187 },
188
189 /**
190 * @param {!WebInspector.UISourceCode} uiSourceCode
191 */
192 showFile: function(uiSourceCode)
193 {
194 this._innerShowFile(uiSourceCode, true);
195 },
196
197 /**
198 * @param {!WebInspector.UISourceCode} uiSourceCode
199 */
200 closeFile: function(uiSourceCode)
201 {
202 var tabId = this._tabIds.get(uiSourceCode);
203 if (!tabId)
204 return;
205 this._closeTabs([tabId]);
206 },
207
208 closeAllFiles: function()
209 {
210 this._closeTabs(this._tabbedPane.allTabs());
211 },
212
213 /**
214 * @return {!Array.<!WebInspector.UISourceCode>}
215 */
216 historyUISourceCodes: function()
217 {
218 // FIXME: there should be a way to fetch UISourceCode for its uri.
219 var uriToUISourceCode = {};
220 for (var id in this._files) {
221 var uiSourceCode = this._files[id];
222 uriToUISourceCode[uiSourceCode.url()] = uiSourceCode;
223 }
224
225 var result = [];
226 var uris = this._history._urls();
227 for (var i = 0; i < uris.length; ++i) {
228 var uiSourceCode = uriToUISourceCode[uris[i]];
229 if (uiSourceCode)
230 result.push(uiSourceCode);
231 }
232 return result;
233 },
234
235 _addViewListeners: function()
236 {
237 if (!this._currentView || !this._currentView.textEditor)
238 return;
239 this._currentView.textEditor.addEventListener(WebInspector.SourcesTextEd itor.Events.ScrollChanged, this._scrollChanged, this);
240 this._currentView.textEditor.addEventListener(WebInspector.SourcesTextEd itor.Events.SelectionChanged, this._selectionChanged, this);
241 },
242
243 _removeViewListeners: function()
244 {
245 if (!this._currentView || !this._currentView.textEditor)
246 return;
247 this._currentView.textEditor.removeEventListener(WebInspector.SourcesTex tEditor.Events.ScrollChanged, this._scrollChanged, this);
248 this._currentView.textEditor.removeEventListener(WebInspector.SourcesTex tEditor.Events.SelectionChanged, this._selectionChanged, this);
249 },
250
251 /**
252 * @param {!WebInspector.Event} event
253 */
254 _scrollChanged: function(event)
255 {
256 if (this._scrollTimer)
257 clearTimeout(this._scrollTimer);
258 var lineNumber = /** @type {number} */ (event.data);
259 this._scrollTimer = setTimeout(saveHistory.bind(this), 100);
260 this._history.updateScrollLineNumber(this._currentFile.url(), lineNumber );
261
262 /**
263 * @this {WebInspector.TabbedEditorContainer}
264 */
265 function saveHistory()
266 {
267 this._history.save(this._previouslyViewedFilesSetting);
268 }
269 },
270
271 /**
272 * @param {!WebInspector.Event} event
273 */
274 _selectionChanged: function(event)
275 {
276 var range = /** @type {!WebInspector.TextRange} */ (event.data);
277 this._history.updateSelectionRange(this._currentFile.url(), range);
278 this._history.save(this._previouslyViewedFilesSetting);
279 },
280
281 /**
282 * @param {!WebInspector.UISourceCode} uiSourceCode
283 * @param {boolean=} userGesture
284 */
285 _innerShowFile: function(uiSourceCode, userGesture)
286 {
287 var binding = WebInspector.persistence.binding(uiSourceCode);
288 uiSourceCode = binding ? binding.network : uiSourceCode;
289 if (this._currentFile === uiSourceCode)
290 return;
291
292 this._removeViewListeners();
293 this._currentFile = uiSourceCode;
294
295 var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSour ceCode, userGesture);
296
297 this._tabbedPane.selectTab(tabId, userGesture);
298 if (userGesture)
299 this._editorSelectedByUserAction();
300
301 var previousView = this._currentView;
302 this._currentView = this.visibleView;
303 this._addViewListeners();
304
305 var eventData = {
306 currentFile: this._currentFile,
307 currentView: this._currentView,
308 previousView: previousView,
309 userGesture: userGesture
310 };
311 this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events. EditorSelected, eventData);
312 },
313
314 /**
315 * @param {!WebInspector.UISourceCode} uiSourceCode
316 * @return {string}
317 */
318 _titleForFile: function(uiSourceCode)
319 {
320 var binding = WebInspector.persistence.binding(uiSourceCode);
321 var titleUISourceCode = binding ? binding.fileSystem : uiSourceCode;
322 var maxDisplayNameLength = 30;
323 var title = titleUISourceCode.displayName(true).trimMiddle(maxDisplayNam eLength);
324 if (uiSourceCode.isDirty() || WebInspector.persistence.hasUnsavedCommitt edChanges(uiSourceCode))
325 title += "*";
326 return title;
327 },
328
329 /**
330 * @param {string} id
331 * @param {string} nextTabId
332 */
333 _maybeCloseTab: function(id, nextTabId)
334 {
335 var uiSourceCode = this._files[id];
336 var shouldPrompt = uiSourceCode.isDirty() && uiSourceCode.project().canS etFileContent();
337 // FIXME: this should be replaced with common Save/Discard/Cancel dialog .
338 if (!shouldPrompt || confirm(WebInspector.UIString("Are you sure you wan t to close unsaved file: %s?", uiSourceCode.name()))) {
339 uiSourceCode.resetWorkingCopy();
340 var previousView = this._currentView;
341 if (nextTabId)
342 this._tabbedPane.selectTab(nextTabId, true);
343 this._tabbedPane.closeTab(id, true);
344 return true;
345 }
346 return false;
347 },
348
349 /**
350 * @param {!Array.<string>} ids
351 * @param {boolean=} forceCloseDirtyTabs
352 */
353 _closeTabs: function(ids, forceCloseDirtyTabs)
354 {
355 var dirtyTabs = [];
356 var cleanTabs = [];
357 for (var i = 0; i < ids.length; ++i) {
358 var id = ids[i];
359 var uiSourceCode = this._files[id];
360 if (!forceCloseDirtyTabs && uiSourceCode.isDirty())
361 dirtyTabs.push(id);
362 else
363 cleanTabs.push(id);
364 }
365 if (dirtyTabs.length)
366 this._tabbedPane.selectTab(dirtyTabs[0], true);
367 this._tabbedPane.closeTabs(cleanTabs, true);
368 for (var i = 0; i < dirtyTabs.length; ++i) {
369 var nextTabId = i + 1 < dirtyTabs.length ? dirtyTabs[i + 1] : null;
370 if (!this._maybeCloseTab(dirtyTabs[i], nextTabId))
371 break;
372 }
373 },
374
375 /**
376 * @param {string} tabId
377 * @param {!WebInspector.ContextMenu} contextMenu
378 */
379 _onContextMenu: function(tabId, contextMenu)
380 {
381 var uiSourceCode = this._files[tabId];
382 if (uiSourceCode)
383 contextMenu.appendApplicableItems(uiSourceCode);
384 },
385
386 /**
387 * @param {!WebInspector.UISourceCode} uiSourceCode
388 */
389 addUISourceCode: function(uiSourceCode)
390 {
391 var uri = uiSourceCode.url();
392 var index = this._history.index(uri);
393 if (index === -1)
394 return;
395
396 if (!this._tabIds.has(uiSourceCode))
397 this._appendFileTab(uiSourceCode, false);
398
399 // Select tab if this file was the last to be shown.
400 if (!index) {
401 this._innerShowFile(uiSourceCode, false);
402 return;
403 }
404
405 if (!this._currentFile)
406 return;
407 var currentProjectType = this._currentFile.project().type();
408 var addedProjectType = uiSourceCode.project().type();
409 var snippetsProjectType = WebInspector.projectTypes.Snippets;
410 if (this._history.index(this._currentFile.url()) && currentProjectType = == snippetsProjectType && addedProjectType !== snippetsProjectType)
411 this._innerShowFile(uiSourceCode, false);
412 },
413
414 /**
415 * @param {!WebInspector.UISourceCode} uiSourceCode
416 */
417 removeUISourceCode: function(uiSourceCode)
418 {
419 this.removeUISourceCodes([uiSourceCode]);
420 },
421
422 /**
423 * @param {!Array.<!WebInspector.UISourceCode>} uiSourceCodes
424 */
425 removeUISourceCodes: function(uiSourceCodes)
426 {
427 var tabIds = [];
428 for (var i = 0; i < uiSourceCodes.length; ++i) {
429 var uiSourceCode = uiSourceCodes[i];
430 var tabId = this._tabIds.get(uiSourceCode);
431 if (tabId)
432 tabIds.push(tabId);
433 }
434 this._tabbedPane.closeTabs(tabIds);
435 },
436
437 /**
438 * @param {!WebInspector.UISourceCode} uiSourceCode
439 */
440 _editorClosedByUserAction: function(uiSourceCode)
441 {
442 this._history.remove(uiSourceCode.url());
443 this._updateHistory();
444 },
445
446 _editorSelectedByUserAction: function()
447 {
448 this._updateHistory();
449 },
450
451 _updateHistory: function()
452 {
453 var tabIds = this._tabbedPane.lastOpenedTabIds(WebInspector.TabbedEditor Container.maximalPreviouslyViewedFilesCount);
454
455 /**
456 * @param {string} tabId
457 * @this {WebInspector.TabbedEditorContainer}
458 */
459 function tabIdToURI(tabId)
460 {
461 return this._files[tabId].url();
462 }
463
464 this._history.update(tabIds.map(tabIdToURI.bind(this)));
465 this._history.save(this._previouslyViewedFilesSetting);
466 },
467
468 /**
469 * @param {!WebInspector.UISourceCode} uiSourceCode
470 * @return {string}
471 */
472 _tooltipForFile: function(uiSourceCode)
473 {
474 uiSourceCode = WebInspector.persistence.fileSystem(uiSourceCode) || uiSo urceCode;
475 return uiSourceCode.url();
476 },
477
478 /**
479 * @param {!WebInspector.UISourceCode} uiSourceCode
480 * @param {boolean=} userGesture
481 * @param {number=} index
482 * @return {string}
483 */
484 _appendFileTab: function(uiSourceCode, userGesture, index)
485 {
486 var view = this._delegate.viewForFile(uiSourceCode);
487 var title = this._titleForFile(uiSourceCode);
488 var tooltip = this._tooltipForFile(uiSourceCode);
489
490 var tabId = this._generateTabId();
491 this._tabIds.set(uiSourceCode, tabId);
492 this._files[tabId] = uiSourceCode;
493
494 var savedSelectionRange = this._history.selectionRange(uiSourceCode.url( ));
495 var savedScrollLineNumber = this._history.scrollLineNumber(uiSourceCode. url());
496 this._restoreEditorProperties(view, savedSelectionRange, savedScrollLine Number);
497
498 this._tabbedPane.appendTab(tabId, title, view, tooltip, userGesture, und efined, index);
499
500 this._updateFileTitle(uiSourceCode);
501 this._addUISourceCodeListeners(uiSourceCode);
502 return tabId;
503 },
504
505 /**
506 * @param {!WebInspector.Widget} editorView
507 * @param {!WebInspector.TextRange=} selection
508 * @param {number=} firstLineNumber
509 */
510 _restoreEditorProperties: function(editorView, selection, firstLineNumber)
511 {
512 var sourceFrame = editorView instanceof WebInspector.SourceFrame ? /** @ type {!WebInspector.SourceFrame} */ (editorView) : null;
513 if (!sourceFrame)
514 return;
515 if (selection)
516 sourceFrame.setSelection(selection);
517 if (typeof firstLineNumber === "number")
518 sourceFrame.scrollToLine(firstLineNumber);
519 },
520
521 /**
522 * @param {!WebInspector.Event} event
523 */
524 _tabClosed: function(event)
525 {
526 var tabId = /** @type {string} */ (event.data.tabId);
527 var userGesture = /** @type {boolean} */ (event.data.isUserGesture);
528
529 var uiSourceCode = this._files[tabId];
530 if (this._currentFile === uiSourceCode) {
531 this._removeViewListeners();
532 delete this._currentView;
533 delete this._currentFile;
534 }
535 this._tabIds.remove(uiSourceCode);
536 delete this._files[tabId];
537
538 this._removeUISourceCodeListeners(uiSourceCode);
539
540 this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events. EditorClosed, uiSourceCode);
541
542 if (userGesture)
543 this._editorClosedByUserAction(uiSourceCode);
544 },
545
546 /**
547 * @param {!WebInspector.Event} event
548 */
549 _tabSelected: function(event)
550 {
551 var tabId = /** @type {string} */ (event.data.tabId);
552 var userGesture = /** @type {boolean} */ (event.data.isUserGesture);
553
554 var uiSourceCode = this._files[tabId];
555 this._innerShowFile(uiSourceCode, userGesture);
556 },
557
558 /**
559 * @param {!WebInspector.UISourceCode} uiSourceCode
560 */
561 _addUISourceCodeListeners: function(uiSourceCode)
562 {
563 uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.TitleChan ged, this._uiSourceCodeTitleChanged, this);
564 uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCo pyChanged, this._uiSourceCodeWorkingCopyChanged, this);
565 uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCo pyCommitted, this._uiSourceCodeWorkingCopyCommitted, this);
566 },
567
568 /**
569 * @param {!WebInspector.UISourceCode} uiSourceCode
570 */
571 _removeUISourceCodeListeners: function(uiSourceCode)
572 {
573 uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.TitleC hanged, this._uiSourceCodeTitleChanged, this);
574 uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.Workin gCopyChanged, this._uiSourceCodeWorkingCopyChanged, this);
575 uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.Workin gCopyCommitted, this._uiSourceCodeWorkingCopyCommitted, this);
576 },
577
578 /**
579 * @param {!WebInspector.UISourceCode} uiSourceCode
580 */
581 _updateFileTitle: function(uiSourceCode)
582 {
583 var tabId = this._tabIds.get(uiSourceCode);
584 if (tabId) {
585 var title = this._titleForFile(uiSourceCode);
586 this._tabbedPane.changeTabTitle(tabId, title);
587 if (WebInspector.persistence.hasUnsavedCommittedChanges(uiSourceCode ))
588 this._tabbedPane.setTabIcon(tabId, "warning-icon", WebInspector. UIString("Changes to this file were not saved to file system."));
589 else
590 this._tabbedPane.setTabIcon(tabId, "");
591 }
592 },
593
594 _uiSourceCodeTitleChanged: function(event)
595 {
596 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.targ et);
597 this._updateFileTitle(uiSourceCode);
598 this._updateHistory();
599 },
600
601 _uiSourceCodeWorkingCopyChanged: function(event)
602 {
603 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.targ et);
604 this._updateFileTitle(uiSourceCode);
605 },
606
607 _uiSourceCodeWorkingCopyCommitted: function(event)
608 {
609 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.targ et);
610 this._updateFileTitle(uiSourceCode);
611 },
612
613 /**
614 * @return {string}
615 */
616 _generateTabId: function()
617 {
618 return "tab_" + (WebInspector.TabbedEditorContainer._tabId++);
619 },
620
621 /**
622 * @return {?WebInspector.UISourceCode} uiSourceCode
623 */
624 currentFile: function()
625 {
626 return this._currentFile || null;
627 },
628
629 __proto__: WebInspector.Object.prototype
630 };
631
632 /** 604 /**
633 * @constructor 605 * @unrestricted
634 * @param {string} url
635 * @param {!WebInspector.TextRange=} selectionRange
636 * @param {number=} scrollLineNumber
637 */ 606 */
638 WebInspector.TabbedEditorContainer.HistoryItem = function(url, selectionRange, s crollLineNumber) 607 WebInspector.TabbedEditorContainer.HistoryItem = class {
639 { 608 /**
609 * @param {string} url
610 * @param {!WebInspector.TextRange=} selectionRange
611 * @param {number=} scrollLineNumber
612 */
613 constructor(url, selectionRange, scrollLineNumber) {
640 /** @const */ this.url = url; 614 /** @const */ this.url = url;
641 /** @const */ this._isSerializable = url.length < WebInspector.TabbedEditorC ontainer.HistoryItem.serializableUrlLengthLimit; 615 /** @const */ this._isSerializable =
616 url.length < WebInspector.TabbedEditorContainer.HistoryItem.serializable UrlLengthLimit;
642 this.selectionRange = selectionRange; 617 this.selectionRange = selectionRange;
643 this.scrollLineNumber = scrollLineNumber; 618 this.scrollLineNumber = scrollLineNumber;
619 }
620
621 /**
622 * @param {!Object} serializedHistoryItem
623 * @return {!WebInspector.TabbedEditorContainer.HistoryItem}
624 */
625 static fromObject(serializedHistoryItem) {
626 var selectionRange = serializedHistoryItem.selectionRange ?
627 WebInspector.TextRange.fromObject(serializedHistoryItem.selectionRange) :
628 undefined;
629 return new WebInspector.TabbedEditorContainer.HistoryItem(
630 serializedHistoryItem.url, selectionRange, serializedHistoryItem.scrollL ineNumber);
631 }
632
633 /**
634 * @return {?Object}
635 */
636 serializeToObject() {
637 if (!this._isSerializable)
638 return null;
639 var serializedHistoryItem = {};
640 serializedHistoryItem.url = this.url;
641 serializedHistoryItem.selectionRange = this.selectionRange;
642 serializedHistoryItem.scrollLineNumber = this.scrollLineNumber;
643 return serializedHistoryItem;
644 }
644 }; 645 };
645 646
646 WebInspector.TabbedEditorContainer.HistoryItem.serializableUrlLengthLimit = 4096 ; 647 WebInspector.TabbedEditorContainer.HistoryItem.serializableUrlLengthLimit = 4096 ;
647 648
649
648 /** 650 /**
649 * @param {!Object} serializedHistoryItem 651 * @unrestricted
650 * @return {!WebInspector.TabbedEditorContainer.HistoryItem}
651 */ 652 */
652 WebInspector.TabbedEditorContainer.HistoryItem.fromObject = function(serializedH istoryItem) 653 WebInspector.TabbedEditorContainer.History = class {
653 { 654 /**
654 var selectionRange = serializedHistoryItem.selectionRange ? WebInspector.Tex tRange.fromObject(serializedHistoryItem.selectionRange) : undefined; 655 * @param {!Array.<!WebInspector.TabbedEditorContainer.HistoryItem>} items
655 return new WebInspector.TabbedEditorContainer.HistoryItem(serializedHistoryI tem.url, selectionRange, serializedHistoryItem.scrollLineNumber); 656 */
656 }; 657 constructor(items) {
657
658 WebInspector.TabbedEditorContainer.HistoryItem.prototype = {
659 /**
660 * @return {?Object}
661 */
662 serializeToObject: function()
663 {
664 if (!this._isSerializable)
665 return null;
666 var serializedHistoryItem = {};
667 serializedHistoryItem.url = this.url;
668 serializedHistoryItem.selectionRange = this.selectionRange;
669 serializedHistoryItem.scrollLineNumber = this.scrollLineNumber;
670 return serializedHistoryItem;
671 }
672 };
673
674 /**
675 * @constructor
676 * @param {!Array.<!WebInspector.TabbedEditorContainer.HistoryItem>} items
677 */
678 WebInspector.TabbedEditorContainer.History = function(items)
679 {
680 this._items = items; 658 this._items = items;
681 this._rebuildItemIndex(); 659 this._rebuildItemIndex();
682 }; 660 }
683 661
684 /** 662 /**
685 * @param {!Array.<!Object>} serializedHistory 663 * @param {!Array.<!Object>} serializedHistory
686 * @return {!WebInspector.TabbedEditorContainer.History} 664 * @return {!WebInspector.TabbedEditorContainer.History}
687 */ 665 */
688 WebInspector.TabbedEditorContainer.History.fromObject = function(serializedHisto ry) 666 static fromObject(serializedHistory) {
689 {
690 var items = []; 667 var items = [];
691 for (var i = 0; i < serializedHistory.length; ++i) 668 for (var i = 0; i < serializedHistory.length; ++i)
692 items.push(WebInspector.TabbedEditorContainer.HistoryItem.fromObject(ser ializedHistory[i])); 669 items.push(WebInspector.TabbedEditorContainer.HistoryItem.fromObject(seria lizedHistory[i]));
693 return new WebInspector.TabbedEditorContainer.History(items); 670 return new WebInspector.TabbedEditorContainer.History(items);
671 }
672
673 /**
674 * @param {string} url
675 * @return {number}
676 */
677 index(url) {
678 return this._itemsIndex.has(url) ? /** @type {number} */ (this._itemsIndex.g et(url)) : -1;
679 }
680
681 _rebuildItemIndex() {
682 /** @type {!Map<string, number>} */
683 this._itemsIndex = new Map();
684 for (var i = 0; i < this._items.length; ++i) {
685 console.assert(!this._itemsIndex.has(this._items[i].url));
686 this._itemsIndex.set(this._items[i].url, i);
687 }
688 }
689
690 /**
691 * @param {string} url
692 * @return {!WebInspector.TextRange|undefined}
693 */
694 selectionRange(url) {
695 var index = this.index(url);
696 return index !== -1 ? this._items[index].selectionRange : undefined;
697 }
698
699 /**
700 * @param {string} url
701 * @param {!WebInspector.TextRange=} selectionRange
702 */
703 updateSelectionRange(url, selectionRange) {
704 if (!selectionRange)
705 return;
706 var index = this.index(url);
707 if (index === -1)
708 return;
709 this._items[index].selectionRange = selectionRange;
710 }
711
712 /**
713 * @param {string} url
714 * @return {number|undefined}
715 */
716 scrollLineNumber(url) {
717 var index = this.index(url);
718 return index !== -1 ? this._items[index].scrollLineNumber : undefined;
719 }
720
721 /**
722 * @param {string} url
723 * @param {number} scrollLineNumber
724 */
725 updateScrollLineNumber(url, scrollLineNumber) {
726 var index = this.index(url);
727 if (index === -1)
728 return;
729 this._items[index].scrollLineNumber = scrollLineNumber;
730 }
731
732 /**
733 * @param {!Array.<string>} urls
734 */
735 update(urls) {
736 for (var i = urls.length - 1; i >= 0; --i) {
737 var index = this.index(urls[i]);
738 var item;
739 if (index !== -1) {
740 item = this._items[index];
741 this._items.splice(index, 1);
742 } else
743 item = new WebInspector.TabbedEditorContainer.HistoryItem(urls[i]);
744 this._items.unshift(item);
745 this._rebuildItemIndex();
746 }
747 }
748
749 /**
750 * @param {string} url
751 */
752 remove(url) {
753 var index = this.index(url);
754 if (index !== -1) {
755 this._items.splice(index, 1);
756 this._rebuildItemIndex();
757 }
758 }
759
760 /**
761 * @param {!WebInspector.Setting} setting
762 */
763 save(setting) {
764 setting.set(this._serializeToObject());
765 }
766
767 /**
768 * @return {!Array.<!Object>}
769 */
770 _serializeToObject() {
771 var serializedHistory = [];
772 for (var i = 0; i < this._items.length; ++i) {
773 var serializedItem = this._items[i].serializeToObject();
774 if (serializedItem)
775 serializedHistory.push(serializedItem);
776 if (serializedHistory.length === WebInspector.TabbedEditorContainer.maxima lPreviouslyViewedFilesCount)
777 break;
778 }
779 return serializedHistory;
780 }
781
782 /**
783 * @return {!Array.<string>}
784 */
785 _urls() {
786 var result = [];
787 for (var i = 0; i < this._items.length; ++i)
788 result.push(this._items[i].url);
789 return result;
790 }
694 }; 791 };
695 792
696 WebInspector.TabbedEditorContainer.History.prototype = { 793
697 /** 794 /**
698 * @param {string} url 795 * @implements {WebInspector.TabbedPaneTabDelegate}
699 * @return {number} 796 * @unrestricted
700 */ 797 */
701 index: function(url) 798 WebInspector.EditorContainerTabDelegate = class {
702 { 799 /**
703 return this._itemsIndex.has(url) ? /** @type {number} */(this._itemsInde x.get(url)) : -1; 800 * @param {!WebInspector.TabbedEditorContainer} editorContainer
704 }, 801 */
705 802 constructor(editorContainer) {
706 _rebuildItemIndex: function() 803 this._editorContainer = editorContainer;
707 { 804 }
708 /** @type {!Map<string, number>} */ 805
709 this._itemsIndex = new Map(); 806 /**
710 for (var i = 0; i < this._items.length; ++i) { 807 * @override
711 console.assert(!this._itemsIndex.has(this._items[i].url)); 808 * @param {!WebInspector.TabbedPane} tabbedPane
712 this._itemsIndex.set(this._items[i].url, i); 809 * @param {!Array.<string>} ids
713 } 810 */
714 }, 811 closeTabs(tabbedPane, ids) {
715 812 this._editorContainer._closeTabs(ids);
716 /** 813 }
717 * @param {string} url 814
718 * @return {!WebInspector.TextRange|undefined} 815 /**
719 */ 816 * @override
720 selectionRange: function(url) 817 * @param {string} tabId
721 { 818 * @param {!WebInspector.ContextMenu} contextMenu
722 var index = this.index(url); 819 */
723 return index !== -1 ? this._items[index].selectionRange : undefined; 820 onContextMenu(tabId, contextMenu) {
724 }, 821 this._editorContainer._onContextMenu(tabId, contextMenu);
725 822 }
726 /**
727 * @param {string} url
728 * @param {!WebInspector.TextRange=} selectionRange
729 */
730 updateSelectionRange: function(url, selectionRange)
731 {
732 if (!selectionRange)
733 return;
734 var index = this.index(url);
735 if (index === -1)
736 return;
737 this._items[index].selectionRange = selectionRange;
738 },
739
740 /**
741 * @param {string} url
742 * @return {number|undefined}
743 */
744 scrollLineNumber: function(url)
745 {
746 var index = this.index(url);
747 return index !== -1 ? this._items[index].scrollLineNumber : undefined;
748 },
749
750 /**
751 * @param {string} url
752 * @param {number} scrollLineNumber
753 */
754 updateScrollLineNumber: function(url, scrollLineNumber)
755 {
756 var index = this.index(url);
757 if (index === -1)
758 return;
759 this._items[index].scrollLineNumber = scrollLineNumber;
760 },
761
762 /**
763 * @param {!Array.<string>} urls
764 */
765 update: function(urls)
766 {
767 for (var i = urls.length - 1; i >= 0; --i) {
768 var index = this.index(urls[i]);
769 var item;
770 if (index !== -1) {
771 item = this._items[index];
772 this._items.splice(index, 1);
773 } else
774 item = new WebInspector.TabbedEditorContainer.HistoryItem(urls[i ]);
775 this._items.unshift(item);
776 this._rebuildItemIndex();
777 }
778 },
779
780 /**
781 * @param {string} url
782 */
783 remove: function(url)
784 {
785 var index = this.index(url);
786 if (index !== -1) {
787 this._items.splice(index, 1);
788 this._rebuildItemIndex();
789 }
790 },
791
792 /**
793 * @param {!WebInspector.Setting} setting
794 */
795 save: function(setting)
796 {
797 setting.set(this._serializeToObject());
798 },
799
800 /**
801 * @return {!Array.<!Object>}
802 */
803 _serializeToObject: function()
804 {
805 var serializedHistory = [];
806 for (var i = 0; i < this._items.length; ++i) {
807 var serializedItem = this._items[i].serializeToObject();
808 if (serializedItem)
809 serializedHistory.push(serializedItem);
810 if (serializedHistory.length === WebInspector.TabbedEditorContainer. maximalPreviouslyViewedFilesCount)
811 break;
812 }
813 return serializedHistory;
814 },
815
816
817 /**
818 * @return {!Array.<string>}
819 */
820 _urls: function()
821 {
822 var result = [];
823 for (var i = 0; i < this._items.length; ++i)
824 result.push(this._items[i].url);
825 return result;
826 }
827 }; 823 };
828
829 /**
830 * @constructor
831 * @implements {WebInspector.TabbedPaneTabDelegate}
832 * @param {!WebInspector.TabbedEditorContainer} editorContainer
833 */
834 WebInspector.EditorContainerTabDelegate = function(editorContainer)
835 {
836 this._editorContainer = editorContainer;
837 };
838
839 WebInspector.EditorContainerTabDelegate.prototype = {
840 /**
841 * @override
842 * @param {!WebInspector.TabbedPane} tabbedPane
843 * @param {!Array.<string>} ids
844 */
845 closeTabs: function(tabbedPane, ids)
846 {
847 this._editorContainer._closeTabs(ids);
848 },
849
850 /**
851 * @override
852 * @param {string} tabId
853 * @param {!WebInspector.ContextMenu} contextMenu
854 */
855 onContextMenu: function(tabId, contextMenu)
856 {
857 this._editorContainer._onContextMenu(tabId, contextMenu);
858 }
859 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698