diff --git a/data/resources/StringResources.resx b/data/resources/StringResources.resx index c74f7076e5..eacd6cda13 100644 --- a/data/resources/StringResources.resx +++ b/data/resources/StringResources.resx @@ -5862,6 +5862,9 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFxCompiler, WixNetFxExtension< Remove watch + + Do you want to stop debugging? + Definition View diff --git a/src/Main/Base/Project/Src/Commands/FileMenuCommands.cs b/src/Main/Base/Project/Src/Commands/FileMenuCommands.cs index f5e0bb27d3..17737ec7da 100644 --- a/src/Main/Base/Project/Src/Commands/FileMenuCommands.cs +++ b/src/Main/Base/Project/Src/Commands/FileMenuCommands.cs @@ -39,9 +39,11 @@ namespace ICSharpCode.SharpDevelop.Project.Commands { public override void Run() { - ProjectService.SaveSolutionPreferences(); - if (WorkbenchSingleton.Workbench.CloseAllSolutionViews()) { - ProjectService.CloseSolution(); + if (!ProjectService.IsClosingCanceled()) { + ProjectService.SaveSolutionPreferences(); + if (WorkbenchSingleton.Workbench.CloseAllSolutionViews()) { + ProjectService.CloseSolution(); + } } } } diff --git a/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs b/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs index 6207ba9ce0..fec29a1026 100644 --- a/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs +++ b/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs @@ -573,25 +573,30 @@ namespace ICSharpCode.SharpDevelop.Gui return; } - Project.ProjectService.SaveSolutionPreferences(); - - while (WorkbenchSingleton.Workbench.WorkbenchWindowCollection.Count > 0) { - IWorkbenchWindow window = WorkbenchSingleton.Workbench.WorkbenchWindowCollection[0]; - if (!window.CloseWindow(false)) { - e.Cancel = true; - return; + if (!Project.ProjectService.IsClosingCanceled()) { + // save preferences + Project.ProjectService.SaveSolutionPreferences(); + + while (WorkbenchSingleton.Workbench.WorkbenchWindowCollection.Count > 0) { + IWorkbenchWindow window = WorkbenchSingleton.Workbench.WorkbenchWindowCollection[0]; + if (!window.CloseWindow(false)) { + e.Cancel = true; + return; + } } - } - - Project.ProjectService.CloseSolution(); - ParserService.StopParserThread(); - - restoreBoundsBeforeClosing = this.RestoreBounds; - - this.WorkbenchLayout = null; - - foreach (PadDescriptor padDescriptor in this.PadContentCollection) { - padDescriptor.Dispose(); + + Project.ProjectService.CloseSolution(); + ParserService.StopParserThread(); + + restoreBoundsBeforeClosing = this.RestoreBounds; + + this.WorkbenchLayout = null; + + foreach (PadDescriptor padDescriptor in this.PadContentCollection) { + padDescriptor.Dispose(); + } + } else { + e.Cancel = true; } } } diff --git a/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs b/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs index 8c6c9d95aa..98bad4e52f 100644 --- a/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs +++ b/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs @@ -114,14 +114,16 @@ namespace ICSharpCode.SharpDevelop.Gui /// public static void OnWorkbenchUnloaded() { - Project.ProjectService.CloseSolution(); - NavigationService.Unload(); - - ApplicationStateInfoService.UnregisterStateGetter(activeContentState); - - WorkbenchUnloaded(null, EventArgs.Empty); - - FileService.Unload(); + if (!Project.ProjectService.IsClosingCanceled()) { + Project.ProjectService.CloseSolution(); + NavigationService.Unload(); + + ApplicationStateInfoService.UnregisterStateGetter(activeContentState); + + WorkbenchUnloaded(null, EventArgs.Empty); + + FileService.Unload(); + } } #region Safe Thread Caller diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs index 55c60abe1d..e621d60987 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs @@ -28,6 +28,8 @@ namespace ICSharpCode.SharpDevelop.Debugging ClearDebugMessages(); }; + ProjectService.BeforeSolutionClosing += OnBeforeSolutionClosing; + BookmarkManager.Added += BookmarkAdded; BookmarkManager.Removed += BookmarkRemoved; } @@ -222,6 +224,29 @@ namespace ICSharpCode.SharpDevelop.Debugging } } + static void OnBeforeSolutionClosing(object sender, SolutionCancelEventArgs e) + { + if (currentDebugger == null) + return; + + if (currentDebugger.IsDebugging) { + string caption = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Stop}"); + string message = StringParser.Parse("${res:MainWindow.Windows.Debug.StopDebugging.Message}"); + string[] buttonLabels = new string[] { StringParser.Parse("${res:Global.Yes}"), StringParser.Parse("${res:Global.No}") }; + int result = MessageService.ShowCustomDialog(caption, + message, + 0, // yes + 1, // no + buttonLabels); + + if (result == 0) { + currentDebugger.Stop(); + } else { + e.Cancel = true; + } + } + } + public static void ToggleBreakpointAt(ITextEditor editor, int lineNumber) { BookmarkManager.ToggleBookmark( diff --git a/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs b/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs index b0c378655b..b506a6eb1d 100644 --- a/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs +++ b/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs @@ -242,7 +242,7 @@ namespace ICSharpCode.SharpDevelop.Project static void BeforeLoadSolution() { - if (openSolution != null) { + if (openSolution != null && !IsClosingCanceled()) { SaveSolutionPreferences(); WorkbenchSingleton.Workbench.CloseAllViews(); CloseSolution(); @@ -258,6 +258,10 @@ namespace ICSharpCode.SharpDevelop.Project { if (!Path.IsPathRooted(fileName)) throw new ArgumentException("Path must be rooted!"); + + if (IsClosingCanceled()) + return; + BeforeLoadSolution(); OnSolutionLoading(fileName); try { @@ -500,7 +504,28 @@ namespace ICSharpCode.SharpDevelop.Project } } - public static void CloseSolution() + /// + /// Executes the OnBeforeSolutionClosing event. + /// + /// This method must be used after CloseSolution is called. + /// true, if closing solution was canceled; false, otherwise. + internal static bool IsClosingCanceled() + { + // run onbefore closing + var beforeClosingArgs = new SolutionCancelEventArgs(openSolution); + OnBeforeSolutionClosing(beforeClosingArgs); + + return beforeClosingArgs.Cancel; + } + + /// + /// Closes the solution: cancels build, clears solution data, fires the SolutionClosing and SolutionClosed events. + /// + /// Before invoking this method, one should check if the closing was canceled (), + /// save solution and project data (e.g. files, bookmarks), then invoke CloseSolution(). + /// + /// + internal static void CloseSolution() { // If a build is running, cancel it. // If we would let a build run but unload the MSBuild projects, the next project.StartBuild call @@ -541,6 +566,13 @@ namespace ICSharpCode.SharpDevelop.Project } } + static void OnBeforeSolutionClosing(SolutionCancelEventArgs e) + { + if (BeforeSolutionClosing != null) { + BeforeSolutionClosing(null, e); + } + } + static void OnSolutionLoading(string fileName) { if (SolutionLoading != null) { @@ -714,6 +746,15 @@ namespace ICSharpCode.SharpDevelop.Project public static event EventHandler SolutionClosing; public static event EventHandler SolutionClosed; + /// + /// Raised before SolutionClosing. + /// + /// When one modifies the e.Cancel property, should have in mind that other consumers might want to cancel the closing.
+ /// Setting e.Cancel = false might override other consumers (if they exist) e.Cancel = true, and might break other functionalities. + ///
+ ///
+ public static event EventHandler BeforeSolutionClosing; + /// /// Raised before the solution preferences are being saved. Allows you to save /// your additional properties in the solution preferences.