| OLD | NEW |
| 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 }; | |
| OLD | NEW |