From 5135ffe8b138a8f35238738e2717cf7d41fb6a15 Mon Sep 17 00:00:00 2001 From: "vsevik@chromium.org" Date: Mon, 30 Jan 2012 13:10:24 +0000 Subject: [PATCH] Web Inspector: TabbedEditorContainer should save open tabs. https://bugs.webkit.org/show_bug.cgi?id=76912 Reviewed by Pavel Feldman. Source/WebCore: Test: inspector/tabbed-editors-history.html * inspector/front-end/ScriptsPanel.js: (WebInspector.ScriptsPanel.prototype._uiSourceCodeAdded): (WebInspector.ScriptsPanel.prototype._reset): (WebInspector.ScriptsPanel.prototype._showFile): (WebInspector.ScriptsPanel.prototype._updateExecutionLine): (WebInspector.ScriptsPanel.prototype._editorSelected): (WebInspector.EditorContainer.prototype.uiSourceCodeAdded): (WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype.showFile): (WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype.reset): * inspector/front-end/TabbedEditorContainer.js: (WebInspector.TabbedEditorContainer): (WebInspector.TabbedEditorContainer.prototype.showFile): (WebInspector.TabbedEditorContainer.prototype._editorClosedByUserAction): (WebInspector.TabbedEditorContainer.prototype._editorSelectedByUserAction): (WebInspector.TabbedEditorContainer.prototype._updateHistory.tabIdToURL): (WebInspector.TabbedEditorContainer.prototype._updateHistory): (WebInspector.TabbedEditorContainer.prototype._appendFileTab): (WebInspector.TabbedEditorContainer.prototype._tabClosed): (WebInspector.TabbedEditorContainer.prototype._tabSelected): (WebInspector.TabbedEditorContainer.prototype.reset): (WebInspector.TabbedEditorContainer.History): (WebInspector.TabbedEditorContainer.History.prototype.index): (WebInspector.TabbedEditorContainer.History.prototype.update): (WebInspector.TabbedEditorContainer.History.prototype.remove): (WebInspector.TabbedEditorContainer.History.prototype.save): * inspector/front-end/TabbedPane.js: (WebInspector.TabbedPane.prototype.appendTab): (WebInspector.TabbedPane.prototype.closeTab): (WebInspector.TabbedPane.prototype._innerCloseTab): (WebInspector.TabbedPane.prototype.closeAllTabs): (WebInspector.TabbedPane.prototype.lastOpenedTabIds): (WebInspector.TabbedPane.prototype._tabsSelectChanged): LayoutTests: * inspector/tabbed-editors-history-expected.txt: Added. * inspector/tabbed-editors-history.html: Added. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106238 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- LayoutTests/ChangeLog | 10 ++ .../inspector/tabbed-editors-history-expected.txt | 27 ++++ LayoutTests/inspector/tabbed-editors-history.html | 70 ++++++++++ Source/WebCore/ChangeLog | 42 ++++++ Source/WebCore/inspector/front-end/ScriptsPanel.js | 60 ++++++--- .../inspector/front-end/TabbedEditorContainer.js | 148 +++++++++++++++++++-- Source/WebCore/inspector/front-end/TabbedPane.js | 51 +++++-- 7 files changed, 368 insertions(+), 40 deletions(-) create mode 100644 LayoutTests/inspector/tabbed-editors-history-expected.txt create mode 100644 LayoutTests/inspector/tabbed-editors-history.html diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index cc7631e..ad0e8f4 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,13 @@ +2012-01-27 Vsevolod Vlasov + + Web Inspector: TabbedEditorContainer should save open tabs. + https://bugs.webkit.org/show_bug.cgi?id=76912 + + Reviewed by Pavel Feldman. + + * inspector/tabbed-editors-history-expected.txt: Added. + * inspector/tabbed-editors-history.html: Added. + 2012-01-30 Alexander Pavlov Web Inspector: [Styles] Unable to paste and subsequently edit multiple properties in the Styles pane diff --git a/LayoutTests/inspector/tabbed-editors-history-expected.txt b/LayoutTests/inspector/tabbed-editors-history-expected.txt new file mode 100644 index 0000000..7f8beee --- /dev/null +++ b/LayoutTests/inspector/tabbed-editors-history-expected.txt @@ -0,0 +1,27 @@ +Tests history saving logic in TabbedEditorContainer. + +Bug 76912 + history = [] + history = [url_1] + history = [url_2,url_1] + history = [url_3,url_2,url_1] + history = [url_2,url_3,url_1] + history = [url_1,url_2,url_3] + history = [url_11,url_1,url_2,url_3] + history = [url_12,url_11,url_1,url_2,url_3] + history = [url_13,url_12,url_11,url_1,url_2,url_3] + history = [url_12,url_13,url_11,url_1,url_2,url_3] + history = [url_11,url_12,url_13,url_1,url_2,url_3] + history = [url_12,url_13,url_1,url_2,url_3] + history = [url_12,url_1,url_2,url_3] + history = [url_14,url_12,url_1,url_2,url_3] + history = [url_15,url_14,url_12,url_1,url_2,url_3] + history = [url_16,url_15,url_14,url_12,url_1,url_2,url_3] + history = [url_15,url_14,url_12,url_1,url_2,url_3] + history = [url_14,url_12,url_1,url_2,url_3] + history = [url_12,url_1,url_2,url_3] + history = [url_1,url_2,url_3] + history = [url_2,url_3] + history = [url_3] + history = [] + diff --git a/LayoutTests/inspector/tabbed-editors-history.html b/LayoutTests/inspector/tabbed-editors-history.html new file mode 100644 index 0000000..12c421e --- /dev/null +++ b/LayoutTests/inspector/tabbed-editors-history.html @@ -0,0 +1,70 @@ + + + + + + +

