|
|
|
@ -19,41 +19,41 @@ namespace ICSharpCode.Core
@@ -19,41 +19,41 @@ namespace ICSharpCode.Core
|
|
|
|
|
/// Provides the infrastructure to handle generalized code navigation.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// <para>This service is not limited to navigating code; rather, it
|
|
|
|
|
/// integrates with SharpDevelop's extendable <see cref="IViewContent"/>
|
|
|
|
|
/// interface so that each window has the opportunity to implement a
|
|
|
|
|
/// <para>This service is not limited to navigating code; rather, it
|
|
|
|
|
/// integrates with SharpDevelop's extendable <see cref="IViewContent"/>
|
|
|
|
|
/// interface so that each window has the opportunity to implement a
|
|
|
|
|
/// contextually appropriate navigation scheme.</para>
|
|
|
|
|
/// <para>The default scheme, <see cref="DefaultNavigationPoint"/>, is
|
|
|
|
|
/// created automatically in the <see cref="AbstractViewContent"/>
|
|
|
|
|
/// implementation. This scheme supports the basic function of logging a
|
|
|
|
|
/// <para>The default scheme, <see cref="DefaultNavigationPoint"/>, is
|
|
|
|
|
/// created automatically in the <see cref="AbstractViewContent"/>
|
|
|
|
|
/// implementation. This scheme supports the basic function of logging a
|
|
|
|
|
/// filename and returning to that file's default view.</para>
|
|
|
|
|
/// <para>The default text editor provides a slightly more sophisticated
|
|
|
|
|
/// <para>The default text editor provides a slightly more sophisticated
|
|
|
|
|
/// scheme, <see cref="ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.TextEditorNavigationPoint">
|
|
|
|
|
/// TextEditorNavigationPoint</see>, that logs filename and line number.</para>
|
|
|
|
|
/// <para>To implement your own navigation scheme, implement
|
|
|
|
|
/// <see cref="IViewContent"/> or derive from
|
|
|
|
|
/// <see cref="AbstractViewContent"/> and override the
|
|
|
|
|
/// <see cref="IViewContent.BuildNavigationPoint">BuildNavigationPoint</see>
|
|
|
|
|
/// <para>To implement your own navigation scheme, implement
|
|
|
|
|
/// <see cref="IViewContent"/> or derive from
|
|
|
|
|
/// <see cref="AbstractViewContent"/> and override the
|
|
|
|
|
/// <see cref="IViewContent.BuildNavigationPoint">BuildNavigationPoint</see>
|
|
|
|
|
/// method.</para>
|
|
|
|
|
/// <para>
|
|
|
|
|
/// <i>History logic based in part on Orlando Curioso's <i>Code Project</i> article:
|
|
|
|
|
/// <see href="http://www.codeproject.com/cs/miscctrl/WinFormsHistory.asp">
|
|
|
|
|
/// Navigational history (go back/forward) for WinForms controls</see></i>
|
|
|
|
|
/// </para>
|
|
|
|
|
/// </para>
|
|
|
|
|
/// </remarks>
|
|
|
|
|
public class NavigationService |
|
|
|
|
{ |
|
|
|
|
#region Private members
|
|
|
|
|
static LinkedList<INavigationPoint> history; |
|
|
|
|
static LinkedListNode<INavigationPoint> currentNode; |
|
|
|
|
static bool loggingSuspended; |
|
|
|
|
static LinkedList<INavigationPoint> history = new LinkedList<INavigationPoint>(); |
|
|
|
|
static LinkedListNode<INavigationPoint> currentNode; // autoinitialized to null (FxCop)
|
|
|
|
|
static bool loggingSuspended; // autoinitialized to false (FxCop)
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
static NavigationService() |
|
|
|
|
{ |
|
|
|
|
history = new LinkedList<INavigationPoint>(); |
|
|
|
|
currentNode = null; |
|
|
|
|
loggingSuspended = false; |
|
|
|
|
// history = new LinkedList<INavigationPoint>();
|
|
|
|
|
// currentNode = null;
|
|
|
|
|
// loggingSuspended = false;
|
|
|
|
|
|
|
|
|
|
WorkbenchSingleton.WorkbenchCreated += WorkbenchCreatedHandler; |
|
|
|
|
FileService.FileRenamed += FileService_FileRenamed; |
|
|
|
@ -86,7 +86,8 @@ namespace ICSharpCode.Core
@@ -86,7 +86,8 @@ namespace ICSharpCode.Core
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: FxCop says "find another way to do this" (ReviewVisibleEventHandlers)
|
|
|
|
|
public static void ContentChanging(object sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
foreach (INavigationPoint p in history) |
|
|
|
@ -110,12 +111,12 @@ namespace ICSharpCode.Core
@@ -110,12 +111,12 @@ namespace ICSharpCode.Core
|
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public static void Log(INavigationPoint p) |
|
|
|
|
public static void Log(INavigationPoint pointToLog) |
|
|
|
|
{ |
|
|
|
|
if (loggingSuspended) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
LogInternal(p); |
|
|
|
|
LogInternal(pointToLog); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// refactoring this out of Log() allows the NavigationService
|
|
|
|
@ -124,7 +125,7 @@ namespace ICSharpCode.Core
@@ -124,7 +125,7 @@ namespace ICSharpCode.Core
|
|
|
|
|
private static void LogInternal(INavigationPoint p) |
|
|
|
|
{ |
|
|
|
|
if (p == null |
|
|
|
|
|| p.FileName==null) { // HACK: why/how do we get here?
|
|
|
|
|
|| p.FileName==null) { // HACK: why/how do we get here?
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (currentNode==null) { |
|
|
|
@ -155,9 +156,11 @@ namespace ICSharpCode.Core
@@ -155,9 +156,11 @@ namespace ICSharpCode.Core
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static List<INavigationPoint> GetListOfPoints() |
|
|
|
|
public static ICollection<INavigationPoint> Points |
|
|
|
|
{ |
|
|
|
|
return new List<INavigationPoint>(history); |
|
|
|
|
get { |
|
|
|
|
return new List<INavigationPoint>(history); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static void ClearHistory() |
|
|
|
@ -176,21 +179,21 @@ namespace ICSharpCode.Core
@@ -176,21 +179,21 @@ namespace ICSharpCode.Core
|
|
|
|
|
OnHistoryChanged(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static void Go(int n) |
|
|
|
|
public static void Go(int delta) |
|
|
|
|
{ |
|
|
|
|
if (0 == n) { |
|
|
|
|
if (0 == delta) { |
|
|
|
|
return; |
|
|
|
|
} else if (0>n) { |
|
|
|
|
} else if (0>delta) { |
|
|
|
|
// move backwards
|
|
|
|
|
while (0>n && currentNode!=history.First) { |
|
|
|
|
while (0>delta && currentNode!=history.First) { |
|
|
|
|
currentNode = currentNode.Previous; |
|
|
|
|
n++; |
|
|
|
|
delta++; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// move forwards
|
|
|
|
|
while (0<n && currentNode!=history.Last) { |
|
|
|
|
while (0<delta && currentNode!=history.Last) { |
|
|
|
|
currentNode = currentNode.Next; |
|
|
|
|
n--; |
|
|
|
|
delta--; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -220,7 +223,7 @@ namespace ICSharpCode.Core
@@ -220,7 +223,7 @@ namespace ICSharpCode.Core
|
|
|
|
|
{ |
|
|
|
|
//LoggingService.Info("suspend logging");
|
|
|
|
|
SuspendLogging(); |
|
|
|
|
if (CurrentPosition!=null) { |
|
|
|
|
if (CurrentPosition!=null) { |
|
|
|
|
CurrentPosition.JumpTo(); |
|
|
|
|
} |
|
|
|
|
//LoggingService.Info("resume logging");
|
|
|
|
@ -241,14 +244,14 @@ namespace ICSharpCode.Core
@@ -241,14 +244,14 @@ namespace ICSharpCode.Core
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
// the following code is not covered by Unit tests as i wasn't sure
|
|
|
|
|
// the following code is not covered by Unit tests as i wasn't sure
|
|
|
|
|
// how to test code triggered by the user interacting with the workbench
|
|
|
|
|
#region event trapping
|
|
|
|
|
|
|
|
|
|
#region ViewContent events
|
|
|
|
|
public static void WorkbenchCreatedHandler(object sender, EventArgs e) |
|
|
|
|
static void WorkbenchCreatedHandler(object sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
WorkbenchSingleton.Workbench.ViewOpened += |
|
|
|
|
WorkbenchSingleton.Workbench.ViewOpened += |
|
|
|
|
new ViewContentEventHandler(ViewContentOpened); |
|
|
|
|
WorkbenchSingleton.Workbench.ViewClosed += |
|
|
|
|
new ViewContentEventHandler(ViewContentClosed); |
|
|
|
@ -265,7 +268,7 @@ namespace ICSharpCode.Core
@@ -265,7 +268,7 @@ namespace ICSharpCode.Core
|
|
|
|
|
e.Content.WorkbenchWindow.WindowSelected -= WorkBenchWindowSelected; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static IWorkbenchWindow lastSelectedWindow = null; |
|
|
|
|
static IWorkbenchWindow lastSelectedWindow; // = null; (FXCop)
|
|
|
|
|
static void WorkBenchWindowSelected(object sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
try { |
|
|
|
@ -273,18 +276,19 @@ namespace ICSharpCode.Core
@@ -273,18 +276,19 @@ namespace ICSharpCode.Core
|
|
|
|
|
if (window == lastSelectedWindow) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
int n = NavigationService.Count; |
|
|
|
|
//int n = NavigationService.Count;
|
|
|
|
|
Log(window); |
|
|
|
|
//LoggingService.DebugFormatted("WorkbenchSelected: logging {0}", window.Title);
|
|
|
|
|
|
|
|
|
|
// HACK: Navigation - for some reason, JumpToFilePosition returns _before_ this
|
|
|
|
|
// gets fired, (not the behaviour i expected) so we need to remember the
|
|
|
|
|
// previous selected window to ensure that we only log once per visit to
|
|
|
|
|
// HACK: Navigation - for some reason, JumpToFilePosition returns _before_ this
|
|
|
|
|
// gets fired, (not the behaviour i expected) so we need to remember the
|
|
|
|
|
// previous selected window to ensure that we only log once per visit to
|
|
|
|
|
// a given window.
|
|
|
|
|
lastSelectedWindow = window; |
|
|
|
|
|
|
|
|
|
} catch (Exception ex) { |
|
|
|
|
LoggingService.ErrorFormatted("{0}:\n{1}",ex.Message, ex.StackTrace); |
|
|
|
|
throw; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
@ -304,7 +308,7 @@ namespace ICSharpCode.Core
@@ -304,7 +308,7 @@ namespace ICSharpCode.Core
|
|
|
|
|
#region Public Events
|
|
|
|
|
public static event System.EventHandler HistoryChanged; |
|
|
|
|
|
|
|
|
|
public static void OnHistoryChanged() |
|
|
|
|
static void OnHistoryChanged() |
|
|
|
|
{ |
|
|
|
|
if (HistoryChanged!=null) { |
|
|
|
|
HistoryChanged(NavigationService.CurrentPosition, EventArgs.Empty); |
|
|
|
|