diff options
author | Marius Ungureanu <teromario@yahoo.com> | 2013-05-14 22:43:43 +0400 |
---|---|---|
committer | Marius Ungureanu <teromario@yahoo.com> | 2013-05-14 22:43:43 +0400 |
commit | 267efbe568d3ae443fe973a72c3bbbc56f2d9b78 (patch) | |
tree | d2325ba14de01d80bfc2bbae742a858f166e46ea /main/src | |
parent | 8105f814d863b0efa927b4e86490eff98fc9ce86 (diff) |
Bug 8541 - Reopen Closed Tab
This adds a feature Open Last Closed Tab similar to Google Chrome.
This acts like a backwards linked-list which opens documents in the order of closing.
ClosedDocumentNavigationPoint is a type specifically for this action.
This required an enhancement to the NavigationHistoryService to support this new kind of items.
*Should I have split this to a new service?
The need of the ReorderTab to fix visual appearance of tabs when reopening.
Diffstat (limited to 'main/src')
11 files changed, 183 insertions, 14 deletions
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml index 504dd574d3..55da868003 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml @@ -489,6 +489,10 @@ <Command id = "MonoDevelop.Ide.Commands.FileTabCommands.ToggleMaximize" defaultHandler = "MonoDevelop.Ide.Commands.ToggleMaximizeHandler" _label = "S_witch maximize/normal view"/> + <Command id ="MonoDevelop.Ide.Commands.FileTabCommands.ReopenClosedTab" + defaultHandler = "MonoDevelop.Ide.Commands.ReopenClosedTabHandler" + _label = "Reopen Closed Tab" + _description = "Opens the last tab that has been closed"/> </Category> <!-- ViewCommands --> diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml index cea94a1393..1299673c0e 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml @@ -255,6 +255,7 @@ <CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.CloseFile" /> <CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.CloseAllFiles" /> <CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.CloseAllButThis" /> + <CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.ReopenClosedTab" /> <SeparatorItem id = "CloseSeparator" /> <CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.Save" /> <CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.SaveAll" /> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs index 360b044631..e3f28cea05 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs @@ -403,4 +403,5 @@ namespace MonoDevelop.Ide.Commands // MonoDevelop.Ide.Commands.FileTabCommands.CloseAllButThis Implemented in FileTabCommands.cs // MonoDevelop.Ide.Commands.CopyPathNameHandler Implemented in FileTabCommands.cs // MonoDevelop.Ide.Commands.FileTabCommands.ToggleMaximize Implemented in FileTabCommands.cs + // MonoDevelop.Ide.Commands.FileTabCommands.ReopenClosedTab Implemented in FileTabCommands.cs } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs index 87b46c16e8..97347d6e47 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs @@ -32,6 +32,7 @@ using Gtk; using MonoDevelop.Components.Commands; using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Navigation; namespace MonoDevelop.Ide.Commands { @@ -39,7 +40,8 @@ namespace MonoDevelop.Ide.Commands { CloseAllButThis, CopyPathName, - ToggleMaximize + ToggleMaximize, + OpenLastTab } class CloseAllButThisHandler : CommandHandler @@ -72,4 +74,17 @@ namespace MonoDevelop.Ide.Commands clipboard.Text = document.FileName; } } + + class ReopenClosedTabHandler : CommandHandler + { + protected override void Run () + { + NavigationHistoryService.OpenLastClosedDocument (); + } + + protected override void Update (CommandInfo info) + { + info.Enabled = NavigationHistoryService.HasClosedDocuments; + } + } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs index d66275049c..dad5bd3e7d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs @@ -1187,7 +1187,14 @@ namespace MonoDevelop.Ide.Gui ignorePageSwitch = false; } } - + + internal void ReorderTab (int oldPlacement, int newPlacement) + { + DockNotebookTab tab = (DockNotebookTab)tabControl.GetTab (oldPlacement); + DockNotebookTab targetTab = (DockNotebookTab)tabControl.GetTab (newPlacement); + tabControl.ReorderTab (tab, targetTab); + } + #endregion #region Dock Item management diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockNotebook.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockNotebook.cs index 5adc5d9115..f58f57b9e5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockNotebook.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DockNotebook.cs @@ -233,12 +233,12 @@ namespace MonoDevelop.Ide.Gui PageRemoved (this, EventArgs.Empty);
}
- internal void ReorderTab (DockNotebookTab tab, DockNotebookTab targetTabPosition)
+ internal void ReorderTab (DockNotebookTab tab, DockNotebookTab targetTab)
{
- if (tab == targetTabPosition)
+ if (tab == targetTab)
return;
- int targetPos = targetTabPosition.Index;
- if (tab.Index > targetTabPosition.Index) {
+ int targetPos = targetTab.Index;
+ if (tab.Index > targetTab.Index) {
pages.RemoveAt (tab.Index);
pages.Insert (targetPos, tab);
} else {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs index 1593bd0fb0..b9c48161af 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs @@ -970,13 +970,18 @@ namespace MonoDevelop.Ide.Gui return pad; return null; } - + + public void ReorderTab (int oldPlacement, int newPlacement) + { + workbench.ReorderTab (oldPlacement, newPlacement); + } + internal void ReorderDocuments (int oldPlacement, int newPlacement) { IViewContent content = workbench.InternalViewContentCollection[oldPlacement]; workbench.InternalViewContentCollection.RemoveAt (oldPlacement); workbench.InternalViewContentCollection.Insert (newPlacement, content); - + Document doc = documents [oldPlacement]; documents.RemoveAt (oldPlacement); documents.Insert (newPlacement, doc); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/ClosedDocumentNavigationPoint.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/ClosedDocumentNavigationPoint.cs new file mode 100644 index 0000000000..0a99edd4e4 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/ClosedDocumentNavigationPoint.cs @@ -0,0 +1,95 @@ +//
+// ClosedDocumentNavigationPoint.cs
+//
+// Author:
+// Therzok <therzok@gmail.com>
+//
+// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using MonoDevelop.Core;
+using MonoDevelop.Ide.Gui;
+
+namespace MonoDevelop.Ide.Navigation
+{
+ public class ClosedDocumentNavigationPoint : NavigationPoint
+ {
+ FilePath fileName;
+ int position;
+
+ public ClosedDocumentNavigationPoint (FilePath fileName, int position)
+ {
+ this.fileName = fileName;
+ this.position = position;
+ }
+
+ public override void Dispose ()
+ {
+ if (fileName != null) {
+ fileName = null;
+ }
+ base.Dispose ();
+ }
+
+ FilePath FileName {
+ get { return fileName; }
+ }
+
+ public override void Show ()
+ {
+ DoShow ();
+ Dispose ();
+ }
+
+ protected virtual Document DoShow ()
+ {
+ Document doc = IdeApp.Workbench.OpenDocument (fileName, true);
+ IdeApp.Workbench.ReorderTab (IdeApp.Workbench.Documents.IndexOf (doc), position);
+ return doc;
+ }
+
+ public override string DisplayName {
+ get {
+ return System.IO.Path.GetFileName ((string) fileName);
+ }
+ }
+
+ public override bool Equals (object o)
+ {
+ ClosedDocumentNavigationPoint dp = o as ClosedDocumentNavigationPoint;
+ return dp != null && ((FileName != FilePath.Null && FileName == dp.FileName));
+ }
+
+ public override int GetHashCode ()
+ {
+ return (FileName != FilePath.Null ? FileName.GetHashCode () : 0);
+ }
+
+ internal bool HandleRenameEvent (string oldName, string newName)
+ {
+ if (oldName == fileName) {
+ fileName = newName;
+ return true;
+ }
+ return false;
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryItem.cs index 7a1955a045..a9f855ec6b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryItem.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryItem.cs @@ -55,8 +55,10 @@ namespace MonoDevelop.Ide.Navigation public void Show () { - if (!NavigationHistoryService.IsCurrent (this)) - NavigationHistoryService.MoveTo (this); + if (NavigationPoint is DocumentNavigationPoint) { + if (!NavigationHistoryService.IsCurrent (this)) + NavigationHistoryService.MoveTo (this); + } NavigationPoint.Show (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs index 6b85e8cecc..9dbdeaa0c0 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs @@ -40,6 +40,7 @@ namespace MonoDevelop.Ide.Navigation public static class NavigationHistoryService { static HistoryList history = new HistoryList (); + static HistoryList closedHistory = new HistoryList (); //used to prevent re-logging the current point during a switch static bool switching; @@ -59,7 +60,16 @@ namespace MonoDevelop.Ide.Navigation history.Clear (); OnHistoryChanged (); }; - + + IdeApp.Workbench.DocumentClosed += delegate(object sender, DocumentEventArgs e) { + ClosedDocumentNavigationPoint point = new ClosedDocumentNavigationPoint ( + e.Document.FileName, IdeApp.Workbench.Documents.IndexOf (IdeApp.Workbench.ActiveDocument) + ); + NavigationHistoryItem item = new NavigationHistoryItem (point); + closedHistory.AddPoint (item); + OnClosedHistoryChanged (); + }; + //keep nav points up to date TextEditorService.LineCountChanged += LineCountChanged; TextEditorService.LineCountChangesCommitted += CommitCountChanges; @@ -202,6 +212,20 @@ namespace MonoDevelop.Ide.Navigation } #endregion + + #region Closed Document List + + public static bool HasClosedDocuments { + get { return closedHistory.Current != null; } + } + + public static void OpenLastClosedDocument () { + if (closedHistory.Current != null) { + closedHistory.Current.Show (); + } + } + + #endregion public static IList<NavigationHistoryItem> GetNavigationList (int desiredLength) { @@ -227,12 +251,19 @@ namespace MonoDevelop.Ide.Navigation } public static event EventHandler HistoryChanged; + public static event EventHandler ClosedHistoryChanged; static void OnHistoryChanged () { if (HistoryChanged != null) HistoryChanged (null, EventArgs.Empty); } + + static void OnClosedHistoryChanged () + { + if (ClosedHistoryChanged != null) + ClosedHistoryChanged (null, EventArgs.Empty); + } #region Handling active doc change events @@ -307,15 +338,22 @@ namespace MonoDevelop.Ide.Navigation static void FileRenamed (object sender, ProjectFileRenamedEventArgs e) { - bool changed = false; + bool historyChanged = false; + bool closedHistoryChanged = false; foreach (ProjectFileRenamedEventInfo args in e) { foreach (NavigationHistoryItem point in history) { DocumentNavigationPoint dp = point.NavigationPoint as DocumentNavigationPoint; - changed &= (dp != null && dp.HandleRenameEvent (args.OldName, args.NewName)); + historyChanged &= (dp != null && dp.HandleRenameEvent (args.OldName, args.NewName)); + } + foreach (NavigationHistoryItem point in history) { + ClosedDocumentNavigationPoint cdp = point.NavigationPoint as ClosedDocumentNavigationPoint; + closedHistoryChanged &= (cdp != null && cdp.HandleRenameEvent (args.OldName, args.NewName)); } } - if (changed) + if (historyChanged) OnHistoryChanged (); + if (closedHistoryChanged) + OnClosedHistoryChanged (); } #endregion diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj index 9d3e997971..dd5fa2ae67 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj @@ -1854,6 +1854,7 @@ <Compile Include="MonoDevelop.Components.MainToolbar\MainStatusBarContextImpl.cs" /> <Compile Include="MonoDevelop.Ide.TypeSystem\MonoDevelopProjectContent.cs" /> <Compile Include="MonoDevelop.Components.Commands\ICommandDelegator.cs" /> + <Compile Include="MonoDevelop.Ide.Navigation\ClosedDocumentNavigationPoint.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> |