Tests history saving logic in TabbedEditorContainer.

+Bug 76912 + + diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index ed053be..868cae1 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,45 @@ +2012-01-27 Vsevolod Vlasov + + Web Inspector: TabbedEditorContainer should save open tabs. + https://bugs.webkit.org/show_bug.cgi?id=76912 + + Reviewed by Pavel Feldman. + + Test: inspector/tabbed-editors-history.html + + * inspector/front-end/ScriptsPanel.js: + (WebInspector.ScriptsPanel.prototype._uiSourceCodeAdded): + (WebInspector.ScriptsPanel.prototype._reset): + (WebInspector.ScriptsPanel.prototype._showFile): + (WebInspector.ScriptsPanel.prototype._updateExecutionLine): + (WebInspector.ScriptsPanel.prototype._editorSelected): + (WebInspector.EditorContainer.prototype.uiSourceCodeAdded): + (WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype.showFile): + (WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype.reset): + * inspector/front-end/TabbedEditorContainer.js: + (WebInspector.TabbedEditorContainer): + (WebInspector.TabbedEditorContainer.prototype.showFile): + (WebInspector.TabbedEditorContainer.prototype._editorClosedByUserAction): + (WebInspector.TabbedEditorContainer.prototype._editorSelectedByUserAction): + (WebInspector.TabbedEditorContainer.prototype._updateHistory.tabIdToURL): + (WebInspector.TabbedEditorContainer.prototype._updateHistory): + (WebInspector.TabbedEditorContainer.prototype._appendFileTab): + (WebInspector.TabbedEditorContainer.prototype._tabClosed): + (WebInspector.TabbedEditorContainer.prototype._tabSelected): + (WebInspector.TabbedEditorContainer.prototype.reset): + (WebInspector.TabbedEditorContainer.History): + (WebInspector.TabbedEditorContainer.History.prototype.index): + (WebInspector.TabbedEditorContainer.History.prototype.update): + (WebInspector.TabbedEditorContainer.History.prototype.remove): + (WebInspector.TabbedEditorContainer.History.prototype.save): + * inspector/front-end/TabbedPane.js: + (WebInspector.TabbedPane.prototype.appendTab): + (WebInspector.TabbedPane.prototype.closeTab): + (WebInspector.TabbedPane.prototype._innerCloseTab): + (WebInspector.TabbedPane.prototype.closeAllTabs): + (WebInspector.TabbedPane.prototype.lastOpenedTabIds): + (WebInspector.TabbedPane.prototype._tabsSelectChanged): + 2012-01-30 Alexander Pavlov Web Inspector: [Styles] Unable to paste and subsequently edit multiple properties in the Styles pane diff --git a/Source/WebCore/inspector/front-end/ScriptsPanel.js b/Source/WebCore/inspector/front-end/ScriptsPanel.js index fe0fda9..5578643 100644 --- a/Source/WebCore/inspector/front-end/ScriptsPanel.js +++ b/Source/WebCore/inspector/front-end/ScriptsPanel.js @@ -256,18 +256,7 @@ WebInspector.ScriptsPanel.prototype = { return; } this._fileSelector.addUISourceCode(uiSourceCode); - - var lastViewedURL = WebInspector.settings.lastViewedScriptFile.get(); - if (!this._initialViewSelectionProcessed) { - this._initialViewSelectionProcessed = true; - // Option we just added is the only option in files select. - // We have to show corresponding source frame immediately. - this._showFile(uiSourceCode); - // Restore original value of lastViewedScriptFile because - // source frame was shown as a result of initial load. - WebInspector.settings.lastViewedScriptFile.set(lastViewedURL); - } else if (uiSourceCode.url === lastViewedURL) - this._showFile(uiSourceCode); + this._editorContainer.uiSourceCodeAdded(uiSourceCode); }, _uiSourceCodeRemoved: function(event) @@ -415,9 +404,7 @@ WebInspector.ScriptsPanel.prototype = { this._debuggerResumed(); - delete this._initialViewSelectionProcessed; delete this._curentUISourceCode; - this._editorContainer.reset(); this._updateScriptViewStatusBarItems(); @@ -486,7 +473,7 @@ WebInspector.ScriptsPanel.prototype = { { if (!this._fileSelector.isScriptSourceAdded(uiSourceCode)) return null; - + var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode); if (this._curentUISourceCode === uiSourceCode) return sourceFrame; @@ -496,9 +483,6 @@ WebInspector.ScriptsPanel.prototype = { this._editorContainer.showFile(uiSourceCode); this._updateScriptViewStatusBarItems(); - if (uiSourceCode.url) - WebInspector.settings.lastViewedScriptFile.set(uiSourceCode.url); - return sourceFrame; }, @@ -617,7 +601,7 @@ WebInspector.ScriptsPanel.prototype = { // Anonymous scripts are not added to files select by default. this._fileSelector.addUISourceCode(uiLocation.uiSourceCode); - + var sourceFrame = this._showFile(uiLocation.uiSourceCode); sourceFrame.setExecutionLine(uiLocation.lineNumber); this._executionSourceFrame = sourceFrame; @@ -1112,6 +1096,11 @@ WebInspector.EditorContainer.prototype = { setFileIsDirty: function(uiSourceCode, isDirty) { }, /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + uiSourceCodeAdded: function(uiSourceCode) { }, + + /** * @param {Array.} oldUISourceCodeList * @param {Array.} uiSourceCodeList */ @@ -1529,14 +1518,45 @@ WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype = { if (this._currentSourceFrame === sourceFrame) return; + this._innerShowFile(uiSourceCode, true); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean} userGesture + */ + _innerShowFile: function(uiSourceCode, userGesture) + { if (this._currentSourceFrame) this._currentSourceFrame.detach(); + this._initialViewSelectionProcessed = true; + + var sourceFrame = this._delegate.viewForFile(uiSourceCode); this._currentSourceFrame = sourceFrame; this._currentFile = uiSourceCode; + + if (userGesture) { + this._userSelectedFiles = true; + WebInspector.settings.lastViewedScriptFile.set(uiSourceCode.url); + } if (sourceFrame) sourceFrame.show(this.element); + this.dispatchEventToListeners(WebInspector.EditorContainer.Events.EditorSelected, uiSourceCode); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + uiSourceCodeAdded: function(uiSourceCode) + { + var lastViewedURL = WebInspector.settings.lastViewedScriptFile.get(); + // Show first file that was added or file with the last viewed url. + if (this._userSelectedFiles) + return; + if (uiSourceCode.url === lastViewedURL || !this._initialViewSelectionProcessed) + this._innerShowFile(uiSourceCode, false); }, /** @@ -1564,6 +1584,8 @@ WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype = { this._currentSourceFrame.detach(); this._currentSourceFrame = null; this._currentFile = null; + delete this._initialViewSelectionProcessed; + delete this._userSelectedFiles; } } diff --git a/Source/WebCore/inspector/front-end/TabbedEditorContainer.js b/Source/WebCore/inspector/front-end/TabbedEditorContainer.js index 924a9ae..14ed458 100644 --- a/Source/WebCore/inspector/front-end/TabbedEditorContainer.js +++ b/Source/WebCore/inspector/front-end/TabbedEditorContainer.js @@ -43,12 +43,18 @@ WebInspector.TabbedEditorContainer = function(delegate) this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabClosed, this._tabClosed, this); this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); - this._tabIds = new Map(); + this._tabIds = new Map(); this._files = {}; + this._loadedURLs = {}; + + this._previouslyViewedFilesSetting = WebInspector.settings.createSetting("previouslyViewedFiles", []); + this._history = new WebInspector.TabbedEditorContainer.History(this._previouslyViewedFilesSetting.get()); } WebInspector.TabbedEditorContainer._tabId = 0; +WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount = 30; + WebInspector.TabbedEditorContainer.prototype = { /** * @type {WebInspector.SourceFrame} @@ -71,12 +77,26 @@ WebInspector.TabbedEditorContainer.prototype = { */ showFile: function(uiSourceCode) { + this._innerShowFile(uiSourceCode, true); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean=} userGesture + */ + _innerShowFile: function(uiSourceCode, userGesture) + { if (this._currentFile === uiSourceCode) return; - this._currentFile = uiSourceCode; - var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode); - this._tabbedPane.selectTab(tabId); + + var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode, userGesture); + + this._tabbedPane.selectTab(tabId, userGesture); + if (userGesture) + this._editorSelectedByUserAction(); + + this.dispatchEventToListeners(WebInspector.EditorContainer.Events.EditorSelected, this._currentFile); }, /** @@ -90,6 +110,55 @@ WebInspector.TabbedEditorContainer.prototype = { /** * @param {WebInspector.UISourceCode} uiSourceCode + */ + uiSourceCodeAdded: function(uiSourceCode) + { + if (this._userSelectedFiles || this._loadedURLs[uiSourceCode.url]) + return; + this._loadedURLs[uiSourceCode.url] = true; + + var index = this._history.index(uiSourceCode.url) + if (index === -1) + return; + + var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode, false); + + // Select tab if this file was the last to be shown. + if (index === 0) + this._innerShowFile(uiSourceCode, false); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + _editorClosedByUserAction: function(uiSourceCode) + { + this._userSelectedFiles = true; + this._history.remove(uiSourceCode.url); + this._updateHistory(); + }, + + _editorSelectedByUserAction: function() + { + this._userSelectedFiles = true; + this._updateHistory(); + }, + + _updateHistory: function() + { + var tabIds = this._tabbedPane.lastOpenedTabIds(WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount); + + function tabIdToURL(tabId) + { + return this._files[tabId].url; + } + + this._history.update(tabIds.map(tabIdToURL.bind(this))); + this._history.save(this._previouslyViewedFilesSetting); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode * @return {string} */ _tooltipForFile: function(uiSourceCode) @@ -99,8 +168,9 @@ WebInspector.TabbedEditorContainer.prototype = { /** * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean=} userGesture */ - _appendFileTab: function(uiSourceCode) + _appendFileTab: function(uiSourceCode, userGesture) { var view = this._delegate.viewForFile(uiSourceCode); var title = this._titleForFile(uiSourceCode); @@ -110,7 +180,7 @@ WebInspector.TabbedEditorContainer.prototype = { this._tabIds.put(uiSourceCode, tabId); this._files[tabId] = uiSourceCode; - this._tabbedPane.appendTab(tabId, title, view, tooltip); + this._tabbedPane.appendTab(tabId, title, view, tooltip, userGesture); return tabId; }, @@ -131,12 +201,16 @@ WebInspector.TabbedEditorContainer.prototype = { _tabClosed: function(event) { var tabId = /** @type {string} */ event.data.tabId; + var userGesture = /** @type {boolean} */ event.data.isUserGesture; var uiSourceCode = this._files[tabId]; this._tabIds.remove(uiSourceCode); delete this._files[tabId]; - this.dispatchEventToListeners(WebInspector.ScriptsPanel.EditorContainer.Events.EditorClosed, uiSourceCode); + this.dispatchEventToListeners(WebInspector.EditorContainer.Events.EditorClosed, uiSourceCode); + + if (userGesture) + this._editorClosedByUserAction(uiSourceCode); }, /** @@ -145,11 +219,10 @@ WebInspector.TabbedEditorContainer.prototype = { _tabSelected: function(event) { var tabId = /** @type {string} */ event.data.tabId; + var userGesture = /** @type {boolean} */ event.data.isUserGesture; + var uiSourceCode = this._files[tabId]; - - if (this._currentFile === uiSourceCode) - return; - this.dispatchEventToListeners(WebInspector.EditorContainer.Events.EditorSelected, uiSourceCode); + this._innerShowFile(uiSourceCode, userGesture); }, /** @@ -217,6 +290,8 @@ WebInspector.TabbedEditorContainer.prototype = { this._tabIds = new Map(); this._files = {}; delete this._currentFile; + delete this._userSelectedFiles; + this._loadedURLs = {}; }, /** @@ -229,3 +304,54 @@ WebInspector.TabbedEditorContainer.prototype = { } WebInspector.TabbedEditorContainer.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + */ +WebInspector.TabbedEditorContainer.History = function(urls) +{ + this._urls = urls; +} + +WebInspector.TabbedEditorContainer.History.prototype = { + /** + * @param {string} url + */ + index: function(url) + { + return this._urls.indexOf(url); + }, + + /** + * @param {Array.} urls + */ + update: function(urls) + { + for (var i = urls.length - 1; i >= 0; --i) { + var index = this._urls.indexOf(urls[i]); + if (index !== -1) + this._urls.splice(index, 1); + this._urls.unshift(urls[i]); + } + }, + + /** + * @param {string} url + */ + remove: function(url) + { + var index = this._urls.indexOf(url); + if (index !== -1) + this._urls.splice(index, 1); + }, + + /** + * @param {WebInspector.Setting} setting + */ + save: function(setting) + { + setting.set(this._urls); + } +} + +WebInspector.TabbedEditorContainer.History.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/Source/WebCore/inspector/front-end/TabbedPane.js b/Source/WebCore/inspector/front-end/TabbedPane.js index 62e18a0..4b24e88 100644 --- a/Source/WebCore/inspector/front-end/TabbedPane.js +++ b/Source/WebCore/inspector/front-end/TabbedPane.js @@ -91,14 +91,19 @@ WebInspector.TabbedPane.prototype = { * @param {string} tabTitle * @param {WebInspector.View} view * @param {string=} tabTooltip + * @param {boolean=} userGesture */ - appendTab: function(id, tabTitle, view, tabTooltip) + appendTab: function(id, tabTitle, view, tabTooltip, userGesture) { var tab = new WebInspector.TabbedPaneTab(this, this._tabsElement, id, tabTitle, this._closeableTabs, view, tabTooltip); + this._tabsById[id] = tab; this._tabs.push(tab); - this._tabsById[id] = tab; this._tabsHistory.push(tab); + + if (this._tabsHistory[0] === tab) + this.selectTab(tab.id, userGesture); + this._updateTabElements(); }, @@ -108,6 +113,20 @@ WebInspector.TabbedPane.prototype = { */ closeTab: function(id, userGesture) { + this._innerCloseTab(id, userGesture); + + if (this._tabsHistory.length) + this.selectTab(this._tabsHistory[0].id, userGesture); + else + this._updateTabElements(); + }, + + /** + * @param {string} id + * @param {boolean=} userGesture + */ + _innerCloseTab: function(id, userGesture) + { if (this._currentTab && this._currentTab.id === id) this._hideCurrentTab(); @@ -119,21 +138,20 @@ WebInspector.TabbedPane.prototype = { if (tab.shown) this._hideTabElement(tab); - if (this._tabsHistory.length) - this.selectTab(this._tabsHistory[0].id); - else - this._updateTabElements(); - var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture }; this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabClosed, eventData); return true; }, - closeAllTabs: function() + /** + * @param {boolean=} userGesture + */ + closeAllTabs: function(userGesture) { var tabs = this._tabs.slice(); for (var i = 0; i < tabs.length; ++i) - this.closeTab(tabs[i].id, false); + this._innerCloseTab(tabs[i].id, userGesture); + this._updateTabElements(); }, /** @@ -163,6 +181,19 @@ WebInspector.TabbedPane.prototype = { }, /** + * @param {number} tabsCount + * @return {Array.} + */ + lastOpenedTabIds: function(tabsCount) + { + function tabToTabId(tab) { + return tab.id; + } + + return this._tabsHistory.slice(0, tabsCount).map(tabToTabId); + }, + + /** * @param {string} id * @param {string} tabTitle */ @@ -296,7 +327,7 @@ WebInspector.TabbedPane.prototype = { { var options = this._tabsSelect.options; var selectedOption = options[this._tabsSelect.selectedIndex]; - this.selectTab(selectedOption.tab.id); + this.selectTab(selectedOption.tab.id, true); }, _measureDropDownButton: function() -- 2.7.4