Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMikayla Hutchinson <m.j.hutchinson@gmail.com>2016-11-05 01:49:29 +0300
committerMikayla Hutchinson <m.j.hutchinson@gmail.com>2016-11-05 01:49:29 +0300
commit45f2b9092af4e89ac60ecab2e80ab73a8ed95537 (patch)
treeb265fc6edc399d895350be1082eb023d84ce3ae0 /main
parentd4e86ee9c8d321f012427fae99f1239842ed9f13 (diff)
parente4fad978da2dd6c1e6850a3c19f0e4affd2ffe38 (diff)
Merge remote-tracking branch 'origin/multisessiondebugging' into vNext
Diffstat (limited to 'main')
-rw-r--r--main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs2
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/SelectorView.cs39
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Win32/CorApi2/Extensions/ProcessExtensions.cs13
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs94
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs7
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs523
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs44
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs10
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ImmediatePad.cs24
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs2
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs6
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs142
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueTooltipProvider.cs5
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueWindow.cs2
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs4
-rw-r--r--main/src/addins/MonoDevelop.UnitTesting/Services/UnitTestService.cs2
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/ComboMenu.cs102
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionTarget.cs33
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MultiItemSolutionRunConfiguration.cs188
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs96
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionRunConfiguration.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml14
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs342
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs20
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationPanel.cs124
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs283
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs207
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs79
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget.cs150
-rw-r--r--main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic169
39 files changed, 1587 insertions, 1188 deletions
diff --git a/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs b/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs
index 7074fa24b2..bffd2966e8 100644
--- a/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs
+++ b/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs
@@ -171,7 +171,7 @@ namespace MonoDevelop.AspNet.Projects
var cfg = GetConfiguration (configuration);
var cmd = CreateExecutionCommand (configuration, cfg);
- var browserExcTarget = (BrowserExecutionTarget) context.ExecutionTarget;
+ var browserExcTarget = context.ExecutionTarget as BrowserExecutionTarget;
OperationConsole console = null;
diff --git a/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs b/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
index a8c17936d5..2d7988e3e5 100644
--- a/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
+++ b/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
@@ -235,11 +235,14 @@ namespace MonoDevelop.MacIntegration.MainToolbar
var menu = new NSMenu {
AutoEnablesItems = false,
- ShowsStateColumn = false,
+ ShowsStateColumn = true,
Font = NSFont.MenuFontOfSize (12),
};
foreach (var item in runtime.Children)
- CreateMenuItem (menu, item);
+ if (item.IsSeparator)
+ menu.AddItem (NSMenuItem.SeparatorItem);
+ else
+ CreateMenuItem (menu, item);
return menu;
}
@@ -251,14 +254,17 @@ namespace MonoDevelop.MacIntegration.MainToolbar
using (var mutableModel = runtime.GetMutableModel ()) {
runtimeFullDisplayString = mutableModel.FullDisplayString;
- menuItem = new NSMenuItem {
- IndentationLevel = runtime.IsIndented ? 2 : 1,
+ menuItem = new NSMenuItem () {
+ IndentationLevel = runtime.IsIndented ? 1 : 0,
AttributedTitle = new NSAttributedString (mutableModel.DisplayString, new NSStringAttributes {
Font = runtime.Notable ? NSFontManager.SharedFontManager.ConvertFont (menu.Font, NSFontTraitMask.Bold) : menu.Font,
}),
Enabled = mutableModel.Enabled,
Hidden = !mutableModel.Visible,
};
+ if (ActiveRuntime == runtime || (ActiveRuntime?.Children.Contains (runtime) ?? false)) {
+ menuItem.State = NSCellStateValue.On;
+ }
}
var subMenu = CreateSubMenuForRuntime (runtime);
@@ -267,27 +273,15 @@ namespace MonoDevelop.MacIntegration.MainToolbar
menuItem.Enabled = true;
} else {
menuItem.Activated += (o2, e2) => {
- string old;
- using (var activeMutableModel = ActiveRuntime.GetMutableModel ())
- old = activeMutableModel.FullDisplayString;
-
- IRuntimeModel newRuntime = runtimeModel.FirstOrDefault (r => {
- using (var newRuntimeMutableModel = r.GetMutableModel ())
- return newRuntimeMutableModel.FullDisplayString == runtimeFullDisplayString;
- });
- if (newRuntime == null)
- return;
-
- ActiveRuntime = newRuntime;
+ var old = ActiveRuntime;
+
+ ActiveRuntime = runtime;
var ea = new HandledEventArgs ();
if (RuntimeChanged != null)
RuntimeChanged (o2, ea);
if (ea.Handled)
- ActiveRuntime = runtimeModel.First (r => {
- using (var newRuntimeMutableModel = r.GetMutableModel ())
- return newRuntimeMutableModel.FullDisplayString == old;
- });
+ ActiveRuntime = old;
};
}
menu.AddItem (menuItem);
@@ -388,7 +382,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
NSMenuItem selectedItem = null;
var menu = new NSMenu {
AutoEnablesItems = false,
- ShowsStateColumn = false,
+ ShowsStateColumn = true,
Font = NSFont.MenuFontOfSize (12),
};
if (cellIdx == RunConfigurationIdx) {
@@ -435,9 +429,6 @@ namespace MonoDevelop.MacIntegration.MainToolbar
using (var activeMutableModel = ActiveRuntime.GetMutableModel ()) {
foreach (var runtime in RuntimeModel) {
- if (runtime.HasParent)
- continue;
-
NSMenuItem menuitem = null;
if (runtime.IsSeparator)
menu.AddItem (NSMenuItem.SeparatorItem);
diff --git a/main/src/addins/MonoDevelop.Debugger.Win32/CorApi2/Extensions/ProcessExtensions.cs b/main/src/addins/MonoDevelop.Debugger.Win32/CorApi2/Extensions/ProcessExtensions.cs
index de197db461..6bbd517df2 100644
--- a/main/src/addins/MonoDevelop.Debugger.Win32/CorApi2/Extensions/ProcessExtensions.cs
+++ b/main/src/addins/MonoDevelop.Debugger.Win32/CorApi2/Extensions/ProcessExtensions.cs
@@ -79,9 +79,11 @@ namespace Microsoft.Samples.Debugging.Extensions
break; // pipe done - normal exit path.
string s = System.Text.Encoding.Default.GetString (buffer, 0, nBytesRead);
- if (OnStdOutput != null)
- OnStdOutput (proc, new CorTargetOutputEventArgs (s, isStdError));
- }
+ List<CorTargetOutputEventHandler> list;
+ if (events.TryGetValue(proc, out list))
+ foreach (var del in list)
+ del(proc, new CorTargetOutputEventArgs(s, isStdError));
+ }
} catch {
}
}
@@ -98,19 +100,14 @@ namespace Microsoft.Samples.Debugging.Extensions
list.Add (handler);
events [proc] = list;
- OnStdOutput += handler;
}
static void RemoveEventsFor (CorProcess proc)
{
- foreach (CorTargetOutputEventHandler handler in events [proc])
- OnStdOutput -= handler;
-
events.Remove (proc);
}
// [Xamarin] Output redirection.
- static event CorTargetOutputEventHandler OnStdOutput;
static readonly Dictionary<CorProcess, List<CorTargetOutputEventHandler>> events = new Dictionary<CorProcess, List<CorTargetOutputEventHandler>> ();
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs
index c5f96272fa..c3ce656268 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs
@@ -77,28 +77,6 @@ namespace MonoDevelop.Debugger
return IdeApp.ProjectOperations.CurrentSelectedSolution ?? IdeApp.ProjectOperations.CurrentSelectedBuildTarget;
}
- internal async static void BuildAndDebug ()
- {
- if (!DebuggingService.IsDebuggingSupported && !IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted) {
- MonoDevelop.Ide.Commands.StopHandler.StopBuildOperations ();
- await IdeApp.ProjectOperations.CurrentRunOperation.Task;
- }
-
- if (IdeApp.Workspace.IsOpen) {
- var it = GetRunTarget ();
- ExecuteSolution (it);
- return;
- }
- }
-
- static void ExecuteSolution (IBuildTarget target)
- {
- if (IdeApp.ProjectOperations.CanDebug (target))
- IdeApp.ProjectOperations.Debug (target);
- else
- IdeApp.ProjectOperations.Execute (target);
- }
-
protected override void Run ()
{
if (DebuggingService.IsPaused) {
@@ -106,41 +84,32 @@ namespace MonoDevelop.Debugger
return;
}
- BuildAndDebug ();
+ if (IdeApp.Workspace.IsOpen) {
+ var target = GetRunTarget ();
+ if (target != null)
+ IdeApp.ProjectOperations.Debug (target);
+ }
}
-
+
protected override void Update (CommandInfo info)
{
- if (DebuggingService.IsRunning) {
+ if (!IdeApp.Workspace.IsOpen || !DebuggingService.IsDebuggingSupported) {
info.Enabled = false;
return;
}
-
if (DebuggingService.IsPaused) {
info.Enabled = true;
info.Text = GettextCatalog.GetString ("_Continue Debugging");
info.Description = GettextCatalog.GetString ("Continue the execution of the application");
return;
}
-
- // If there are no debugger installed, this command will not debug, it will
- // just run, so the label has to be changed accordingly.
- if (!DebuggingService.IsDebuggingSupported) {
- info.Text = IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted ? GettextCatalog.GetString ("Start Without Debugging") : GettextCatalog.GetString ("Restart Without Debugging");
- info.Icon = Stock.RunProgramIcon;
- }
-
- if (IdeApp.Workspace.IsOpen) {
- var target = GetRunTarget ();
- bool canExecute = target != null && (
- IdeApp.ProjectOperations.CanDebug (target) ||
- (!DebuggingService.IsDebuggingSupported && IdeApp.ProjectOperations.CanExecute (target))
- );
-
- info.Enabled = canExecute && (IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted || !DebuggingService.IsDebuggingSupported);
- } else {
+ if (DebuggingService.IsDebugging) {
info.Enabled = false;
+ return;
}
+
+ var target = GetRunTarget ();
+ info.Enabled = target != null && IdeApp.ProjectOperations.CanDebug (target);
}
}
@@ -156,9 +125,7 @@ namespace MonoDevelop.Debugger
protected override void Update (CommandInfo info)
{
IBuildTarget target = IdeApp.ProjectOperations.CurrentSelectedBuildTarget;
- info.Enabled = target != null &&
- !(target is Workspace) && IdeApp.ProjectOperations.CanDebug (target) &&
- IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted;
+ info.Enabled = target != null && !(target is Workspace) && IdeApp.ProjectOperations.CanDebug (target);
}
}
@@ -207,8 +174,7 @@ namespace MonoDevelop.Debugger
protected override void Update (CommandInfo info)
{
- info.Enabled = IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted;
- info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.DebugFile);
+ info.Enabled = info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.DebugFile);
}
}
@@ -229,8 +195,7 @@ namespace MonoDevelop.Debugger
protected override void Update (CommandInfo info)
{
- info.Enabled = IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted;
- info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Attaching);
+ info.Enabled = info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Attaching);
}
}
@@ -315,7 +280,7 @@ namespace MonoDevelop.Debugger
protected override void Update (CommandInfo info)
{
- info.Visible = !DebuggingService.IsRunning;
+ info.Visible = DebuggingService.IsPaused;
info.Enabled = DebuggingService.IsConnected && DebuggingService.IsPaused;
}
}
@@ -577,33 +542,34 @@ namespace MonoDevelop.Debugger
return;
}
- var bp = new RunToCursorBreakpoint (doc.FileName, doc.Editor.CaretLine, doc.Editor.CaretColumn);
- DebuggingService.Breakpoints.Add (bp);
- DebugHandler.BuildAndDebug ();
+ if (IdeApp.Workspace.IsOpen) {
+ var bp = new RunToCursorBreakpoint (doc.FileName, doc.Editor.CaretLine, doc.Editor.CaretColumn);
+ DebuggingService.Breakpoints.Add (bp);
+ var target = DebugHandler.GetRunTarget ();
+ if (target != null)
+ IdeApp.ProjectOperations.Debug (target);
+ }
}
protected override void Update (CommandInfo info)
{
info.Visible = true;
- if (!DebuggingService.IsDebuggingSupported || !DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints) || DebuggingService.Breakpoints.IsReadOnly) {
+ if (!IdeApp.Workspace.IsOpen || !DebuggingService.IsDebuggingSupported || !DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints) || DebuggingService.Breakpoints.IsReadOnly) {
info.Enabled = false;
return;
}
var doc = IdeApp.Workbench.ActiveDocument;
- if (doc != null && doc.Editor != null && doc.FileName != FilePath.Null) {
- if (IdeApp.Workspace.IsOpen) {
- var target = DebugHandler.GetRunTarget ();
-
- info.Enabled = target != null && IdeApp.ProjectOperations.CanDebug (target);
- } else {
- info.Enabled = false;
+ if (doc?.Editor != null && doc.FileName != FilePath.Null) {
+ var target = DebugHandler.GetRunTarget ();
+ if (target != null && IdeApp.ProjectOperations.CanDebug (target)) {
+ info.Enabled = true;
+ return;
}
- } else {
- info.Enabled = false;
}
+ info.Enabled = false;
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs
index fb30399b30..1dc7d699d2 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugExecutionHandlerFactory.cs
@@ -56,9 +56,11 @@ namespace MonoDevelop.Debugger
class DebugAsyncOperation: ProcessAsyncOperation
{
TaskCompletionSource<int> taskSource;
+ DebuggerSession session;
- public DebugAsyncOperation ()
+ public DebugAsyncOperation (DebuggerSession session)
{
+ this.session = session;
taskSource = new TaskCompletionSource<int> ();
DebuggingService.StoppedEvent += OnStopDebug;
CancellationTokenSource = new CancellationTokenSource ();
@@ -73,11 +75,12 @@ namespace MonoDevelop.Debugger
taskSource = null;
}
DebuggingService.StoppedEvent -= OnStopDebug;
+ session = null;
}
void OnStopDebug (object sender, EventArgs args)
{
- if (taskSource != null) {
+ if (taskSource != null && session == sender) {
taskSource.SetResult (0);
taskSource = null;
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
index c3c9c248ca..7bfe017058 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
@@ -46,52 +46,48 @@ using MonoDevelop.Debugger.Viewers;
using MonoDevelop.Ide.TextEditing;
using System.Linq;
using System.Threading.Tasks;
-using MonoDevelop.Ide.TypeSystem;
+using System.Collections.Concurrent;
+using System.Threading;
namespace MonoDevelop.Debugger
{
public static class DebuggingService
{
const string FactoriesPath = "/MonoDevelop/Debugging/DebuggerEngines";
- static DebuggerEngine[] engines;
-
+ static DebuggerEngine [] engines;
+
const string EvaluatorsPath = "/MonoDevelop/Debugging/Evaluators";
static Dictionary<string, ExpressionEvaluatorExtensionNode> evaluators;
static readonly PinnedWatchStore pinnedWatches = new PinnedWatchStore ();
static readonly BreakpointStore breakpoints = new BreakpointStore ();
static readonly DebugExecutionHandlerFactory executionHandlerFactory;
-
- static OperationConsole console;
- static IDisposable cancelRegistration;
static Dictionary<long, SourceLocation> nextStatementLocations = new Dictionary<long, SourceLocation> ();
- static DebuggerEngine currentEngine;
- static DebuggerSession session;
+ static Dictionary<DebuggerSession, SessionManager> sessions = new Dictionary<DebuggerSession, SessionManager> ();
static Backtrace currentBacktrace;
+ static SessionManager currentSession;
static int currentFrame;
-
+
static ExceptionCaughtMessage exceptionDialog;
-
+
static BusyEvaluator busyEvaluator;
static StatusBarIcon busyStatusIcon;
static bool isBusy;
- static DebugAsyncOperation currentDebugOperation = new DebugAsyncOperation ();
-
static public event EventHandler DebugSessionStarted;
static public event EventHandler PausedEvent;
static public event EventHandler ResumedEvent;
static public event EventHandler StoppedEvent;
-
+
static public event EventHandler CallStackChanged;
static public event EventHandler CurrentFrameChanged;
static public event EventHandler ExecutionLocationChanged;
static public event EventHandler DisassemblyRequested;
static public event EventHandler<DocumentEventArgs> DisableConditionalCompilation;
-
+
static public event EventHandler EvaluationOptionsChanged;
-
+
static DebuggingService ()
{
executionHandlerFactory = new DebugExecutionHandlerFactory ();
@@ -110,30 +106,54 @@ namespace MonoDevelop.Debugger
// Refresh the evaluators list
evaluators = null;
});
- }
+ }
public static IExecutionHandler GetExecutionHandler ()
{
return executionHandlerFactory;
}
-
+
public static DebuggerSession DebuggerSession {
- get { return session; }
+ get { return currentSession?.Session; }
}
-
+
+
+ public static DebuggerSession [] GetSessions ()
+ {
+ return sessions.Keys.ToArray ();
+ }
+
+ public static ProcessInfo [] GetProcesses ()
+ {
+ return sessions.Keys.Where (s => !s.IsRunning).SelectMany (s => s.GetProcesses ()).ToArray ();
+ }
+
+ public static BreakEventStatus GetBreakpointStatus (Breakpoint bp)
+ {
+ var result = BreakEventStatus.Disconnected;
+ foreach (var sesion in sessions.Keys.ToArray ()) {
+ var status = bp.GetStatus (sesion);
+ if (status == BreakEventStatus.Bound)
+ return BreakEventStatus.Bound;
+ else
+ result = status;
+ }
+ return result;
+ }
+
public static BreakpointStore Breakpoints {
get { return breakpoints; }
}
-
+
public static PinnedWatchStore PinnedWatches {
get { return pinnedWatches; }
}
-
+
public static void SetLiveUpdateMode (PinnedWatch watch, bool liveUpdate)
{
if (watch.LiveUpdate == liveUpdate)
return;
-
+
watch.LiveUpdate = liveUpdate;
if (liveUpdate) {
var bp = new Breakpoint (watch.File, watch.Line);
@@ -149,19 +169,10 @@ namespace MonoDevelop.Debugger
breakpoints.Remove (watch.BoundTracer);
}
}
-
- static void BreakpointTraceHandler (BreakEvent be, string trace)
- {
- if (be is Breakpoint) {
- if (pinnedWatches.UpdateLiveWatch ((Breakpoint) be, trace))
- return; // No need to log the value. It is shown in the watch.
- }
- DebugWriter (0, "", trace + Environment.NewLine);
- }
[Obsolete]
- public static string[] EnginePriority {
- get { return new string[0]; }
+ public static string [] EnginePriority {
+ get { return new string [0]; }
set {
}
}
@@ -245,7 +256,7 @@ namespace MonoDevelop.Debugger
{
return GetSetConverter<T> (val) != null;
}
-
+
public static void ShowValueVisualizer (ObjectValue val)
{
using (var dlg = new ValueVisualizerDialog ()) {
@@ -258,7 +269,7 @@ namespace MonoDevelop.Debugger
{
PreviewWindowManager.Show (val, widget, previewButtonArea);
}
-
+
public static bool ShowBreakpointProperties (ref BreakEvent bp, BreakpointType breakpointType = BreakpointType.Location)
{
using (var dlg = new BreakpointPropertiesDialog (bp, breakpointType)) {
@@ -272,7 +283,7 @@ namespace MonoDevelop.Debugger
public static void AddWatch (string expression)
{
var pad = IdeApp.Workbench.GetPad<WatchPad> ();
- var wp = (WatchPad) pad.Content;
+ var wp = (WatchPad)pad.Content;
pad.BringToFront (false);
wp.AddWatch (expression);
@@ -291,7 +302,7 @@ namespace MonoDevelop.Debugger
public static bool CurrentSessionSupportsFeature (DebuggerFeatures feature)
{
- return (currentEngine.SupportedFeatures & feature) == feature;
+ return (currentSession.Engine.SupportedFeatures & feature) == feature;
}
public static bool IsFeatureSupported (DebuggerFeatures feature)
@@ -305,7 +316,7 @@ namespace MonoDevelop.Debugger
public static DebuggerFeatures GetSupportedFeatures (IBuildTarget target)
{
var fc = new FeatureCheckerHandlerFactory ();
- var ctx = new ExecutionContext (fc, null, IdeApp.Workspace.ActiveExecutionTarget);
+ var ctx = new Projects.ExecutionContext (fc, null, IdeApp.Workspace.ActiveExecutionTarget);
target.CanExecute (ctx, IdeApp.Workspace.ActiveConfiguration);
@@ -331,7 +342,7 @@ namespace MonoDevelop.Debugger
public static void ShowExceptionCaughtDialog ()
{
- var ops = session.EvaluationOptions.Clone ();
+ var ops = GetUserOptions ().EvaluationOptions;
ops.MemberEvaluationTimeout = 0;
ops.EvaluationTimeout = 0;
ops.EllipsizeStrings = false;
@@ -362,19 +373,21 @@ namespace MonoDevelop.Debugger
return exceptionDialog;
}
}
-
- static void SetupSession ()
+
+ static void SetupSession (SessionManager sessionManager)
{
+ sessions.Add (sessionManager.Session, sessionManager);
isBusy = false;
+ var session = sessionManager.Session;
session.Breakpoints = breakpoints;
session.TargetEvent += OnTargetEvent;
session.TargetStarted += OnStarted;
- session.OutputWriter = OutputWriter;
- session.LogWriter = LogWriter;
- session.DebugWriter = DebugWriter;
+ session.OutputWriter = sessionManager.OutputWriter;
+ session.LogWriter = sessionManager.LogWriter;
+ session.DebugWriter = sessionManager.DebugWriter;
session.BusyStateChanged += OnBusyStateChanged;
session.TypeResolverHandler = ResolveType;
- session.BreakpointTraceHandler = BreakpointTraceHandler;
+ session.BreakpointTraceHandler = sessionManager.BreakpointTraceHandler;
session.GetExpressionEvaluator = OnGetExpressionEvaluator;
session.ConnectionDialogCreatorExtended = delegate (DebuggerStartInfo dsi) {
if (dsi.RequiresManualStart)
@@ -382,61 +395,54 @@ namespace MonoDevelop.Debugger
return new StatusBarConnectionDialog ();
};
- currentDebugOperation = new DebugAsyncOperation ();
- cancelRegistration = console.CancellationToken.Register (Stop);
-
Runtime.RunInMainThread (delegate {
if (DebugSessionStarted != null)
DebugSessionStarted (null, EventArgs.Empty);
NotifyLocationChanged ();
});
-
}
static readonly object cleanup_lock = new object ();
- static void Cleanup ()
+ static void Cleanup (SessionManager sessionManager)
{
- DebuggerSession currentSession;
StatusBarIcon currentIcon;
- OperationConsole currentConsole;
+ var cleaningCurrentSession = sessionManager == currentSession;
lock (cleanup_lock) {
if (!IsDebugging)
return;
currentIcon = busyStatusIcon;
- currentSession = session;
- currentConsole = console;
nextStatementLocations.Clear ();
- currentBacktrace = null;
+ if (cleaningCurrentSession) {
+ currentSession = null;
+ currentBacktrace = null;
+ }
busyStatusIcon = null;
- session = null;
- console = null;
+ sessions.Remove (sessionManager.Session);
pinnedWatches.InvalidateAll ();
}
- UnsetDebugLayout ();
+ if (sessions.Count == 0)
+ UnsetDebugLayout ();
+ var session = sessionManager.Session;
+ session.BusyStateChanged -= OnBusyStateChanged;
+ session.TargetEvent -= OnTargetEvent;
+ session.TargetStarted -= OnStarted;
- currentSession.BusyStateChanged -= OnBusyStateChanged;
- currentSession.TargetEvent -= OnTargetEvent;
- currentSession.TargetStarted -= OnStarted;
+ session.BreakpointTraceHandler = null;
+ session.GetExpressionEvaluator = null;
+ session.TypeResolverHandler = null;
+ session.OutputWriter = null;
+ session.LogWriter = null;
- currentSession.BreakpointTraceHandler = null;
- currentSession.GetExpressionEvaluator = null;
- currentSession.TypeResolverHandler = null;
- currentSession.OutputWriter = null;
- currentSession.LogWriter = null;
- currentDebugOperation.Cleanup ();
+ sessionManager.Dispose ();
- if (currentConsole != null) {
- cancelRegistration.Dispose ();
- currentConsole.Dispose ();
- }
-
Runtime.RunInMainThread (delegate {
- HideExceptionCaughtDialog ();
+ if (cleaningCurrentSession)
+ HideExceptionCaughtDialog ();
if (currentIcon != null) {
currentIcon.Dispose ();
@@ -444,14 +450,13 @@ namespace MonoDevelop.Debugger
}
if (StoppedEvent != null)
- StoppedEvent (null, new EventArgs ());
+ StoppedEvent (session, new EventArgs ());
NotifyCallStackChanged ();
NotifyCurrentFrameChanged ();
NotifyLocationChanged ();
});
- currentSession.Dispose ();
}
static string oldLayout;
@@ -479,31 +484,48 @@ namespace MonoDevelop.Debugger
public static bool IsDebugging {
get {
- return session != null;
+ return sessions.Count > 0;
}
}
public static bool IsConnected {
get {
- return IsDebugging && session.IsConnected;
+ return IsDebugging && sessions.Keys.Any (s => s.IsConnected);
}
}
public static bool IsRunning {
get {
- return IsDebugging && session.IsRunning;
+ return IsDebugging && sessions.Keys.Any (s => s.IsRunning);
}
}
public static bool IsPaused {
get {
- return IsDebugging && !IsRunning && currentBacktrace != null;
+ return IsDebugging && currentSession != null && currentBacktrace != null;
}
}
public static void Pause ()
{
- session.Stop ();
+ foreach (var session in sessions.Keys.ToArray ()) {
+ if (session.IsRunning)
+ session.Stop ();
+ }
+ }
+
+ static ConcurrentQueue<Func<bool>> StopsQueue = new ConcurrentQueue<Func<bool>> ();
+
+ static bool HandleStopQueue ()
+ {
+ Func<bool> delayedStop;
+ while (StopsQueue.TryDequeue (out delayedStop)) {
+ //Returns false if session which scheduled stop is terminated
+ //So we just ignore it's stop entry and keep processing others or resume
+ if (delayedStop ())
+ return true;
+ }
+ return false;
}
public static void Resume ()
@@ -511,8 +533,13 @@ namespace MonoDevelop.Debugger
Runtime.AssertMainThread ();
if (CheckIsBusy ())
return;
+ if (HandleStopQueue ())
+ return;
- session.Continue ();
+ foreach (var session in sessions.Keys.ToArray ()) {
+ if (!session.IsRunning)
+ session.Continue ();
+ }
NotifyLocationChanged ();
}
@@ -525,20 +552,20 @@ namespace MonoDevelop.Debugger
var bp = new RunToCursorBreakpoint (fileName, line, column);
Breakpoints.Add (bp);
- session.Continue ();
+ Resume ();
NotifyLocationChanged ();
}
public static void SetNextStatement (string fileName, int line, int column)
{
Runtime.AssertMainThread ();
- if (!IsDebugging || IsRunning || CheckIsBusy ())
+ if (!IsDebugging || !IsPaused || CheckIsBusy ())
return;
- session.SetNextStatement (fileName, line, column);
+ currentSession.Session.SetNextStatement (fileName, line, column);
- var location = new SourceLocation (CurrentFrame.SourceLocation.MethodName, fileName, line);
- nextStatementLocations[session.ActiveThread.Id] = location;
+ var location = new SourceLocation (CurrentFrame.SourceLocation.MethodName, fileName, line, column, -1, -1, null);
+ nextStatementLocations [ActiveThread.Id] = location;
NotifyLocationChanged ();
}
@@ -548,10 +575,10 @@ namespace MonoDevelop.Debugger
return Run (cmd, console);
}
- public static ProcessAsyncOperation Run (string file, string args, string workingDir, IDictionary<string,string> envVars, OperationConsole console)
+ public static ProcessAsyncOperation Run (string file, string args, string workingDir, IDictionary<string, string> envVars, OperationConsole console)
{
var cmd = Runtime.ProcessService.CreateCommand (file);
- if (args != null)
+ if (args != null)
cmd.Arguments = args;
if (workingDir != null)
cmd.WorkingDirectory = workingDir;
@@ -562,26 +589,25 @@ namespace MonoDevelop.Debugger
public static ProcessAsyncOperation Run (ExecutionCommand cmd, OperationConsole console, DebuggerEngine engine = null)
{
- InternalRun (cmd, engine, console);
- return currentDebugOperation;
+ return InternalRun (cmd, engine, console);
}
-
+
public static AsyncOperation AttachToProcess (DebuggerEngine debugger, ProcessInfo proc)
{
- currentEngine = debugger;
- session = debugger.CreateSession ();
- session.ExceptionHandler = ExceptionHandler;
+ var session = debugger.CreateSession ();
var monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor ();
- console = monitor.Console;
- SetupSession ();
+ var sessionManager = new SessionManager (session, monitor.Console, debugger);
+ sessions.Add (session, sessionManager);
+ session.ExceptionHandler = ExceptionHandler;
+ SetupSession (sessionManager);
session.TargetExited += delegate {
monitor.Dispose ();
};
SetDebugLayout ();
session.AttachToProcess (proc, GetUserOptions ());
- return currentDebugOperation;
+ return sessionManager.debugOperation;
}
-
+
public static DebuggerSessionOptions GetUserOptions ()
{
EvaluationOptions eval = EvaluationOptions.DefaultOptions;
@@ -598,70 +624,68 @@ namespace MonoDevelop.Debugger
EvaluationOptions = eval,
};
}
-
+
public static void SetUserOptions (DebuggerSessionOptions options)
{
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.StepOverPropertiesAndOperators", options.StepOverPropertiesAndOperators);
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.ProjectAssembliesOnly", options.ProjectAssembliesOnly);
-
+
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.AllowTargetInvoke", options.EvaluationOptions.AllowTargetInvoke);
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.AllowToStringCalls", options.EvaluationOptions.AllowToStringCalls);
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.EvaluationTimeout", options.EvaluationOptions.EvaluationTimeout);
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.FlattenHierarchy", options.EvaluationOptions.FlattenHierarchy);
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.GroupPrivateMembers", options.EvaluationOptions.GroupPrivateMembers);
PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.GroupStaticMembers", options.EvaluationOptions.GroupStaticMembers);
-
- if (session != null) {
+
+ foreach (var session in sessions.Keys.ToArray ()) {
session.Options.EvaluationOptions = GetUserOptions ().EvaluationOptions;
- if (EvaluationOptionsChanged != null)
- EvaluationOptionsChanged (null, EventArgs.Empty);
}
+ if (EvaluationOptionsChanged != null)
+ EvaluationOptionsChanged (null, EventArgs.Empty);
}
-
+
public static void ShowDisassembly ()
{
if (DisassemblyRequested != null)
DisassemblyRequested (null, EventArgs.Empty);
}
-
- internal static void InternalRun (ExecutionCommand cmd, DebuggerEngine factory, OperationConsole c)
+
+ internal static ProcessAsyncOperation InternalRun (ExecutionCommand cmd, DebuggerEngine factory, OperationConsole c)
{
if (factory == null) {
factory = GetFactoryForCommand (cmd);
if (factory == null)
throw new InvalidOperationException ("Unsupported command: " + cmd);
}
-
- if (session != null)
- throw new InvalidOperationException ("A debugger session is already started");
DebuggerStartInfo startInfo = factory.CreateDebuggerStartInfo (cmd);
startInfo.UseExternalConsole = c is ExternalConsole;
if (startInfo.UseExternalConsole)
startInfo.CloseExternalConsoleOnExit = ((ExternalConsole)c).CloseOnDispose;
- currentEngine = factory;
- session = factory.CreateSession ();
+
+ var session = factory.CreateSession ();
session.ExceptionHandler = ExceptionHandler;
-
+
+ SessionManager sessionManager;
// When using an external console, create a new internal console which will be used
// to show the debugger log
if (startInfo.UseExternalConsole)
- console = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor ().Console;
+ sessionManager = new SessionManager (session, IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor ().Console, factory);
else
- console = c;
-
- SetupSession ();
-
+ sessionManager = new SessionManager (session, c, factory);
+ SetupSession (sessionManager);
+
SetDebugLayout ();
-
+
try {
session.Run (startInfo, GetUserOptions ());
} catch {
- Cleanup ();
+ Cleanup (sessionManager);
throw;
}
+ return sessionManager.debugOperation;
}
-
+
static bool ExceptionHandler (Exception ex)
{
Gtk.Application.Invoke (delegate {
@@ -672,34 +696,65 @@ namespace MonoDevelop.Debugger
});
return true;
}
-
- static void LogWriter (bool iserr, string text)
+
+ class SessionManager : IDisposable
{
- // Events may come with a bit of delay, so the debug session
- // may already have been cleaned up
- var logger = console;
+ OperationConsole console;
+ IDisposable cancelRegistration;
+ public readonly DebuggerSession Session;
+ public readonly DebugAsyncOperation debugOperation;
+ public readonly DebuggerEngine Engine;
- if (logger != null)
- logger.Log.Write (text);
- }
+ public SessionManager (DebuggerSession session, OperationConsole console, DebuggerEngine engine)
+ {
+ Engine = engine;
+ Session = session;
+ this.console = console;
+ cancelRegistration = console.CancellationToken.Register (Cancel);
+ debugOperation = new DebugAsyncOperation (session);
+ }
- static void DebugWriter (int level, string category, string message)
- {
- var logger = console;
+ void Cancel ()
+ {
+ Session.Exit ();
+ Cleanup (this);
+ }
- if (logger != null)
- logger.Debug (level, category, message);
- }
+ public void LogWriter (bool iserr, string text)
+ {
+ console?.Log.Write (text);
+ }
- static void OutputWriter (bool iserr, string text)
- {
- var logger = console;
+ public void DebugWriter (int level, string category, string message)
+ {
+ console?.Debug (level, category, message);
+ }
- if (logger != null) {
+ public void OutputWriter (bool iserr, string text)
+ {
if (iserr)
- logger.Error.Write (text);
+ console?.Error.Write (text);
else
- logger.Out.Write (text);
+ console?.Out.Write (text);
+ }
+
+ public void BreakpointTraceHandler (BreakEvent be, string trace)
+ {
+ if (be is Breakpoint) {
+ if (pinnedWatches.UpdateLiveWatch ((Breakpoint)be, trace))
+ return; // No need to log the value. It is shown in the watch.
+ }
+ DebugWriter (0, "", trace + Environment.NewLine);
+ }
+
+ public void Dispose ()
+ {
+ console?.Dispose ();
+ console = null;
+ Session.Dispose ();
+ debugOperation.Cleanup ();
+ cancelRegistration?.Dispose ();
+ cancelRegistration = null;
}
}
@@ -729,18 +784,21 @@ namespace MonoDevelop.Debugger
{
MessageService.PlaceDialog (busyEvaluator.Dialog, MessageService.RootWindow);
}
-
+
static bool CheckIsBusy ()
{
if (isBusy && !busyEvaluator.Dialog.Visible)
MessageService.PlaceDialog (busyEvaluator.Dialog, MessageService.RootWindow);
return isBusy;
}
-
+
static void OnStarted (object s, EventArgs a)
{
nextStatementLocations.Clear ();
- currentBacktrace = null;
+ if (currentSession?.Session == s) {
+ currentBacktrace = null;
+ currentSession = null;
+ }
Runtime.RunInMainThread (delegate {
HideExceptionCaughtDialog ();
@@ -751,9 +809,10 @@ namespace MonoDevelop.Debugger
NotifyLocationChanged ();
});
}
-
+
static void OnTargetEvent (object sender, TargetEventArgs args)
{
+ var session = (DebuggerSession)sender;
if (args.BreakEvent != null && args.BreakEvent.NonUserBreakpoint)
return;
nextStatementLocations.Clear ();
@@ -762,7 +821,9 @@ namespace MonoDevelop.Debugger
switch (args.Type) {
case TargetEventType.TargetExited:
Breakpoints.RemoveRunToCursorBreakpoints ();
- Cleanup ();
+ SessionManager sessionToCleanup;
+ if (sessions.TryGetValue (session, out sessionToCleanup))//It was already cleanedUp by Stop command
+ Cleanup (sessionToCleanup);
break;
case TargetEventType.TargetSignaled:
case TargetEventType.TargetStopped:
@@ -770,17 +831,30 @@ namespace MonoDevelop.Debugger
case TargetEventType.TargetInterrupted:
case TargetEventType.UnhandledException:
case TargetEventType.ExceptionThrown:
- Breakpoints.RemoveRunToCursorBreakpoints ();
- SetCurrentBacktrace (args.Backtrace);
- NotifyPaused ();
- NotifyException (args);
+ var action = new Func<bool> (delegate {
+ SessionManager sessionManager;
+ if (!sessions.TryGetValue (session, out sessionManager))
+ return false;
+ Breakpoints.RemoveRunToCursorBreakpoints ();
+ currentSession = sessionManager;
+ ActiveThread = args.Thread;
+ NotifyPaused ();
+ NotifyException (args);
+ return true;
+ });
+ if (currentSession != null && currentSession != sessions [session]) {
+ StopsQueue.Enqueue (action);
+ NotifyPaused ();//Notify about pause again, so ThreadsPad can update, to show all processes
+ } else {
+ action ();
+ }
break;
}
} catch (Exception ex) {
LoggingService.LogError ("Error handling debugger target event", ex);
}
}
-
+
static void OnDisableConditionalCompilation (DocumentEventArgs e)
{
EventHandler<DocumentEventArgs> handler = DisableConditionalCompilation;
@@ -791,13 +865,14 @@ namespace MonoDevelop.Debugger
static void NotifyPaused ()
{
Runtime.RunInMainThread (delegate {
+ stepSwitchCts?.Cancel ();
if (PausedEvent != null)
PausedEvent (null, EventArgs.Empty);
NotifyLocationChanged ();
IdeApp.Workbench.GrabDesktopFocus ();
});
}
-
+
static void NotifyException (TargetEventArgs args)
{
if (args.Type == TargetEventType.UnhandledException || args.Type == TargetEventType.ExceptionThrown) {
@@ -808,14 +883,14 @@ namespace MonoDevelop.Debugger
});
}
}
-
+
static void NotifyLocationChanged ()
{
Runtime.AssertMainThread ();
if (ExecutionLocationChanged != null)
ExecutionLocationChanged (null, EventArgs.Empty);
}
-
+
static void NotifyCurrentFrameChanged ()
{
if (currentBacktrace != null)
@@ -823,53 +898,76 @@ namespace MonoDevelop.Debugger
if (CurrentFrameChanged != null)
CurrentFrameChanged (null, EventArgs.Empty);
}
-
+
static void NotifyCallStackChanged ()
{
if (CallStackChanged != null)
CallStackChanged (null, EventArgs.Empty);
}
-
+
public static void Stop ()
{
if (!IsDebugging)
return;
- session.Exit ();
- Cleanup ();
+ foreach (var pair in sessions.ToArray ()) {
+ pair.Key.Exit ();
+ Cleanup (pair.Value);
+ }
}
public static void StepInto ()
{
Runtime.AssertMainThread ();
- if (!IsDebugging || IsRunning || CheckIsBusy ())
+ if (!IsDebugging || !IsPaused || CheckIsBusy ())
return;
-
- session.StepLine ();
+ currentSession.Session.StepLine ();
NotifyLocationChanged ();
+ DelayHandleStopQueue ();
}
public static void StepOver ()
{
Runtime.AssertMainThread ();
- if (!IsDebugging || IsRunning || CheckIsBusy ())
+ if (!IsDebugging || !IsPaused || CheckIsBusy ())
return;
-
- session.NextLine ();
+ currentSession.Session.NextLine ();
NotifyLocationChanged ();
+ DelayHandleStopQueue ();
}
public static void StepOut ()
{
Runtime.AssertMainThread ();
- if (!IsDebugging || IsRunning || CheckIsBusy ())
+ if (!IsDebugging || !IsPaused || CheckIsBusy ())
return;
-
- session.Finish ();
+ currentSession.Session.Finish ();
NotifyLocationChanged ();
+ DelayHandleStopQueue ();
+ }
+
+ static CancellationTokenSource stepSwitchCts;
+ static void DelayHandleStopQueue ()
+ {
+ stepSwitchCts?.Cancel ();
+ if (StopsQueue.Count > 0) {
+ stepSwitchCts = new CancellationTokenSource ();
+ var token = stepSwitchCts.Token;
+ Task.Delay (500, token).ContinueWith ((t) => {
+ if (token.IsCancellationRequested)
+ return;
+ Runtime.RunInMainThread (() => {
+ if (token.IsCancellationRequested)
+ return;
+ if (IsPaused)//If session is already paused(stepping finished in time), don't switch
+ return;
+ HandleStopQueue ();
+ });
+ });
+ }
}
public static Backtrace CurrentCallStack {
@@ -881,7 +979,7 @@ namespace MonoDevelop.Debugger
SourceLocation location = null;
if (IsPaused)
- nextStatementLocations.TryGetValue (session.ActiveThread.Id, out location);
+ nextStatementLocations.TryGetValue (ActiveThread.Id, out location);
return location;
}
@@ -895,7 +993,7 @@ namespace MonoDevelop.Debugger
return null;
}
}
-
+
/// <summary>
/// The deepest stack frame with source above the CurrentFrame
/// </summary>
@@ -910,7 +1008,7 @@ namespace MonoDevelop.Debugger
}
return null;
}
-
+
public static int CurrentFrameIndex {
get {
return currentFrame;
@@ -921,22 +1019,33 @@ namespace MonoDevelop.Debugger
Runtime.RunInMainThread (delegate {
NotifyCurrentFrameChanged ();
});
- }
- else
+ } else
currentFrame = -1;
}
}
-
+
public static ThreadInfo ActiveThread {
get {
- return session.ActiveThread;
+ return currentSession?.Session.ActiveThread;
}
set {
- session.ActiveThread = value;
- SetCurrentBacktrace (session.ActiveThread.Backtrace);
+ if (currentSession != null && currentSession.Session.GetProcesses () [0].GetThreads ().Contains (value)) {
+ currentSession.Session.ActiveThread = value;
+ SetCurrentBacktrace (value.Backtrace);
+ } else {
+ foreach (var session in sessions) {
+ if (session.Key.GetProcesses () [0].GetThreads ().Contains (value)) {
+ currentSession = session.Value;
+ currentSession.Session.ActiveThread = value;
+ SetCurrentBacktrace (value.Backtrace);
+ return;
+ }
+ }
+ throw new Exception ("Thread not found in any of active sessions.");
+ }
}
}
-
+
static void SetCurrentBacktrace (Backtrace bt)
{
currentBacktrace = bt;
@@ -951,7 +1060,7 @@ namespace MonoDevelop.Debugger
NotifyLocationChanged ();
});
}
-
+
public static async void ShowCurrentExecutionLine ()
{
Runtime.AssertMainThread ();
@@ -976,13 +1085,13 @@ namespace MonoDevelop.Debugger
ShowCurrentExecutionLine ();
}
}
-
+
public static bool CanDebugCommand (ExecutionCommand command)
{
return GetFactoryForCommand (command) != null;
}
-
- public static DebuggerEngine[] GetDebuggerEngines ()
+
+ public static DebuggerEngine [] GetDebuggerEngines ()
{
if (engines == null) {
var list = new List<DebuggerEngine> ();
@@ -996,18 +1105,18 @@ namespace MonoDevelop.Debugger
return engines;
}
- public static Dictionary<string, ExpressionEvaluatorExtensionNode> GetExpressionEvaluators()
+ public static Dictionary<string, ExpressionEvaluatorExtensionNode> GetExpressionEvaluators ()
{
if (evaluators == null) {
var evgs = new Dictionary<string, ExpressionEvaluatorExtensionNode> (StringComparer.InvariantCultureIgnoreCase);
foreach (ExpressionEvaluatorExtensionNode node in AddinManager.GetExtensionNodes (EvaluatorsPath))
evgs.Add (node.extension, node);
-
+
evaluators = evgs;
}
return evaluators;
}
-
+
static DebuggerEngine GetFactoryForCommand (ExecutionCommand cmd)
{
DebuggerEngine supportedEngine = null;
@@ -1025,7 +1134,7 @@ namespace MonoDevelop.Debugger
}
return supportedEngine;
}
-
+
static void OnLineCountChanged (object ob, LineCountEventArgs a)
{
lock (breakpoints) {
@@ -1043,7 +1152,7 @@ namespace MonoDevelop.Debugger
}
}
}
-
+
static void OnStoreUserPrefs (object s, UserPreferencesEventArgs args)
{
var baseDir = (args.Item as Solution)?.BaseDirectory;
@@ -1051,7 +1160,7 @@ namespace MonoDevelop.Debugger
args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.Breakpoints", breakpoints.Save (baseDir));
args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.PinnedWatches", pinnedWatches);
}
-
+
static Task OnLoadUserPrefs (object s, UserPreferencesEventArgs args)
{
var elem = args.Properties.GetValue<XmlElement> ("MonoDevelop.Ide.DebuggingService.Breakpoints") ?? args.Properties.GetValue<XmlElement> ("MonoDevelop.Ide.DebuggingService");
@@ -1068,21 +1177,21 @@ namespace MonoDevelop.Debugger
lock (breakpoints)
pinnedWatches.BindAll (breakpoints);
-
+
return Task.FromResult (true);
}
-
+
static void OnSolutionClosed (object s, EventArgs args)
{
lock (breakpoints)
breakpoints.Clear ();
}
-
+
static string ResolveType (string identifier, SourceLocation location)
{
Document doc = IdeApp.Workbench.GetDocument (location.FileName);
if (doc != null) {
- ITextEditorResolver textEditorResolver = doc.GetContent <ITextEditorResolver> ();
+ ITextEditorResolver textEditorResolver = doc.GetContent<ITextEditorResolver> ();
if (textEditorResolver != null) {
var rr = textEditorResolver.GetLanguageItem (doc.Editor.LocationToOffset (location.Line, 1), identifier);
var ns = rr as Microsoft.CodeAnalysis.INamespaceSymbol;
@@ -1100,7 +1209,7 @@ namespace MonoDevelop.Debugger
}
return null;
}
-
+
public static ExpressionEvaluatorExtensionNode EvaluatorForExtension (string extension)
{
ExpressionEvaluatorExtensionNode result;
@@ -1118,11 +1227,11 @@ namespace MonoDevelop.Debugger
return info != null ? info.Evaluator : null;
}
}
-
- class FeatureCheckerHandlerFactory: IExecutionHandler
+
+ class FeatureCheckerHandlerFactory : IExecutionHandler
{
public DebuggerFeatures SupportedFeatures { get; set; }
-
+
public bool CanExecute (ExecutionCommand command)
{
SupportedFeatures = DebuggingService.GetSupportedFeaturesForCommand (command);
@@ -1135,16 +1244,16 @@ namespace MonoDevelop.Debugger
throw new NotImplementedException ();
}
}
-
- class InternalDebugExecutionHandler: IExecutionHandler
+
+ class InternalDebugExecutionHandler : IExecutionHandler
{
readonly DebuggerEngine engine;
-
+
public InternalDebugExecutionHandler (DebuggerEngine engine)
{
this.engine = engine;
}
-
+
public bool CanExecute (ExecutionCommand command)
{
return engine.CanDebugCommand (command);
@@ -1174,13 +1283,13 @@ namespace MonoDevelop.Debugger
});
}
}
-
+
class GtkConnectionDialog : IConnectionDialog
{
static readonly string DefaultListenMessage = GettextCatalog.GetString ("Waiting for debugger to connect...");
System.Threading.CancellationTokenSource cts;
bool disposed;
-
+
public event EventHandler UserCancelled;
public void SetMessage (DebuggerStartInfo dsi, string message, bool listening, int attemptNumber)
@@ -1188,22 +1297,22 @@ namespace MonoDevelop.Debugger
//FIXME: we don't support changing the message
if (disposed || cts != null)
return;
-
+
cts = new System.Threading.CancellationTokenSource ();
-
+
//MessageService is threadsafe but we want this to be async
Gtk.Application.Invoke (delegate {
RunDialog (message);
});
}
-
+
void RunDialog (string message)
{
if (disposed)
return;
-
+
string title;
-
+
if (message == null) {
title = GettextCatalog.GetString ("Waiting for debugger");
} else {
@@ -1223,7 +1332,7 @@ namespace MonoDevelop.Debugger
gm.DefaultButton = 0;
MessageService.GenericAlert (gm);
cts = null;
-
+
if (!disposed && UserCancelled != null) {
UserCancelled (null, null);
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs
index 3a03dee6d1..64d0f31467 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs
@@ -60,6 +60,7 @@ namespace MonoDevelop.Debugger
bool dragging;
FilePath currentFile;
ITextLineMarker asmMarker;
+ DebuggerSession session;
List<AssemblyLine> cachedLines = new List<AssemblyLine> ();
string cachedLinesAddrSpace;
@@ -206,9 +207,9 @@ namespace MonoDevelop.Debugger
cachedLines.Clear ();
StackFrame sf = DebuggingService.CurrentFrame;
-
+ session = sf.DebuggerSession;
if (currentFile != sf.SourceLocation.FileName) {
- AssemblyLine[] asmLines = DebuggingService.DebuggerSession.DisassembleFile (sf.SourceLocation.FileName);
+ AssemblyLine[] asmLines = sf.DebuggerSession.DisassembleFile (sf.SourceLocation.FileName);
if (asmLines == null) {
// Mixed disassemble not supported
Fill ();
@@ -217,24 +218,25 @@ namespace MonoDevelop.Debugger
currentFile = sf.SourceLocation.FileName;
addressLines.Clear ();
editor.Text = string.Empty;
- StreamReader sr = new StreamReader (sf.SourceLocation.FileName);
- string line;
- int sourceLine = 1;
- int na = 0;
- int editorLine = 1;
- StringBuilder sb = new StringBuilder ();
- List<int> asmLineNums = new List<int> ();
- while ((line = sr.ReadLine ()) != null) {
- InsertSourceLine (sb, editorLine++, line);
- while (na < asmLines.Length && asmLines [na].SourceLine == sourceLine) {
- asmLineNums.Add (editorLine);
- InsertAssemblerLine (sb, editorLine++, asmLines [na++]);
+ using (var sr = new StreamReader (sf.SourceLocation.FileName)) {
+ string line;
+ int sourceLine = 1;
+ int na = 0;
+ int editorLine = 1;
+ var sb = new StringBuilder ();
+ var asmLineNums = new List<int> ();
+ while ((line = sr.ReadLine ()) != null) {
+ InsertSourceLine (sb, editorLine++, line);
+ while (na < asmLines.Length && asmLines [na].SourceLine == sourceLine) {
+ asmLineNums.Add (editorLine);
+ InsertAssemblerLine (sb, editorLine++, asmLines [na++]);
+ }
+ sourceLine++;
}
- sourceLine++;
+ editor.Text = sb.ToString ();
+ foreach (int li in asmLineNums)
+ editor.AddMarker (li, asmMarker);
}
- editor.Text = sb.ToString ();
- foreach (int li in asmLineNums)
- editor.AddMarker (li, asmMarker);
}
int aline;
if (!addressLines.TryGetValue (GetAddrId (sf.Address, sf.AddressSpace), out aline))
@@ -397,9 +399,11 @@ namespace MonoDevelop.Debugger
this.cachedLines.AddRange (lines);
return lineCount;
}
-
+
void OnStop (object s, EventArgs args)
{
+ if (session != s)
+ return;
addressLines.Clear ();
currentFile = null;
if (messageOverlayContent != null) {
@@ -410,6 +414,7 @@ namespace MonoDevelop.Debugger
autoRefill = false;
editor.Text = string.Empty;
cachedLines.Clear ();
+ session = null;
}
public override bool IsReadOnly {
@@ -421,6 +426,7 @@ namespace MonoDevelop.Debugger
{
base.Dispose ();
DebuggingService.StoppedEvent -= OnStop;
+ session = null;
}
[CommandHandler (DebugCommands.StepOver)]
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
index c1a7fac6ae..ac19a8f579 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
@@ -46,13 +46,9 @@ namespace MonoDevelop.Debugger
public static AsyncOperation Debug (this ProjectOperations opers, IBuildTarget entry, bool buildBeforeExecuting = true)
{
- if (opers.CurrentRunOperation != null && !opers.CurrentRunOperation.IsCompleted)
- return opers.CurrentRunOperation;
-
ExecutionContext context = new ExecutionContext (DebuggingService.GetExecutionHandler (), IdeApp.Workbench.ProgressMonitors.ConsoleFactory, IdeApp.Workspace.ActiveExecutionTarget);
- AsyncOperation op = opers.Execute (entry, context, buildBeforeExecuting);
- return op;
+ return opers.Execute (entry, context, buildBeforeExecuting);
}
public static bool CanDebugFile (this ProjectOperations opers, string file)
@@ -75,7 +71,7 @@ namespace MonoDevelop.Debugger
var monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor ();
var oper = DebuggingService.Run (executableFile, args, workingDir, envVars, monitor.Console);
- opers.CurrentRunOperation = oper;
+ opers.AddRunOperation (oper);
oper.Task.ContinueWith (t => {
monitor.Dispose ();
@@ -91,7 +87,7 @@ namespace MonoDevelop.Debugger
var oper = DebuggingService.AttachToProcess (debugger, proc);
- opers.CurrentRunOperation = oper;
+ opers.AddRunOperation (oper);
return opers.CurrentRunOperation;
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ImmediatePad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ImmediatePad.cs
index 1b5489e8f8..603d108857 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ImmediatePad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ImmediatePad.cs
@@ -41,7 +41,7 @@ namespace MonoDevelop.Debugger
{
static readonly object mutex = new object();
DebuggerConsoleView view;
- readonly List<uint> timersList = new List<uint>();
+ readonly Dictionary<DebuggerSession, List<uint>> timersList = new Dictionary<DebuggerSession, List<uint>> ();
protected override void Initialize (IPadWindow container)
{
@@ -77,7 +77,7 @@ namespace MonoDevelop.Debugger
var val = frame.GetExpressionValue (expression, ops);
if (val.IsEvaluating) {
- WaitForCompleted (val);
+ WaitForCompleted (val, frame.DebuggerSession);
return;
}
@@ -195,14 +195,15 @@ namespace MonoDevelop.Debugger
view.Buffer.Insert (ref start, text + "\n");
}
- void WaitForCompleted (ObjectValue val)
+ void WaitForCompleted (ObjectValue val, DebuggerSession session)
{
var mark = view.Buffer.CreateMark (null, view.InputLineEnd, true);
var iteration = 0;
uint timerId = 0;
timerId = GLib.Timeout.Add (100, () => {
- if (!timersList.Contains (timerId)) {
+ List<uint> list;
+ if (!timersList.TryGetValue (session, out list) || !list.Contains (timerId)) {
SetLineText (GettextCatalog.GetString ("Debugging stopped"), mark);
FinishPrinting ();
return false;
@@ -210,7 +211,7 @@ namespace MonoDevelop.Debugger
if (!val.IsEvaluating) {
if (iteration >= 5)
DeleteLineAtMark (mark);
- timersList.Remove (timerId);
+ list.Remove (timerId);
PrintValue (val);
@@ -226,7 +227,10 @@ namespace MonoDevelop.Debugger
return true;
});
- timersList.Add (timerId);
+ List<uint> tList;
+ if (!timersList.TryGetValue (session, out tList))
+ timersList [session] = tList = new List<uint> ();
+ tList.Add (timerId);
}
void WaitChildForCompleted (ObjectValue val, IDictionary<ObjectValue, bool> evaluatingList, bool hasMore)
@@ -279,18 +283,18 @@ namespace MonoDevelop.Debugger
void DebuggerResumed (object sender, EventArgs e)
{
- view.Editable = false;
+ view.Editable = DebuggingService.IsPaused;
}
void DebuggerPaused (object sender, EventArgs e)
{
- view.Editable = true;
+ view.Editable = DebuggingService.IsPaused;
}
void DebuggerStopped (object sender, EventArgs e)
{
- timersList.Clear ();
- view.Editable = false;
+ timersList.Remove ((DebuggerSession)sender);
+ view.Editable = DebuggingService.IsPaused;
}
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs
index eb6217ecec..bb97027184 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValuePad.cs
@@ -130,6 +130,8 @@ namespace MonoDevelop.Debugger
protected virtual void OnDebuggerStopped (object s, EventArgs a)
{
+ if (DebuggingService.IsDebugging)
+ return;
tree.ResetChangeTracking ();
tree.ClearAll ();
lastFrame = null;
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs
index afb0bc8f64..7b981c588a 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs
@@ -207,8 +207,10 @@ namespace MonoDevelop.Debugger
}
void OnDebuggingServiceStopped (object sender, EventArgs e)
- {
- if (store != null)
+ {
+ TreeIter iter;
+
+ if (store != null && store.GetIterFirst (out iter) && (store.GetValue (iter, FrameColumn) as StackFrame)?.DebuggerSession == sender)
store.Clear ();
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs
index 93e504e2a2..460f3a3190 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs
@@ -39,10 +39,11 @@ using MonoDevelop.Ide.Gui.Components;
using MonoDevelop.Ide;
using MonoDevelop.Components.AutoTest;
using System.ComponentModel;
+using System.Linq;
namespace MonoDevelop.Debugger
{
- public class ThreadsPad: PadContent
+ public class ThreadsPad : PadContent
{
ThreadsPadWidget control = new ThreadsPadWidget ();
@@ -66,7 +67,7 @@ namespace MonoDevelop.Debugger
TreeStore store;
bool needsUpdate;
IPadWindow window;
-
+
enum Columns
{
Icon,
@@ -74,15 +75,16 @@ namespace MonoDevelop.Debugger
Name,
Object,
Weight,
- Location
+ Location,
+ Session
}
-
+
public ThreadsPadWidget ()
{
this.ShadowType = ShadowType.None;
- store = new TreeStore (typeof(string), typeof (string), typeof(string), typeof(object), typeof(int), typeof(string));
- SemanticModelAttribute modelAttr = new SemanticModelAttribute ("store__Icon", "store__Id","store_Name",
+ store = new TreeStore (typeof (string), typeof (string), typeof (string), typeof (object), typeof (int), typeof (string), typeof (object));
+ SemanticModelAttribute modelAttr = new SemanticModelAttribute ("store__Icon", "store__Id", "store_Name",
"store_Object", "store_Weight", "store_Location");
TypeDescriptor.AddAttributes (store, modelAttr);
@@ -90,18 +92,18 @@ namespace MonoDevelop.Debugger
tree.RulesHint = true;
tree.HeadersVisible = true;
treeViewState = new TreeViewState (tree, (int)Columns.Object);
-
+
TreeViewColumn col = new TreeViewColumn ();
CellRenderer crp = new CellRendererImage ();
col.PackStart (crp, false);
- col.AddAttribute (crp, "stock_id", (int) Columns.Icon);
+ col.AddAttribute (crp, "stock_id", (int)Columns.Icon);
tree.AppendColumn (col);
-
+
TreeViewColumn FrameCol = new TreeViewColumn ();
FrameCol.Title = GettextCatalog.GetString ("Id");
FrameCol.PackStart (tree.TextRenderer, true);
- FrameCol.AddAttribute (tree.TextRenderer, "text", (int) Columns.Id);
- FrameCol.AddAttribute (tree.TextRenderer, "weight", (int) Columns.Weight);
+ FrameCol.AddAttribute (tree.TextRenderer, "text", (int)Columns.Id);
+ FrameCol.AddAttribute (tree.TextRenderer, "weight", (int)Columns.Weight);
FrameCol.Resizable = true;
FrameCol.Alignment = 0.0f;
tree.AppendColumn (FrameCol);
@@ -110,30 +112,56 @@ namespace MonoDevelop.Debugger
col.Title = GettextCatalog.GetString ("Name");
col.Resizable = true;
col.PackStart (tree.TextRenderer, false);
- col.AddAttribute (tree.TextRenderer, "text", (int) Columns.Name);
- col.AddAttribute (tree.TextRenderer, "weight", (int) Columns.Weight);
+ col.AddAttribute (tree.TextRenderer, "text", (int)Columns.Name);
+ col.AddAttribute (tree.TextRenderer, "weight", (int)Columns.Weight);
tree.AppendColumn (col);
col = new TreeViewColumn ();
col.Title = GettextCatalog.GetString ("Location");
col.Resizable = true;
col.PackStart (tree.TextRenderer, false);
- col.AddAttribute (tree.TextRenderer, "text", (int) Columns.Location);
- col.AddAttribute (tree.TextRenderer, "weight", (int) Columns.Weight);
+ col.AddAttribute (tree.TextRenderer, "text", (int)Columns.Location);
+ col.AddAttribute (tree.TextRenderer, "weight", (int)Columns.Weight);
tree.AppendColumn (col);
-
+
Add (tree);
ShowAll ();
-
+
UpdateDisplay ();
-
+
tree.RowActivated += OnRowActivated;
+ tree.DoPopupMenu = ShowPopup;
DebuggingService.CallStackChanged += OnStackChanged;
DebuggingService.PausedEvent += OnDebuggerPaused;
DebuggingService.ResumedEvent += OnDebuggerResumed;
DebuggingService.StoppedEvent += OnDebuggerStopped;
}
-
+
+ void ShowPopup (Gdk.EventButton evt)
+ {
+ TreeIter selected;
+
+ if (!tree.Selection.GetSelected (out selected))
+ return;
+ var process = store.GetValue (selected, (int)Columns.Object) as ProcessInfo;
+ if (process == null)
+ return;//User right-clicked on thread and not process
+ var session = store.GetValue (selected, (int)Columns.Session) as DebuggerSession;
+ var context_menu = new ContextMenu ();
+ var continueExecution = new ContextMenuItem (GettextCatalog.GetString ("Resume"));
+ continueExecution.Sensitive = !session.IsRunning;
+ continueExecution.Clicked += delegate {
+ session.Continue ();
+ };
+ context_menu.Items.Add (continueExecution);
+ var pauseExecution = new ContextMenuItem (GettextCatalog.GetString ("Pause"));
+ pauseExecution.Sensitive = session.IsRunning;
+ pauseExecution.Clicked += delegate {
+ session.Stop ();
+ };
+ context_menu.Items.Add (pauseExecution);
+ context_menu.Show (this, evt);
+ }
public override void Dispose ()
{
base.Dispose ();
@@ -142,12 +170,12 @@ namespace MonoDevelop.Debugger
DebuggingService.ResumedEvent -= OnDebuggerResumed;
DebuggingService.StoppedEvent -= OnDebuggerStopped;
}
-
+
void OnStackChanged (object s, EventArgs a)
{
UpdateDisplay ();
}
-
+
public void Initialize (IPadWindow window)
{
this.window = window;
@@ -156,7 +184,7 @@ namespace MonoDevelop.Debugger
Update ();
};
}
-
+
public void UpdateDisplay ()
{
if (window != null && window.ContentVisible)
@@ -171,50 +199,58 @@ namespace MonoDevelop.Debugger
tree.ScrollToPoint (0, 0);
treeViewState.Save ();
-
- store.Clear ();
- if (!DebuggingService.IsPaused)
- return;
+ store.Clear ();
try {
- var processes = DebuggingService.DebuggerSession.GetProcesses ();
-
- if (processes.Length == 1) {
- AppendThreads (TreeIter.Zero, processes[0]);
- } else {
- foreach (var process in processes) {
- TreeIter iter = store.AppendValues (null, process.Id.ToString (), process.Name, process, (int) Pango.Weight.Normal, "");
- AppendThreads (iter, process);
+ if (DebuggingService.GetSessions ().SelectMany (s => s.GetProcesses ()).Count () > 1) {
+ foreach (var session in DebuggingService.GetSessions ()) {
+ foreach (var process in session.GetProcesses ()) {
+ var iter = store.AppendValues (
+ session.IsRunning ? "md-continue-debug" : "md-pause-debug",
+ process.Id.ToString (),
+ process.Name,
+ process,
+ session == DebuggingService.DebuggerSession ? (int)Pango.Weight.Bold : (int)Pango.Weight.Normal,
+ "",
+ session);
+ if (session.IsRunning)
+ continue;
+ AppendThreads (iter, process, session);
+ }
}
+ } else {
+ if (!DebuggingService.IsPaused)
+ return;
+ AppendThreads (TreeIter.Zero, DebuggingService.DebuggerSession.GetProcesses () [0], DebuggingService.DebuggerSession);
}
} catch (Exception ex) {
LoggingService.LogInternalError (ex);
}
-
+
tree.ExpandAll ();
-
+
treeViewState.Load ();
}
- void AppendThreads (TreeIter iter, ProcessInfo process)
+ void AppendThreads (TreeIter iter, ProcessInfo process, DebuggerSession session)
{
var threads = process.GetThreads ();
Array.Sort (threads, (ThreadInfo t1, ThreadInfo t2) => t1.Id.CompareTo (t2.Id));
- DebuggingService.DebuggerSession.FetchFrames (threads);
+ session.FetchFrames (threads);
+ var activeThread = session.ActiveThread;
foreach (var thread in threads) {
- ThreadInfo activeThread = DebuggingService.DebuggerSession.ActiveThread;
- var name = thread.Name == null && thread.Id == 1 ? GettextCatalog.GetString("Main Thread") : thread.Name;
+ var name = thread.Name == null && thread.Id == 1 ? GettextCatalog.GetString ("Main Thread") : thread.Name;
var weight = thread == activeThread ? Pango.Weight.Bold : Pango.Weight.Normal;
var icon = thread == activeThread ? Gtk.Stock.GoForward : null;
if (iter.Equals (TreeIter.Zero))
- store.AppendValues (icon, thread.Id.ToString (), name, thread, (int) weight, thread.Location);
+ store.AppendValues (icon, thread.Id.ToString (), name, thread, (int)weight, thread.Location, session);
else
- store.AppendValues (iter, icon, thread.Id.ToString (), name, thread, (int) weight, thread.Location);
+ store.AppendValues (iter, icon, thread.Id.ToString (), name, thread, (int)weight, thread.Location, session);
}
}
@@ -223,8 +259,8 @@ namespace MonoDevelop.Debugger
var weight = thread == activeThread ? Pango.Weight.Bold : Pango.Weight.Normal;
var icon = thread == activeThread ? Gtk.Stock.GoForward : null;
- store.SetValue (iter, (int) Columns.Weight, (int) weight);
- store.SetValue (iter, (int) Columns.Icon, icon);
+ store.SetValue (iter, (int)Columns.Weight, (int)weight);
+ store.SetValue (iter, (int)Columns.Icon, icon);
}
void UpdateThreads (ThreadInfo activeThread)
@@ -235,16 +271,18 @@ namespace MonoDevelop.Debugger
return;
do {
- var thread = store.GetValue (iter, (int) Columns.Object) as ThreadInfo;
+ var thread = store.GetValue (iter, (int)Columns.Object) as ThreadInfo;
if (thread == null) {
+ store.SetValue (iter, (int)Columns.Weight, (int)(((ProcessInfo)store.GetValue (iter, (int)Columns.Object)).GetThreads ().Contains (activeThread) ? Pango.Weight.Bold : Pango.Weight.Normal));
+ var sessionActiveThread = ((DebuggerSession)store.GetValue (iter, (int)Columns.Session)).ActiveThread;
// this is a process... descend into our children
TreeIter child;
- if (store.IterChildren (out child)) {
+ if (store.IterChildren (out child, iter)) {
do {
- thread = store.GetValue (iter, (int) Columns.Object) as ThreadInfo;
- UpdateThread (child, thread, activeThread);
+ thread = store.GetValue (child, (int)Columns.Object) as ThreadInfo;
+ UpdateThread (child, thread, sessionActiveThread);
} while (store.IterNext (ref child));
}
} else {
@@ -252,7 +290,7 @@ namespace MonoDevelop.Debugger
}
} while (store.IterNext (ref iter));
}
-
+
void OnRowActivated (object s, RowActivatedArgs args)
{
TreeIter selected;
@@ -260,7 +298,7 @@ namespace MonoDevelop.Debugger
if (!tree.Selection.GetSelected (out selected))
return;
- var thread = store.GetValue (selected, (int) Columns.Object) as ThreadInfo;
+ var thread = store.GetValue (selected, (int)Columns.Object) as ThreadInfo;
if (thread != null) {
DebuggingService.CallStackChanged -= OnStackChanged;
@@ -279,12 +317,12 @@ namespace MonoDevelop.Debugger
{
UpdateDisplay ();
}
-
+
void OnDebuggerResumed (object s, EventArgs a)
{
UpdateDisplay ();
}
-
+
void OnDebuggerStopped (object s, EventArgs a)
{
UpdateDisplay ();
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueTooltipProvider.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueTooltipProvider.cs
index a7d6ca8c57..28c0ba6a20 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueTooltipProvider.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueTooltipProvider.cs
@@ -59,7 +59,10 @@ namespace MonoDevelop.SourceEditor
void TargetProcessExited (object sender, EventArgs e)
{
- if (tooltip != null) {
+ if (tooltip == null)
+ return;
+ var debuggerSession = tooltip.tree.Frame?.DebuggerSession;
+ if (debuggerSession == null || debuggerSession == sender) {
tooltip.Destroy ();
tooltip = null;
}
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueWindow.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueWindow.cs
index 050df0b9d0..95ee36d940 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueWindow.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/DebugValueWindow.cs
@@ -67,7 +67,7 @@ namespace MonoDevelop.SourceEditor
class DebugValueWindow : PopoverWindow
{
- ObjectValueTreeView tree;
+ internal ObjectValueTreeView tree;
ScrolledWindow sw;
static readonly string innerTreeName = "MonoDevelop.SourceEditor.DebugValueWindow.ObjectValueTreeView";
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
index 5cd8ea24ce..4d76a1dc1c 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
@@ -1228,6 +1228,8 @@ namespace MonoDevelop.SourceEditor
void HandleTargetExited (object sender, EventArgs e)
{
+ if (DebuggingService.IsDebugging)
+ return;
foreach (var marker in currentErrorMarkers) {
marker.IsVisible = true;
}
@@ -1343,7 +1345,7 @@ namespace MonoDevelop.SourceEditor
return;
}
DocumentLine line = document.GetLine (bp.Line);
- var status = bp.GetStatus (DebuggingService.DebuggerSession);
+ var status = DebuggingService.GetBreakpointStatus(bp);
bool tracepoint = (bp.HitAction & HitAction.Break) == HitAction.None;
if (line == null)
diff --git a/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTestService.cs b/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTestService.cs
index 5223c31fac..9e3edc791d 100644
--- a/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTestService.cs
+++ b/main/src/addins/MonoDevelop.UnitTesting/Services/UnitTestService.cs
@@ -154,7 +154,7 @@ namespace MonoDevelop.UnitTesting
OnTestSessionStarting (new TestSessionEventArgs { Session = session, Test = test });
if (checkCurrentRunOperation)
- IdeApp.ProjectOperations.CurrentRunOperation = session;
+ IdeApp.ProjectOperations.AddRunOperation (session);
try {
await session.Start ();
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/ComboMenu.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/ComboMenu.cs
index ffa685e006..bb4c3ee9da 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/ComboMenu.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/ComboMenu.cs
@@ -276,36 +276,68 @@ namespace WindowsPlatform.MainToolbar
};
}
+ IEnumerable<RuntimeMenuItem> Flatten(IEnumerable<RuntimeMenuItem> list)
+ {
+ foreach (var item in list)
+ {
+ yield return item;
+ foreach (var child in Flatten(item.Items.OfType<RuntimeMenuItem>()))
+ yield return child;
+ }
+ }
+
IRuntimeModel active;
public override IRuntimeModel Active
{
get
{
return active;
- }
+ }
set
{
var menuItem = DropMenu.Items
- .OfType<RuntimeMenuItem> ()
- .FirstOrDefault (it => it.Model == value);
-
- if (menuItem == null) {
- active = null;
- DropMenuText = "Default";
- IsEnabled = false;
+ .OfType<RuntimeMenuItem>()
+ .FirstOrDefault(it => it.Model == value);
+ active = value;
+ if (menuItem == null)
+ {
+ if (value != null)
+ {
+ //We have MultipleTargets runtime
+ foreach (var item in value.Children)
+ {
+ menuItem = Flatten(DropMenu.Items
+ .OfType<RuntimeMenuItem>())
+ .FirstOrDefault(it => it.Model == item);
+ if (menuItem != null)
+ {
+ menuItem.Margin = new Thickness(0, 0, 0, 0);
+ menuItem.FontWeight = FontWeights.Normal;
+ }
+ }
+ using (var mutableModel = active.GetMutableModel())
+ {
+ DropMenuText = mutableModel.FullDisplayString;
+ IsEnabled = true;
+ }
+ }
+ else
+ {
+ DropMenuText = "Default";
+ IsEnabled = false;
+ }
return;
}
-
- active = menuItem.Model;
- menuItem.Margin = new Thickness (0, 0, 0, 0);
+ menuItem.Margin = new Thickness(0, 0, 0, 0);
menuItem.FontWeight = FontWeights.Normal;
- using (var mutableModel = active.GetMutableModel ()) {
+ using (var mutableModel = active.GetMutableModel())
+ {
DropMenuText = mutableModel.FullDisplayString;
IsEnabled = true;
}
- }
+ }
}
IEnumerable<IRuntimeModel> model;
@@ -336,38 +368,34 @@ namespace WindowsPlatform.MainToolbar
}
}
- void OnMenuItemClicked (object sender, RoutedEventArgs args)
+ void OnMenuItemClicked(object sender, RoutedEventArgs args)
{
var item = (RuntimeMenuItem)sender;
-
- SelectionChanged?.Invoke (this, new SelectionChangedEventArgs<IRuntimeModel> (item.Model, Active));
+ args.Handled = true;
+ SelectionChanged?.Invoke(this, new SelectionChangedEventArgs<IRuntimeModel>(item.Model, Active));
}
- void FillSource (ItemCollection source, IEnumerable<IRuntimeModel> model)
+ void FillSource(ItemCollection source, IEnumerable<IRuntimeModel> model)
{
- foreach (var item in source.OfType<MenuItem> ()) {
- item.Click -= OnMenuItemClicked;
- foreach (var subItem in item.Items.OfType<MenuItem> ())
- subItem.Click -= OnMenuItemClicked;
- }
-
- source.Clear ();
-
- foreach (var item in model) {
- if (item.HasParent)
- continue;
+ Flatten(source.OfType<RuntimeMenuItem>()).ToList().ForEach(mi => mi.Click -= OnMenuItemClicked);
+ source.Clear();
+ RecursiveFillChildren(source, model);
+ }
+ void RecursiveFillChildren(ItemCollection source, IEnumerable<IRuntimeModel> children)
+ {
+ foreach (var item in children)
+ {
if (item.IsSeparator)
- source.Add (new Separator { UseLayoutRounding = true, });
- else {
- var menuItem = new RuntimeMenuItem (item);
+ {
+ source.Add(new Separator { UseLayoutRounding = true, });
+ }
+ else
+ {
+ var menuItem = new RuntimeMenuItem(item);
menuItem.Click += OnMenuItemClicked;
- foreach (var child in item.Children) {
- var childMenuItem = new RuntimeMenuItem (item);
- childMenuItem.Click += OnMenuItemClicked;
- menuItem.Items.Add (childMenuItem);
- }
- source.Add (menuItem);
+ source.Add(menuItem);
+ RecursiveFillChildren(menuItem.Items, item.Children);
}
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionTarget.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionTarget.cs
index b743fb60aa..c5917d9ea3 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionTarget.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ExecutionTarget.cs
@@ -27,6 +27,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using MonoDevelop.Projects;
namespace MonoDevelop.Core.Execution
{
@@ -203,4 +204,36 @@ namespace MonoDevelop.Core.Execution
#endregion
}
+
+ public class MultiProjectExecutionTarget : ExecutionTarget
+ {
+ //string id;
+
+ public override string Id {
+ get {
+ return "multiple-projects-5ce70911-0a07-4da6-ad3d-cc7a293f6656";
+ }
+ }
+
+ public override string Name { get; } = GettextCatalog.GetString ("Multiple");
+
+ Dictionary<SolutionItem, ExecutionTarget> list = new Dictionary<SolutionItem, ExecutionTarget> ();
+
+ public void SetExecutionTarget (SolutionItem project, ExecutionTarget target)
+ {
+ if (target == null)
+ list.Remove (project);
+ else
+ list [project] = target;
+ //id = string.Join ("/", list.Select (p => p.Value.Id).OrderBy (id => id));
+ }
+
+ public ExecutionTarget GetTarget(SolutionItem project)
+ {
+ ExecutionTarget target;
+ if (list.TryGetValue (project, out target))
+ return target;
+ return null;
+ }
+ }
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MultiItemSolutionRunConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MultiItemSolutionRunConfiguration.cs
index 99b88483df..bcc66705aa 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MultiItemSolutionRunConfiguration.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MultiItemSolutionRunConfiguration.cs
@@ -25,17 +25,195 @@
// THE SOFTWARE.
using System;
using System.Collections.Generic;
+using MonoDevelop.Core.Execution;
+using MonoDevelop.Core.Serialization;
+using System.Linq;
+using System.Text;
+using MonoDevelop.Core;
namespace MonoDevelop.Projects
{
- class MultiItemSolutionRunConfiguration: SolutionRunConfiguration
+ public sealed class MultiItemSolutionRunConfiguration : SolutionRunConfiguration
{
- public MultiItemSolutionRunConfiguration (string id, string name): base (id, name)
+ internal MultiItemSolutionRunConfiguration ()
{
- Items = new List<SolutionItem> ();
+ Items = new StartupItemCollection ();
+ }
+
+ public MultiItemSolutionRunConfiguration (string id, string name) : base (id, name)
+ {
+ Items = new StartupItemCollection ();
+ }
+
+ public MultiItemSolutionRunConfiguration (MultiItemSolutionRunConfiguration other, string newName = null) : base (newName ?? other.Id, newName ?? other.Name)
+ {
+ Items = new StartupItemCollection ();
+ Items.AddRange (other.Items.Select (it => new StartupItem (it.SolutionItem, it.RunConfiguration)));
+ }
+
+ public void CopyFrom (MultiItemSolutionRunConfiguration other)
+ {
+ Items.Clear ();
+ Items.AddRange (other.Items.Select (it => new StartupItem (it.SolutionItem, it.RunConfiguration)));
+ OnRunConfigurationsChanged ();
+ }
+
+ public StartupItemCollection Items { get; }
+
+ [ItemProperty ("Items")]
+ [ItemProperty ("StartupItem", ValueType = typeof (StartupItem), Scope = "*")]
+ StartupItem [] ItemArray {
+ get {
+ return Items.ToArray ();
+ }
+ set {
+ Items.Clear ();
+ Items.AddRange (value);
+ }
+ }
+
+ internal void ReplaceItem (SolutionItem oldItem, SolutionItem newItem)
+ {
+ foreach (var si in Items)
+ if (si.SolutionItem == oldItem)
+ si.SolutionItem = newItem;
+ }
+
+ internal void RemoveItem (SolutionItem item)
+ {
+ var i = Items.FindIndex (si => si.SolutionItem == item);
+ if (i != -1)
+ Items.RemoveAt (i);
+ }
+
+ internal void OnRunConfigurationsChanged ()
+ {
+ ParentSolution?.NotifyRunConfigurationsChanged ();
+ }
+
+ internal void ResolveObjects (Solution sol)
+ {
+ foreach (var it in Items)
+ it.ResolveObjects (sol);
+ }
+
+ public override string Summary {
+ get {
+ if (Items.Count == 0)
+ return GettextCatalog.GetString ("No projects selected to run");
+ var sb = new StringBuilder ();
+ foreach (var it in Items) {
+ if (sb.Length > 0)
+ sb.Append (", ");
+ sb.Append (it.SolutionItem.Name).Append (" (").Append (it.RunConfiguration.Name).Append (")");
+ }
+ return sb.ToString ();
+ }
}
- public List<SolutionItem> Items { get; set; }
- }
}
+ public sealed class StartupItem
+ {
+ StartupItem ()
+ {
+ }
+
+ public StartupItem (SolutionItem item, SolutionItemRunConfiguration configuration)
+ {
+ SolutionItem = item;
+ RunConfiguration = configuration;
+ }
+
+ string itemId;
+ string configurationId;
+
+ [ItemProperty]
+ string ItemId {
+ get { return itemId ?? SolutionItem?.ItemId; }
+ set { itemId = value; }
+ }
+
+ [ItemProperty]
+ string ConfigurationId {
+ get { return configurationId ?? RunConfiguration?.Id; }
+ set { configurationId = value; }
+ }
+
+ internal void ResolveObjects (Solution sol)
+ {
+ if (ItemId != null) {
+ SolutionItem = sol.GetSolutionItem (ItemId) as SolutionItem;
+ if (SolutionItem != null && ConfigurationId != null)
+ RunConfiguration = SolutionItem.GetRunConfigurations ().FirstOrDefault (c => c.Id == ConfigurationId);
+ ItemId = null;
+ ConfigurationId = null;
+ }
+ }
+
+ public SolutionItem SolutionItem { get; internal set; }
+ public SolutionItemRunConfiguration RunConfiguration { get; internal set; }
+ }
+
+ public sealed class MultiItemSolutionRunConfigurationCollection : ItemCollection<MultiItemSolutionRunConfiguration>
+ {
+ Solution parentSolution;
+
+ public MultiItemSolutionRunConfigurationCollection ()
+ {
+ }
+
+ internal MultiItemSolutionRunConfigurationCollection (Solution parentSolution)
+ {
+ this.parentSolution = parentSolution;
+ }
+
+ protected override void OnItemsAdded (IEnumerable<MultiItemSolutionRunConfiguration> items)
+ {
+ if (parentSolution != null) {
+ foreach (var conf in items) {
+ conf.ParentSolution = parentSolution;
+ conf.ResolveObjects (parentSolution);
+ }
+ }
+ base.OnItemsAdded (items);
+ parentSolution.OnRunConfigurationsAdded (items);
+ }
+
+ protected override void OnItemsRemoved (IEnumerable<MultiItemSolutionRunConfiguration> items)
+ {
+ if (parentSolution != null) {
+ foreach (var conf in items)
+ conf.ParentSolution = null;
+ }
+ base.OnItemsRemoved (items);
+ parentSolution.OnRunConfigurationRemoved (items);
+ }
+ }
+
+ public sealed class StartupItemCollection : ItemCollection<StartupItem>
+ {
+ MultiItemSolutionRunConfiguration parent;
+
+ public StartupItemCollection ()
+ {
+ }
+
+ internal StartupItemCollection (MultiItemSolutionRunConfiguration parent)
+ {
+ this.parent = parent;
+ }
+
+ protected override void OnItemsAdded (IEnumerable<StartupItem> items)
+ {
+ base.OnItemsAdded (items);
+ parent?.OnRunConfigurationsChanged ();
+ }
+
+ protected override void OnItemsRemoved (IEnumerable<StartupItem> items)
+ {
+ base.OnItemsRemoved (items);
+ parent?.OnRunConfigurationsChanged ();
+ }
+ }}
+
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs
index b04eac04cc..0f58656485 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs
@@ -56,8 +56,10 @@ namespace MonoDevelop.Projects
ReadOnlyCollection<SolutionItem> solutionItems;
SolutionConfigurationCollection configurations;
- SolutionRunConfigurationCollection runConfigurations;
+ MultiItemSolutionRunConfigurationCollection runConfigurations;
+
MultiItemSolutionRunConfiguration multiStartupConfig = new MultiItemSolutionRunConfiguration (MultiStartupConfigId, "Multi-Startup");
+
const string MultiStartupConfigId = "MonoDevelop.Projects.MultiStartup";
MSBuildEngineManager msbuildEngineManager = new MSBuildEngineManager ();
@@ -80,7 +82,7 @@ namespace MonoDevelop.Projects
loadingFromConstructor = loading;
Counters.SolutionsLoaded++;
configurations = new SolutionConfigurationCollection (this);
- runConfigurations = new SolutionRunConfigurationCollection (this);
+ runConfigurations = new MultiItemSolutionRunConfigurationCollection (this);
format = MSBuildFileFormat.DefaultFormat;
Initialize (this);
}
@@ -188,29 +190,30 @@ namespace MonoDevelop.Projects
}
}
+ [Obsolete ("Use StartupConfiguration")]
public bool SingleStartup {
get {
return StartupConfiguration is SingleItemSolutionRunConfiguration;
}
set {
- if (value == SingleStartup)
- return;
- if (value) {
- StartupItem = multiStartupConfig.Items.FirstOrDefault () ?? GetRunConfigurations ().OfType<SingleItemSolutionRunConfiguration> ().Select (i => i.Item).FirstOrDefault ();
- } else {
- if (!runConfigurations.Contains (multiStartupConfig))
- runConfigurations.Add (multiStartupConfig);
- StartupConfiguration = multiStartupConfig;
- }
}
}
+ [Obsolete ("Use StartupConfiguration or MultiStartupRunConfigurations")]
public List<SolutionItem> MultiStartupItems {
get {
- return multiStartupConfig.Items;
+ var sc = StartupConfiguration as MultiItemSolutionRunConfiguration;
+ if (sc != null)
+ return sc.Items.Select (it => it.SolutionItem).ToList ();
+ else
+ return new List<SolutionItem> ();
}
}
+ public MultiItemSolutionRunConfigurationCollection MultiStartupRunConfigurations {
+ get { return runConfigurations; }
+ }
+
/// <summary>
/// Gets the author information for this solution. If no specific information is set for this solution, it
/// will return the author defined in the global settings.
@@ -244,6 +247,12 @@ namespace MonoDevelop.Projects
bool startupConfigSet = false;
+ var mconfigs = UserProperties.GetValue<MultiItemSolutionRunConfiguration []> ("MultiItemStartupConfigurations");
+ if (mconfigs != null) {
+ MultiStartupRunConfigurations.Clear ();
+ MultiStartupRunConfigurations.AddRange (mconfigs);
+ }
+
var sitem = UserProperties.GetValue<string> ("StartupItem");
if (!string.IsNullOrEmpty (sitem)) {
// Old StartupItem property. Find the corresponding SingleItemSolutionRunConfiguration instance and get rid of the property.
@@ -259,14 +268,16 @@ namespace MonoDevelop.Projects
var sitems = UserProperties.GetValue<string []> ("StartupItems");
if (sitems != null && sitems.Length > 0) {
// Old StartupItems property. Create a corresponding MultiItemSolutionRunConfiguration.
+ UserProperties.RemoveValue ("StartupItems");
var multiStartupItems = sitems.Select (p => (string)GetAbsoluteChildPath (p)).Select (FindSolutionItem).Where (i => i != null);
- multiStartupConfig.Items.Clear ();
- multiStartupConfig.Items.AddRange (multiStartupItems.ToArray ());
- runConfigurations.Add (multiStartupConfig);
+ var msc = new MultiItemSolutionRunConfiguration ("Multi-Startup", "Multi-Startup");
+ foreach (var si in multiStartupItems)
+ msc.Items.Add (new StartupItem (si, si.GetDefaultRunConfiguration ()));
+ runConfigurations.Add (msc);
if (!startupConfigSet) {
// If the config has not been set by StartupItem it means that this is an old solution that had been configured with multiple startup.
// Select the multi-startup config in this case.
- StartupConfiguration = multiStartupConfig;
+ StartupConfiguration = msc;
startupConfigSet = true;
}
}
@@ -289,13 +300,9 @@ namespace MonoDevelop.Projects
protected override async Task OnSaveUserProperties ()
{
UserProperties.SetValue ("StartupConfiguration", (string)StartupConfiguration?.Id);
-
+ UserProperties.SetValue ("MultiItemStartupConfigurations", MultiStartupRunConfigurations.ToArray ());
+
// Save the multi-startup configuration only if it is the one that's selected
- var msc = StartupConfiguration as MultiItemSolutionRunConfiguration;
- if (msc != null)
- UserProperties.SetValue ("StartupItems", msc.Items.Select (p => (string)GetRelativeChildPath (p.FileName)).ToArray ());
- else
- UserProperties.RemoveValue ("StartupItems");
CollectItemProperties (UserProperties, RootFolder, "MonoDevelop.Ide.ItemProperties");
await base.OnSaveUserProperties ();
@@ -439,7 +446,7 @@ namespace MonoDevelop.Projects
public ReadOnlyCollection<Project> GetAllProjectsWithTopologicalSort (ConfigurationSelector configuration)
{
return RootFolder.GetAllProjectsWithTopologicalSort (configuration);
- }
+ }
public override IEnumerable<Project> GetProjectsContainingFile (FilePath fileName)
{
@@ -818,8 +825,13 @@ namespace MonoDevelop.Projects
var msc = runConfiguration as MultiItemSolutionRunConfiguration;
if (msc != null) {
- foreach (SolutionItem it in msc.Items) {
- if (it.CanExecute (context, configuration))
+ var multiProject = context.ExecutionTarget as MultiProjectExecutionTarget;
+ foreach (StartupItem it in msc.Items) {
+ var localContext = context;
+ //Set project specific execution target to context if exists
+ if (multiProject?.GetTarget (it.SolutionItem) != null)
+ localContext = new ExecutionContext (context.ExecutionHandler, context.ExternalConsoleFactory, multiProject?.GetTarget (it.SolutionItem));
+ if (it.SolutionItem.CanExecute (localContext, configuration, it.RunConfiguration))
return true;
}
return false;
@@ -840,16 +852,18 @@ namespace MonoDevelop.Projects
var monitors = new List<AggregatedProgressMonitor> ();
monitor.BeginTask ("Executing projects", 1);
- var secondaryContext = new ExecutionContext (Runtime.ProcessService.DefaultExecutionMode, context.ConsoleFactory, null);
-
- foreach (SolutionItem it in msc.Items) {
- if (!it.CanExecute (context, configuration))
+ var multiProject = context.ExecutionTarget as MultiProjectExecutionTarget;
+ foreach (StartupItem it in msc.Items) {
+ var localContext = context;
+ //Set project specific execution target to context if exists
+ if (multiProject?.GetTarget (it.SolutionItem) != null)
+ localContext = new ExecutionContext (context.ExecutionHandler, context.ConsoleFactory, multiProject?.GetTarget (it.SolutionItem));
+ if (!it.SolutionItem.CanExecute (localContext, configuration, it.RunConfiguration))
continue;
AggregatedProgressMonitor mon = new AggregatedProgressMonitor ();
mon.AddFollowerMonitor (monitor, MonitorAction.ReportError | MonitorAction.ReportWarning | MonitorAction.FollowerCancel);
monitors.Add (mon);
- tasks.Add (it.Execute (mon, context, configuration));
- context = secondaryContext;
+ tasks.Add (it.SolutionItem.Execute (mon, localContext, configuration, it.RunConfiguration));
}
try {
await Task.WhenAll (tasks);
@@ -915,10 +929,10 @@ namespace MonoDevelop.Projects
bool OnGetSupportsFormat (MSBuildFileFormat format)
{
return GetAllItems<SolutionItem> ().All (p => p.SupportsFormat (format));
- }
-
+ }
+
protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles)
- {
+ {
List<FilePath> files = base.OnGetItemFiles (includeReferencedFiles).ToList ();
if (includeReferencedFiles) {
foreach (SolutionItem item in GetAllItems<SolutionItem> ())
@@ -967,13 +981,12 @@ namespace MonoDevelop.Projects
// Reuse the configuration information of the replaced item
foreach (SolutionConfiguration conf in Configurations)
conf.ReplaceItem ((SolutionItem)replacedItem, eitem);
+
if (StartupItem == replacedItem)
StartupItem = eitem;
- else {
- int i = MultiStartupItems.IndexOf ((SolutionItem)replacedItem);
- if (i != -1)
- MultiStartupItems [i] = eitem;
- }
+
+ foreach (var sc in MultiStartupRunConfigurations.OfType<MultiItemSolutionRunConfiguration> ())
+ sc.ReplaceItem ((SolutionItem)replacedItem, eitem);
}
}
}
@@ -1009,8 +1022,9 @@ namespace MonoDevelop.Projects
if (StartupItem == item)
StartupItem = null;
- else
- MultiStartupItems.Remove (item);
+
+ foreach (var sc in MultiStartupRunConfigurations)
+ sc.RemoveItem (item);
}
// Update the file name because the file format may have changed
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionRunConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionRunConfiguration.cs
index 1e0d693b37..7780c20f4b 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionRunConfiguration.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionRunConfiguration.cs
@@ -24,13 +24,22 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
+using MonoDevelop.Core.Serialization;
+
namespace MonoDevelop.Projects
{
public class SolutionRunConfiguration: RunConfiguration
{
+ [ItemProperty ("Id")]
string id;
+
+ [ItemProperty ("Name")]
string name;
+ internal SolutionRunConfiguration ()
+ {
+ }
+
public SolutionRunConfiguration (string id)
{
this.name = this.id = id;
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml
index ce11430353..4a059c141a 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/ItemOptionPanels.addin.xml
@@ -80,16 +80,16 @@
<Section id="Run" _label="Run">
<Section id="General" _label="Configurations">
<Condition id="ItemType" value="Project">
-<!-- <Panel id = "RunOptionsPanel" _label = "Run" fill = "true" class = "MonoDevelop.Ide.Projects.OptionPanels.RunOptionsPanel"/>-->
<Panel id = "RunConfigurationsPanel" _label = "Run Configurations" fill = "true" class = "MonoDevelop.Ide.Projects.OptionPanels.RunConfigurationsPanel"/>
</Condition>
+ <Condition id="ItemType" value="Solution">
+ <!--<Section id = "StartupOptionsPanel" _label = "Startup Project" fill = "true" class = "MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanel"/>-->
+ <Panel id = "SolutionRunConfigurationsPanel" _label = "Run Configurations" fill = "true" class = "MonoDevelop.Ide.Projects.OptionPanels.SolutionRunConfigurationsPanel" icon="md-prefs-startup-project" />
+ </Condition>
+ <Condition id="ItemType" value="SolutionItem">
+ <!-- <Section id = "CustomCommands" _label = "Custom Commands" fill = "true" class = "MonoDevelop.Ide.Projects.OptionPanels.ExecutionCustomCommandPanel" />-->
+ </Condition>
</Section>
- <Condition id="ItemType" value="Solution">
- <Section id = "StartupOptionsPanel" _label = "Startup Project" fill = "true" class = "MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanel" icon="md-prefs-startup-project" />
- </Condition>
- <Condition id="ItemType" value="SolutionItem">
-<!-- <Section id = "CustomCommands" _label = "Custom Commands" fill = "true" class = "MonoDevelop.Ide.Projects.OptionPanels.ExecutionCustomCommandPanel" />-->
- </Condition>
</Section>
<Section id="SourceCode" _label="Source Code">
<Section id="DotNetNamingPolicies" _label=".NET Naming Policies" icon="md-prefs-dotnet-naming-policies">
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs
index bbbc46bd93..6071ec1e50 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/ConfigurationMerger.cs
@@ -54,7 +54,7 @@ namespace MonoDevelop.Components.MainToolbar
/// <summary>
/// Load configuration information for a solution
/// </summary>
- public void Load (Solution sol)
+ public void Load (Solution sol, SolutionItem project, SolutionItemRunConfiguration runConfig)
{
currentSolutionConfigurations.Clear ();
currentTargetPartitions.Clear ();
@@ -63,9 +63,6 @@ namespace MonoDevelop.Components.MainToolbar
if (sol == null)
return;
- var project = sol.StartupItem;
- var runConfig = (sol.StartupConfiguration as SingleItemSolutionRunConfiguration)?.RunConfiguration;
-
// Create a set of configuration partitions. Each partition will contain configurations
// which are implicitly selected when selecting an execution target. For example, in
// an iOS project we would have two partitions:
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
index 0a041a4baf..a0ad42f0b4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
@@ -518,9 +518,6 @@ namespace MonoDevelop.Components.MainToolbar
runtimeModel = value;
runtimeStore.Clear ();
foreach (var item in value) {
- if (item.HasParent)
- continue;
-
var iter = runtimeStore.AppendValues (item);
foreach (var subitem in item.Children)
runtimeStore.AppendValues (iter, subitem);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
index cbfd4b690b..3007789dc6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
@@ -59,11 +59,11 @@ namespace MonoDevelop.Components.MainToolbar
set { searchForMembers.Value = value; }
}
- ConfigurationMerger configurationMerger = new ConfigurationMerger ();
+ Dictionary<SolutionItem, ConfigurationMerger> configurationMergers = new Dictionary<SolutionItem, ConfigurationMerger> ();
int ignoreConfigurationChangedCount, ignoreRuntimeChangedCount;
Solution currentSolution;
bool settingGlobalConfig;
- SolutionItem currentStartupProject;
+ Tuple<SolutionItem, SolutionItemRunConfiguration> [] startupProjects = new Tuple<SolutionItem, SolutionItemRunConfiguration> [0];
EventHandler executionTargetsChanged;
public MainToolbarController (IMainToolbarView toolbarView)
@@ -141,7 +141,13 @@ namespace MonoDevelop.Components.MainToolbar
if (settingGlobalConfig)
return;
- configurationMerger.Load (currentSolution);
+ TrackStartupProject ();
+ configurationMergers = new Dictionary<SolutionItem, ConfigurationMerger> ();
+ foreach (var project in startupProjects) {
+ var configurationMerger = new ConfigurationMerger ();
+ configurationMerger.Load (currentSolution, project.Item1, project.Item2);
+ configurationMergers [project.Item1] = configurationMerger;
+ }
ignoreConfigurationChangedCount++;
try {
@@ -152,11 +158,13 @@ namespace MonoDevelop.Components.MainToolbar
ToolbarView.RunConfigurationVisible = false;
return;
}
-
- ToolbarView.ConfigurationModel = configurationMerger
- .SolutionConfigurations
- .Distinct ()
- .Select (conf => new ConfigurationModel (conf));
+ if (configurationMergers.Count == 1)
+ ToolbarView.ConfigurationModel = configurationMergers.First ().Value.SolutionConfigurations
+ .Distinct ()
+ .Select (conf => new ConfigurationModel (conf));
+ else
+ ToolbarView.ConfigurationModel = currentSolution?.Configurations.OfType<SolutionConfiguration> ()
+ .Select (conf => new ConfigurationModel (conf.Id)) ?? new ConfigurationModel [0];
if (currentSolution != null)
ToolbarView.RunConfigurationModel = currentSolution.GetRunConfigurations ().Select (rc => new RunConfigurationModel (rc)).ToArray ();
@@ -179,65 +187,45 @@ namespace MonoDevelop.Components.MainToolbar
ignoreRuntimeChangedCount++;
try {
ToolbarView.RuntimeModel = Enumerable.Empty<IRuntimeModel> ();
- if (!IdeApp.Workspace.IsOpen || currentSolution == null || !currentSolution.SingleStartup || currentSolution.StartupItem == null)
- return;
-
- // Check that the current startup project is enabled for the current configuration
- var solConf = currentSolution.GetConfiguration (IdeApp.Workspace.ActiveConfiguration);
- if (solConf == null || !solConf.BuildEnabledForItem (currentSolution.StartupItem))
+ if (!IdeApp.Workspace.IsOpen || currentSolution == null)
return;
-
- ExecutionTarget previous = null;
+ var list = new List<RuntimeModel> ();
int runtimes = 0;
+ if (currentSolution.StartupConfiguration is MultiItemSolutionRunConfiguration) {
+ bool anyValid = false;
+ foreach (var startConf in ((MultiItemSolutionRunConfiguration)currentSolution.StartupConfiguration).Items) {
+ if (startConf?.SolutionItem == null)
+ continue;
- var list = new List<RuntimeModel> ();
- foreach (var target in configurationMerger.GetTargetsForConfiguration (IdeApp.Workspace.ActiveConfigurationId, true)) {
- if (target is ExecutionTargetGroup) {
- var devices = (ExecutionTargetGroup) target;
-
- if (previous != null)
- list.Add (new RuntimeModel (this, target: null));
-
- list.Add (new RuntimeModel (this, target));
- foreach (var device in devices) {
- if (device is ExecutionTargetGroup) {
- var versions = (ExecutionTargetGroup) device;
-
- if (versions.Count > 1) {
- var parent = new RuntimeModel (this, device) {
- IsIndented = true,
- };
- list.Add (parent);
-
- foreach (var version in versions) {
- list.Add (new RuntimeModel (this, version, parent));
- runtimes++;
- }
- } else {
- list.Add (new RuntimeModel (this, versions[0]) {
- IsIndented = true,
- });
- runtimes++;
- }
- } else {
- list.Add (new RuntimeModel (this, device) {
- IsIndented = true,
- });
- runtimes++;
- }
- }
- } else {
- if (previous is ExecutionTargetGroup) {
- list.Add (new RuntimeModel (this, target: null));
+ // Check that the current startup project is enabled for the current configuration
+ var solConf = currentSolution.GetConfiguration (IdeApp.Workspace.ActiveConfiguration);
+ if (solConf == null || !solConf.BuildEnabledForItem (startConf.SolutionItem))
+ continue;
+ anyValid = true;
+ var projectList = new List<RuntimeModel> ();
+ FillRuntimesForProject (projectList, startConf.SolutionItem, ref runtimes);
+ var parent = new RuntimeModel (this, startConf.SolutionItem.Name);
+ parent.HasChildren = true;
+ list.Add (parent);
+ foreach (var p in projectList) {
+ parent.AddChild (p);
}
-
- list.Add (new RuntimeModel (this, target));
- runtimes++;
}
+ if (!anyValid)
+ return;
+ } else {
+ var startConf = currentSolution.StartupConfiguration as SingleItemSolutionRunConfiguration;
+ if (startConf == null || startConf.Item == null)
+ return;
- previous = target;
+ // Check that the current startup project is enabled for the current configuration
+ var solConf = currentSolution.GetConfiguration (IdeApp.Workspace.ActiveConfiguration);
+ if (solConf == null || !solConf.BuildEnabledForItem (startConf.Item))
+ return;
+ FillRuntimesForProject (list, startConf.Item, ref runtimes);
}
+
var cmds = IdeApp.CommandService.CreateCommandEntrySet (TargetsMenuPath);
if (cmds.Count > 0) {
bool needsSeparator = runtimes > 0;
@@ -251,7 +239,7 @@ namespace MonoDevelop.Components.MainToolbar
var ci = IdeApp.CommandService.GetCommandInfo (cmd.Id, new CommandTargetRoute (lastCommandTarget));
if (ci.Visible) {
if (needsSeparator) {
- list.Add (new RuntimeModel (this, target: null));
+ list.Add (new RuntimeModel (this, displayText: null));
needsSeparator = false;
}
list.Add (new RuntimeModel (this, cmd));
@@ -268,6 +256,57 @@ namespace MonoDevelop.Components.MainToolbar
}
}
+ void FillRuntimesForProject (List<RuntimeModel> list, SolutionItem project, ref int runtimes)
+ {
+ ExecutionTarget previous = null;
+
+ foreach (var target in configurationMergers [project].GetTargetsForConfiguration (IdeApp.Workspace.ActiveConfigurationId, configurationMergers.Count < 2)) {
+ if (target is ExecutionTargetGroup) {
+ var devices = (ExecutionTargetGroup)target;
+
+ if (previous != null)
+ list.Add (new RuntimeModel (this, displayText: null));//Seperator
+
+ foreach (var device in devices) {
+ if (device is ExecutionTargetGroup) {
+ var versions = (ExecutionTargetGroup)device;
+
+ if (versions.Count > 1) {
+ var parent = new RuntimeModel (this, device, true, project) {
+ IsIndented = true,
+ };
+ list.Add (parent);
+
+ foreach (var version in versions) {
+ parent.AddChild (new RuntimeModel (this, version, false, project));
+ runtimes++;
+ }
+ } else {
+ list.Add (new RuntimeModel (this, versions [0], true, project) {
+ IsIndented = true,
+ });
+ runtimes++;
+ }
+ } else {
+ list.Add (new RuntimeModel (this, device, true, project) {
+ IsIndented = true,
+ });
+ runtimes++;
+ }
+ }
+ } else {
+ if (previous is ExecutionTargetGroup) {
+ list.Add (new RuntimeModel (this, displayText: null));//Seperator
+ }
+
+ list.Add (new RuntimeModel (this, target, true, project));
+ runtimes++;
+ }
+
+ previous = target;
+ }
+ }
+
void HandleRuntimeChanged (object sender, HandledEventArgs e)
{
if (ignoreRuntimeChangedCount == 0) {
@@ -278,6 +317,7 @@ namespace MonoDevelop.Components.MainToolbar
}
NotifyConfigurationChange ();
+ SelectActiveRuntime (runtime);
}
}
@@ -296,14 +336,18 @@ namespace MonoDevelop.Components.MainToolbar
void UpdateBuildConfiguration ()
{
var config = ToolbarView.ActiveConfiguration;
- if (config == null)
+ if (config == null || configurationMergers.Count == 0)
+ return;
+ if (configurationMergers.Count > 1) {
+ IdeApp.Workspace.ActiveConfigurationId = config.OriginalId;
return;
+ }
ExecutionTarget newTarget;
string fullConfig;
var runtime = (RuntimeModel)ToolbarView.ActiveRuntime;
- configurationMerger.ResolveConfiguration (config.OriginalId, runtime != null ? runtime.ExecutionTarget : null, out fullConfig, out newTarget);
+ configurationMergers.Values.First ().ResolveConfiguration (config.OriginalId, runtime != null ? runtime.ExecutionTarget : null, out fullConfig, out newTarget);
settingGlobalConfig = true;
try {
IdeApp.Workspace.ActiveExecutionTarget = newTarget;
@@ -321,7 +365,7 @@ namespace MonoDevelop.Components.MainToolbar
UpdateBuildConfiguration ();
FillRuntimes ();
- SelectActiveRuntime ();
+ SelectActiveRuntime (ToolbarView.ActiveRuntime as RuntimeModel);
}
void NotifyRunConfigurationChange ()
@@ -365,7 +409,12 @@ namespace MonoDevelop.Components.MainToolbar
void SelectActiveConfiguration ()
{
- string name = configurationMerger.GetUnresolvedConfiguration (IdeApp.Workspace.ActiveConfigurationId);
+ var allNames = configurationMergers.Values.Select (cm => cm.GetUnresolvedConfiguration (IdeApp.Workspace.ActiveConfigurationId)).Distinct ();
+ string name;
+ if (allNames.Count () == 1)
+ name = allNames.First ();
+ else
+ name = IdeApp.Workspace.ActiveConfigurationId;
ignoreConfigurationChangedCount++;
try {
@@ -393,79 +442,86 @@ namespace MonoDevelop.Components.MainToolbar
ignoreConfigurationChangedCount--;
}
- SelectActiveRuntime ();
+ SelectActiveRuntime (ToolbarView.ActiveRuntime as RuntimeModel);
}
- bool SelectActiveRuntime (ref bool selected, ref ExecutionTarget defaultTarget, ref int defaultIter)
+ IEnumerable<IRuntimeModel> AllRuntimes (IEnumerable<IRuntimeModel> runtimes)
{
- var runtimes = ToolbarView.RuntimeModel.Cast<RuntimeModel> ().ToList ();
- string lastRuntimeForProject = currentStartupProject?.UserProperties.GetValue<string> ("PreferredExecutionTarget", defaultValue: null);
- var activeTarget = IdeApp.Workspace.ActiveExecutionTarget;
- var activeTargetId = activeTarget != null ? activeTarget.Id : null;
+ foreach (var runtime in runtimes) {
+ yield return runtime;
+ foreach (var childRuntime in AllRuntimes (runtime.Children))
+ yield return childRuntime;
+ }
+ }
- for (int iter = 0; iter < runtimes.Count; ++iter) {
- var item = runtimes [iter];
+ RuntimeModel SelectActiveRuntime (SolutionItem project, RuntimeModel preferedRuntimeModel)
+ {
+ var runtimes = AllRuntimes (ToolbarView.RuntimeModel).Cast<RuntimeModel> ().ToList ();
+ string lastRuntimeForProject = project.UserProperties.GetValue<string> ("PreferredExecutionTarget", defaultValue: null);
+ var activeTarget = preferedRuntimeModel?.Project == project ? preferedRuntimeModel.ExecutionTarget : null;
+ var multiProjectExecutionTarget = activeTarget as MultiProjectExecutionTarget;
+ if (multiProjectExecutionTarget != null) {
+ activeTarget = multiProjectExecutionTarget.GetTarget (project);
+ }
+ var activeTargetId = activeTarget?.Id;
+ RuntimeModel defaultRuntime = null;
+
+ foreach (var item in runtimes) {
using (var model = item.GetMutableModel ()) {
if (!model.Enabled)
continue;
}
var target = item.ExecutionTarget;
- if (target == null || !target.Enabled)
+ if (target == null || !target.Enabled || item.Project != project)
continue;
if (target is ExecutionTargetGroup)
if (item.HasChildren)
continue;
- if (defaultTarget == null || lastRuntimeForProject == target.Id) {
- defaultTarget = target;
- defaultIter = iter;
+ if (defaultRuntime == null || lastRuntimeForProject == target.Id) {
+ defaultRuntime = item;
}
if (target.Id == activeTargetId) {
- IdeApp.Workspace.ActiveExecutionTarget = target;
- ToolbarView.ActiveRuntime = ToolbarView.RuntimeModel.ElementAt (iter);
- UpdateBuildConfiguration ();
- selected = true;
- return true;
+ project.UserProperties.SetValue ("PreferredExecutionTarget", target.Id);
+ return item;
}
if (target.Equals (activeTarget)) {
- ToolbarView.ActiveRuntime = ToolbarView.RuntimeModel.ElementAt (iter);
- UpdateBuildConfiguration ();
- selected = true;
+ defaultRuntime = item;
}
}
-
- return false;
+ if (defaultRuntime?.ExecutionTarget?.Id != null)
+ project.UserProperties.SetValue("PreferredExecutionTarget", defaultRuntime.ExecutionTarget.Id);
+ return defaultRuntime;
}
- void SelectActiveRuntime ()
+ void SelectActiveRuntime (RuntimeModel preferedRuntimeModel)
{
ignoreRuntimeChangedCount++;
try {
if (ToolbarView.RuntimeModel.Any ()) {
- ExecutionTarget defaultTarget = null;
- bool selected = false;
- int defaultIter = 0;
-
- if (!SelectActiveRuntime (ref selected, ref defaultTarget, ref defaultIter) && !selected) {
- if (defaultTarget != null) {
- IdeApp.Workspace.ActiveExecutionTarget = defaultTarget;
- ToolbarView.ActiveRuntime = ToolbarView.RuntimeModel.ElementAt (defaultIter);
+ if (startupProjects.Length > 1) {
+ var multiProjectTarget = new MultiProjectExecutionTarget ();
+ var multipleRuntime = new RuntimeModel (this, multiProjectTarget, false, null);
+ foreach (var startupProject in startupProjects) {
+ var runtimeModel = SelectActiveRuntime (startupProject.Item1, preferedRuntimeModel);
+ multiProjectTarget.SetExecutionTarget (startupProject.Item1, runtimeModel.ExecutionTarget);
+ multipleRuntime.AddChild (runtimeModel);
}
+ ToolbarView.ActiveRuntime = multipleRuntime;
+ IdeApp.Workspace.ActiveExecutionTarget = multipleRuntime.ExecutionTarget;
+ } else if (startupProjects.Length == 1) {
+ var runtimeModel = SelectActiveRuntime (startupProjects.First ().Item1, preferedRuntimeModel);
+ ToolbarView.ActiveRuntime = runtimeModel;
+ IdeApp.Workspace.ActiveExecutionTarget = runtimeModel?.ExecutionTarget;
UpdateBuildConfiguration ();
- }
-
- if (currentStartupProject == null) {
- return;
- }
-
- var runtime = (RuntimeModel)ToolbarView.ActiveRuntime;
- if (runtime != null && runtime.Command == null) {
- currentStartupProject.UserProperties.SetValue<string> ("PreferredExecutionTarget", runtime.TargetId);
+ } else {
+ ToolbarView.ActiveRuntime = null;
+ IdeApp.Workspace.ActiveExecutionTarget = null;
}
}
} finally {
@@ -511,18 +567,28 @@ namespace MonoDevelop.Components.MainToolbar
void TrackStartupProject ()
{
- if (currentStartupProject != null && ((currentSolution != null && currentStartupProject != currentSolution.StartupItem) || currentSolution == null)) {
- currentStartupProject.ExecutionTargetsChanged -= executionTargetsChanged;
+ Tuple<SolutionItem, SolutionItemRunConfiguration> [] projects;
+ if (currentSolution?.StartupConfiguration is MultiItemSolutionRunConfiguration) {
+ var multiRunConfigs = (MultiItemSolutionRunConfiguration)currentSolution.StartupConfiguration;
+ projects = multiRunConfigs.Items.Select (rc => new Tuple<SolutionItem, SolutionItemRunConfiguration> (
+ rc.SolutionItem,
+ rc.RunConfiguration
+ )).ToArray ();
+ } else if (currentSolution?.StartupConfiguration is SingleItemSolutionRunConfiguration) {
+ var singleRunConfig = (SingleItemSolutionRunConfiguration)currentSolution.StartupConfiguration;
+ projects = new Tuple<SolutionItem, SolutionItemRunConfiguration> []{ new Tuple<SolutionItem, SolutionItemRunConfiguration> (
+ singleRunConfig.Item, singleRunConfig.RunConfiguration)};
+ } else {
+ projects = new Tuple<SolutionItem, SolutionItemRunConfiguration> [0];
}
-
- if (currentSolution != null) {
- currentStartupProject = currentSolution.StartupItem;
- if (currentStartupProject != null) {
- currentStartupProject.ExecutionTargetsChanged += executionTargetsChanged;
+ if (!startupProjects.SequenceEqual (projects)) {
+ foreach (var item in startupProjects) {
+ item.Item1.ExecutionTargetsChanged -= executionTargetsChanged;
}
+ foreach (var item in projects)
+ item.Item1.ExecutionTargetsChanged += executionTargetsChanged;
+ startupProjects = projects;
}
- else
- currentStartupProject = null;
}
bool updatingCombos;
@@ -842,31 +908,31 @@ namespace MonoDevelop.Components.MainToolbar
List<IRuntimeModel> children = new List<IRuntimeModel> ();
public object Command { get; private set; }
public ExecutionTarget ExecutionTarget { get; private set; }
+ string DisplayText = null;
+ bool fullText;
RuntimeModel (MainToolbarController controller)
{
Controller = controller;
}
- public RuntimeModel (MainToolbarController controller, ActionCommand command) : this (controller)
+ public RuntimeModel (MainToolbarController controller, string displayText) : this (controller)
{
- Command = command.Id;
+ DisplayText = displayText;
}
- public RuntimeModel (MainToolbarController controller, ExecutionTarget target) : this (controller)
+ public RuntimeModel (MainToolbarController controller, ActionCommand command) : this (controller)
{
- ExecutionTarget = target;
+ Command = command.Id;
}
- public RuntimeModel (MainToolbarController controller, ExecutionTarget target, RuntimeModel parent) : this (controller, target)
+ public RuntimeModel (MainToolbarController controller, ExecutionTarget target, bool fullText, SolutionItem project) : this (controller)
{
- if (parent == null)
- HasParent = false;
- else {
- HasParent = true;
- parent.HasChildren = true;
- parent.AddChild (this);
- }
+ if (target == null)
+ throw new ArgumentNullException (nameof (target));
+ ExecutionTarget = target;
+ this.fullText = fullText;
+ Project = project;
}
public void AddChild (IRuntimeModel child)
@@ -884,16 +950,11 @@ namespace MonoDevelop.Components.MainToolbar
public bool HasChildren {
get;
- private set;
- }
-
- public bool HasParent {
- get;
set;
}
public bool IsSeparator {
- get { return Command == null && ExecutionTarget == null; }
+ get { return Command == null && ExecutionTarget == null && DisplayText == null; }
}
public bool IsIndented {
@@ -916,14 +977,27 @@ namespace MonoDevelop.Components.MainToolbar
}
}
+ public SolutionItem Project { get; }
+
public IRuntimeMutableModel GetMutableModel ()
{
- return Command != null ? new RuntimeMutableModel (Controller, Command) : new RuntimeMutableModel (ExecutionTarget, HasParent);
+ if (Command != null)
+ return new RuntimeMutableModel (Controller, Command);
+ else if (ExecutionTarget != null)
+ return new RuntimeMutableModel (ExecutionTarget, fullText);
+ else
+ return new RuntimeMutableModel (DisplayText);
}
}
class RuntimeMutableModel : IRuntimeMutableModel
{
+ public RuntimeMutableModel(string text)
+ {
+ Enabled = Visible = true;
+ DisplayString = FullDisplayString = text;
+ }
+
public RuntimeMutableModel (MainToolbarController controller, object command)
{
var ci = IdeApp.CommandService.GetCommandInfo (command, new CommandTargetRoute (controller.lastCommandTarget));
@@ -932,7 +1006,7 @@ namespace MonoDevelop.Components.MainToolbar
DisplayString = FullDisplayString = RemoveUnderline (ci.Text);
}
- public RuntimeMutableModel (ExecutionTarget target, bool hasParent)
+ public RuntimeMutableModel (ExecutionTarget target, bool fullName)
{
Enabled = !(target is ExecutionTargetGroup);
Visible = true;
@@ -940,7 +1014,7 @@ namespace MonoDevelop.Components.MainToolbar
DisplayString = FullDisplayString = string.Empty;
else {
FullDisplayString = target.FullName;
- DisplayString = !hasParent ? target.FullName : target.Name;
+ DisplayString = fullName ? target.FullName : target.Name;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs
index 7dd60d4b64..280e33fdac 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs
@@ -84,13 +84,10 @@ namespace MonoDevelop.Components.MainToolbar
bool Notable { get; }
/// <summary>
- /// Gets a value indicating whether this instance has a parent.
+ /// Gets the project to which this runtime belongs.
/// </summary>
- /// <remarks>
- /// If a menu item has a parent, it means it is in this list just for easier traversal and it should not be displayed.
- /// </remarks>
- /// <value><c>true</c> if this instance has a parent; otherwise, <c>false</c>.</value>
- bool HasParent { get; }
+ /// <value>The project.</value>
+ MonoDevelop.Projects.SolutionItem Project { get; }
/// <summary>
/// Gets the runtime combo item model.
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
index eacc488c97..128eb40283 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
@@ -300,7 +300,7 @@ namespace MonoDevelop.Ide.Commands
protected override void Update (CommandInfo info)
{
IBuildTarget buildTarget = IdeApp.ProjectOperations.CurrentSelectedBuildTarget;
- info.Enabled = ((buildTarget != null) && (!(buildTarget is Workspace)) && IdeApp.ProjectOperations.CanExecute (buildTarget) && IdeApp.ProjectOperations.CurrentRunOperation.IsCompleted);
+ info.Enabled = ((buildTarget != null) && (!(buildTarget is Workspace)) && IdeApp.ProjectOperations.CanExecute (buildTarget));
}
protected override void Run ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs
index 4852a7f502..c06160f4a7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ClassPad/SolutionNodeBuilder.cs
@@ -116,6 +116,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
Solution solution = (Solution) dataObject;
solution.NameChanged += OnCombineRenamed;
solution.StartupItemChanged += OnStartupChanged;
+ solution.RunConfigurationsChanged += OnStartupChanged;
+ solution.StartupConfigurationChanged += OnStartupChanged;
}
public override void OnNodeRemoved (object dataObject)
@@ -123,6 +125,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ClassPad
Solution solution = (Solution) dataObject;
solution.NameChanged -= OnCombineRenamed;
solution.StartupItemChanged -= OnStartupChanged;
+ solution.RunConfigurationsChanged -= OnStartupChanged;
+ solution.StartupConfigurationChanged -= OnStartupChanged;
}
void OnStartupChanged (object sender, EventArgs args)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
index 275e555542..f0e3b25b4c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
@@ -123,9 +123,10 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
}
nodeInfo.Icon = Context.GetIcon (p.StockIcon);
- if (p.ParentSolution != null && p.ParentSolution.SingleStartup && p.ParentSolution.StartupItem == p)
+ var sc = p.ParentSolution?.StartupConfiguration;
+ if (sc != null && IsStartupProject (p, sc)) {
nodeInfo.Label = "<b>" + escapedProjectName + "</b>";
- else
+ } else
nodeInfo.Label = escapedProjectName;
// Gray out the project name if it is not selected in the current build configuration
@@ -146,6 +147,15 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
}
}
+ bool IsStartupProject (Project p, SolutionRunConfiguration sc)
+ {
+ var single = sc as SingleItemSolutionRunConfiguration;
+ if (single != null)
+ return single.Item == p;
+ var multi = sc as MultiItemSolutionRunConfiguration;
+ return multi != null && multi.Items.Any (si => si.SolutionItem == p);
+ }
+
public override void BuildChildNodes (ITreeBuilder builder, object dataObject)
{
Project project = (Project) dataObject;
@@ -389,11 +399,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
{
Project project = CurrentNode.DataItem as Project;
project.ParentSolution.StartupItem = project;
- if (!project.ParentSolution.SingleStartup) {
- project.ParentSolution.SingleStartup = true;
- await IdeApp.ProjectOperations.SaveAsync (project.ParentSolution);
- } else
- await project.ParentSolution.SaveUserProperties ();
+ await project.ParentSolution.SaveUserProperties ();
}
public override void DeleteItem ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs
index 6b5fd12c36..16567bd651 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/SolutionNodeBuilder.cs
@@ -105,6 +105,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
Solution solution = (Solution) dataObject;
solution.NameChanged += OnCombineRenamed;
solution.StartupItemChanged += OnStartupChanged;
+ solution.RunConfigurationsChanged += OnStartupChanged;
+ solution.StartupConfigurationChanged += OnStartupChanged;
solution.RootFolder.ItemAdded += OnEntryAdded;
solution.RootFolder.ItemRemoved += OnEntryRemoved;
solution.RootFolder.SolutionItemFileAdded += OnFileAdded;
@@ -116,6 +118,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
Solution solution = (Solution) dataObject;
solution.NameChanged -= OnCombineRenamed;
solution.StartupItemChanged -= OnStartupChanged;
+ solution.RunConfigurationsChanged -= OnStartupChanged;
+ solution.StartupConfigurationChanged -= OnStartupChanged;
solution.RootFolder.ItemAdded -= OnEntryAdded;
solution.RootFolder.ItemRemoved -= OnEntryRemoved;
solution.RootFolder.SolutionItemFileAdded -= OnFileAdded;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs
index a5c5b8102e..bf9eedc9ad 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs
@@ -80,7 +80,7 @@ namespace MonoDevelop.Ide.Gui
public OutputProgressMonitor GetRunProgressMonitor ()
{
- return GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.RunProgramIcon, false, true);
+ return GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.MessageLog, false, true);
}
public OutputProgressMonitor GetToolOutputProgressMonitor (bool bringToFront, CancellationTokenSource cs = null)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationPanel.cs
new file mode 100644
index 0000000000..cc54643322
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationPanel.cs
@@ -0,0 +1,124 @@
+//
+// SolutionRunConfigurationPanel.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin, Inc (http://www.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.Components;
+using MonoDevelop.Ide.Gui.Dialogs;
+using Xwt;
+using MonoDevelop.Projects;
+using System.Linq;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.Ide.Projects.OptionPanels
+{
+ public class SolutionRunConfigurationPanel: OptionsPanel
+ {
+ SolutionRunConfigInfo config;
+ ListStore store;
+ ListView listView;
+ DataField<bool> selectedField = new DataField<bool> ();
+ DataField<string> projectNameField = new DataField<string> ();
+ DataField<SolutionItem> projectField = new DataField<SolutionItem> ();
+ DataField<string> runConfigField = new DataField<string> ();
+ DataField<ItemCollection> projectRunConfigsField = new DataField<ItemCollection> ();
+
+ public SolutionRunConfigurationPanel ()
+ {
+ }
+
+ public override void Initialize (OptionsDialog dialog, object dataObject)
+ {
+ base.Initialize (dialog, dataObject);
+
+ config = (SolutionRunConfigInfo)dataObject;
+
+ store = new ListStore (selectedField, projectNameField, projectField, runConfigField, projectRunConfigsField);
+ listView = new ListView (store);
+
+ var col1 = new ListViewColumn (GettextCatalog.GetString ("Solution Item"));
+ var cb = new CheckBoxCellView (selectedField);
+ cb.Toggled += SelectionChanged;
+ cb.Editable = true;
+ col1.Views.Add (cb);
+ col1.Views.Add (new TextCellView (projectNameField));
+ listView.Columns.Add (col1);
+
+ var configSelView = new ComboBoxCellView (runConfigField);
+ configSelView.Editable = true;
+ configSelView.ItemsField = projectRunConfigsField;
+ var col2 = new ListViewColumn (GettextCatalog.GetString ("Run Configuration"), configSelView);
+ listView.Columns.Add (col2);
+
+ foreach (var it in config.Solution.GetAllSolutionItems ().Where (si => si.SupportsExecute ()).OrderBy (si => si.Name)) {
+ var row = store.AddRow ();
+ var si = config.EditedConfig.Items.FirstOrDefault (i => i.SolutionItem == it);
+ var sc = si?.RunConfiguration?.Name ?? it.GetDefaultRunConfiguration ()?.Name;
+ var configs = new ItemCollection ();
+ foreach (var pc in it.GetRunConfigurations ())
+ configs.Add (pc.Name);
+ store.SetValues (row, selectedField, si != null, projectNameField, it.Name, projectField, it, runConfigField, sc, projectRunConfigsField, configs);
+ }
+ }
+
+ public override bool ValidateChanges ()
+ {
+ return true;
+ }
+
+ public override void ApplyChanges ()
+ {
+ SaveChanges ();
+ if (config.ProjectConfig != null)
+ config.ProjectConfig.CopyFrom (config.EditedConfig);
+ }
+
+ void SaveChanges ()
+ {
+ config.EditedConfig.Items.Clear ();
+ for (int n = 0; n < store.RowCount; n++) {
+ if (store.GetValue (n, selectedField)) {
+ var proj = store.GetValue (n, projectField);
+ var rconf = store.GetValue (n, runConfigField);
+ var conf = rconf != null ? proj.GetRunConfigurations ().FirstOrDefault (c => c.Name == rconf) : null;
+ config.EditedConfig.Items.Add (new StartupItem (proj, conf));
+ }
+ }
+ }
+
+ public override Control CreatePanelWidget ()
+ {
+ return new XwtControl (listView);
+ }
+
+ void SelectionChanged (object sender, WidgetEventArgs e)
+ {
+ Xwt.Application.Invoke (delegate {
+ SaveChanges ();
+ var panel = ParentDialog.GetPanel<SolutionRunConfigurationsPanel> ("General");
+ panel.RefreshList ();
+ });
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs
new file mode 100644
index 0000000000..37f0020d2d
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs
@@ -0,0 +1,283 @@
+//
+// CodeFormattingPanelWidget.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2009 Novell, Inc (http://www.novell.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 System.Collections;
+using System.Collections.Generic;
+using Mono.Addins;
+using MonoDevelop.Ide.Gui.Dialogs;
+using MonoDevelop.Ide.Extensions;
+using MonoDevelop.Projects;
+using MonoDevelop.Core;
+using MonoDevelop.Projects.Policies;
+using MonoDevelop.Components;
+using System.Linq;
+using RefactoringEssentials.CSharp.Diagnostics;
+using Xwt.Backends;
+using Xwt;
+
+namespace MonoDevelop.Ide.Projects.OptionPanels
+{
+ class SolutionRunConfigurationsPanel: OptionsPanel
+ {
+ List<SolutionRunConfigInfo> configs = new List<SolutionRunConfigInfo> ();
+ Dictionary<SolutionRunConfigInfo, SolutionRunConfigurationOptionsDialogSection> sections = new Dictionary<SolutionRunConfigInfo, SolutionRunConfigurationOptionsDialogSection> ();
+ SolutionRunConfigurationsPanelWidget widget;
+ XwtControl control;
+
+ public override void Initialize (OptionsDialog dialog, object dataObject)
+ {
+ base.Initialize (dialog, dataObject);
+
+ Solution = (Solution)dataObject;
+
+ foreach (var rc in Solution.MultiStartupRunConfigurations)
+ configs.Add (new SolutionRunConfigInfo { ProjectConfig = rc, EditedConfig = new MultiItemSolutionRunConfiguration (rc) });
+
+ foreach (var c in configs)
+ AddPanel (c);
+ ParentDialog.ExpandChildren (this);
+ }
+
+ public Solution Solution { get; set; }
+
+ public List<SolutionRunConfigInfo> Configurations {
+ get { return configs; }
+ }
+
+ public override void Dispose ()
+ {
+ base.Dispose ();
+ }
+
+ public void RefreshList ()
+ {
+ if (widget != null)
+ widget.RefreshList ();
+ }
+
+ void AddPanel (SolutionRunConfigInfo configInfo)
+ {
+ configInfo.Solution = Solution;
+ var sec = new SolutionRunConfigurationOptionsDialogSection (configInfo);
+ sec.Fill = true;
+ sections [configInfo] = sec;
+ ParentDialog.AddChildSection (this, sec, configInfo);
+ }
+
+ void RemovePanel (SolutionRunConfigInfo rc)
+ {
+ var section = sections [rc];
+ sections.Remove (rc);
+ ParentDialog.RemoveSection (section);
+ }
+
+ internal void RemoveConfiguration (MultiItemSolutionRunConfiguration editedConfig)
+ {
+ var c = configs.First (ci => ci.EditedConfig == editedConfig);
+ configs.Remove (c);
+ RemovePanel (c);
+ }
+
+ internal void AddConfiguration (MultiItemSolutionRunConfiguration editedConfig)
+ {
+ var c = new SolutionRunConfigInfo { EditedConfig = editedConfig };
+ configs.Add (c);
+ AddPanel (c);
+ }
+
+ internal void ReplaceConfiguration (MultiItemSolutionRunConfiguration oldConf, MultiItemSolutionRunConfiguration newConf)
+ {
+ var i = configs.FindIndex (ci => ci.EditedConfig == oldConf);
+ var oldc = configs [i];
+ var newc = new SolutionRunConfigInfo { EditedConfig = newConf };
+ configs [i] = newc;
+ RemovePanel (oldc);
+ AddPanel (newc);
+ }
+
+ internal void ShowConfiguration (MultiItemSolutionRunConfiguration editedConfig)
+ {
+ var rc = configs.First (ci => ci.EditedConfig == editedConfig);
+ var section = sections [rc];
+ ParentDialog.ShowPage (section);
+ }
+
+ public override Control CreatePanelWidget ()
+ {
+ widget = new SolutionRunConfigurationsPanelWidget (this, ParentDialog);
+ return control = new XwtControl (widget);
+ }
+
+ public override void ApplyChanges ()
+ {
+ foreach (var c in configs.Where (co => co.ProjectConfig == null)) {
+ c.ProjectConfig = new MultiItemSolutionRunConfiguration (c.EditedConfig);
+ Solution.MultiStartupRunConfigurations.Add (c.ProjectConfig);
+ }
+ foreach (var c in Solution.MultiStartupRunConfigurations.Where (co => !configs.Any (mc => mc.EditedConfig.Name == co.Name)).ToArray ())
+ Solution.MultiStartupRunConfigurations.Remove (c);
+ }
+ }
+
+ class SolutionRunConfigInfo
+ {
+ public Solution Solution { get; set; }
+ public MultiItemSolutionRunConfiguration ProjectConfig { get; set; }
+ public MultiItemSolutionRunConfiguration EditedConfig { get; set; }
+ }
+
+ class SolutionRunConfigurationOptionsDialogSection : OptionsDialogSection
+ {
+ public SolutionRunConfigurationOptionsDialogSection (SolutionRunConfigInfo configInfo): base (typeof(SolutionRunConfigurationPanel))
+ {
+ RunConfiguration = configInfo.EditedConfig;
+ Label = configInfo.EditedConfig.Name;
+ HeaderLabel = GettextCatalog.GetString ("Run Configuration: " + configInfo.EditedConfig.Name);
+ Icon = "md-prefs-play";
+ }
+
+ //this is used by the options dialog to look up the icon as needed, at required scales
+ public MultiItemSolutionRunConfiguration RunConfiguration { get; private set; }
+ }
+
+ class SolutionRunConfigurationsPanelWidget: Xwt.VBox
+ {
+ SolutionRunConfigurationsPanel panel;
+ RunConfigurationsList list;
+
+ Xwt.Button removeButton;
+ Xwt.Button copyButton;
+ Xwt.Button renameButton;
+
+ public SolutionRunConfigurationsPanelWidget (SolutionRunConfigurationsPanel panel, OptionsDialog dialog)
+ {
+ this.panel = panel;
+
+ Margin = 6;
+ Spacing = 6;
+
+ list = new RunConfigurationsList ();
+ PackStart (list, true);
+
+ var box = new Xwt.HBox ();
+ box.Spacing = 6;
+
+ var btn = new Xwt.Button (GettextCatalog.GetString ("New"));
+ btn.Clicked += OnAddConfiguration;
+ box.PackStart (btn, false);
+
+ copyButton = new Xwt.Button (GettextCatalog.GetString ("Duplicate"));
+ copyButton.Clicked += OnCopyConfiguration;
+ box.PackStart (copyButton, false);
+
+ renameButton = new Xwt.Button (GettextCatalog.GetString ("Rename"));
+ renameButton.Clicked += OnRenameConfiguration;
+ box.PackStart (renameButton, false);
+
+ removeButton = new Xwt.Button (GettextCatalog.GetString ("Remove"));
+ removeButton.Clicked += OnRemoveConfiguration;
+ box.PackEnd (removeButton, false);
+
+ Fill ();
+
+ PackStart (box, false);
+
+ list.SelectionChanged += (sender, e) => UpdateButtons ();
+ list.RowActivated += (sender, e) => panel.ShowConfiguration ((MultiItemSolutionRunConfiguration)list.SelectedConfiguration);
+ UpdateButtons ();
+ }
+
+ void Fill ()
+ {
+ list.Fill (panel.Configurations.Select (c => c.EditedConfig).ToArray ());
+ }
+
+ public void RefreshList ()
+ {
+ Fill ();
+ UpdateButtons ();
+ }
+
+ void UpdateButtons ()
+ {
+ var selection = list.SelectedConfiguration != null;
+ removeButton.Sensitive = selection;
+ copyButton.Sensitive = selection;
+ renameButton.Sensitive = selection;
+ }
+
+ void OnAddConfiguration (object sender, EventArgs e)
+ {
+ var okCommand = new Command (GettextCatalog.GetString ("Create"));
+ using (var dlg = new RunConfigurationNameDialog (ParentWindow, "", okCommand, panel.Configurations.Select (c => c.EditedConfig.Name))) {
+ dlg.Title = GettextCatalog.GetString ("New Configuration");
+ if (dlg.Run () == okCommand) {
+ var config = new MultiItemSolutionRunConfiguration (dlg.NewName, dlg.NewName);
+ panel.AddConfiguration (config);
+ Fill ();
+ }
+ }
+ }
+
+ void OnCopyConfiguration (object sender, EventArgs e)
+ {
+ var config = (MultiItemSolutionRunConfiguration)list.SelectedConfiguration;
+ var okCommand = new Command (GettextCatalog.GetString ("Create"));
+ using (var dlg = new RunConfigurationNameDialog (ParentWindow, config.Name, okCommand, panel.Configurations.Select (c => c.EditedConfig.Name))) {
+ dlg.Title = GettextCatalog.GetString ("Duplicate Configuration");
+ if (dlg.Run () == okCommand) {
+ var copy = new MultiItemSolutionRunConfiguration (config, dlg.NewName);
+ panel.AddConfiguration (copy);
+ Fill ();
+ }
+ }
+ }
+
+ void OnRenameConfiguration (object sender, EventArgs e)
+ {
+ var config = (MultiItemSolutionRunConfiguration)list.SelectedConfiguration;
+ var okCommand = new Command (GettextCatalog.GetString ("Rename"));
+ using (var dlg = new RunConfigurationNameDialog (ParentWindow, config.Name, okCommand, panel.Configurations.Select (c => c.EditedConfig.Name))) {
+ dlg.Title = GettextCatalog.GetString ("Rename Configuration");
+ if (dlg.Run () != Command.Cancel) {
+ var copy = new MultiItemSolutionRunConfiguration (config, dlg.NewName);
+ panel.ReplaceConfiguration (config, copy);
+ Fill ();
+ }
+ }
+ }
+
+ void OnRemoveConfiguration (object sender, EventArgs e)
+ {
+ var config = (MultiItemSolutionRunConfiguration)list.SelectedConfiguration;
+ if (MessageService.Confirm (GettextCatalog.GetString ("Are you sure you want to remove the configuration '{0}'?", config.Name), AlertButton.Remove)) {
+ panel.RemoveConfiguration (config);
+ Fill ();
+ }
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs
deleted file mode 100644
index cc17543aee..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/StartupOptionsPanel.cs
+++ /dev/null
@@ -1,207 +0,0 @@
-// StartupOptionsPanel.cs
-//
-// Author:
-// Lluis Sanchez Gual <lluis@novell.com>
-//
-// Copyright (c) 2008 Novell, Inc (http://www.novell.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 System.Collections.Generic;
-using Gtk;
-using MonoDevelop.Components;
-using MonoDevelop.Projects;
-using MonoDevelop.Core;
-using MonoDevelop.Core.Execution;
-using MonoDevelop.Ide.Gui.Dialogs;
-
-namespace MonoDevelop.Ide.Projects.OptionPanels
-{
- [System.ComponentModel.Category("MonoDevelop.Projects.Gui")]
- [System.ComponentModel.ToolboxItem(true)]
- partial class StartupOptionsPanelWidget : Gtk.Bin
- {
- Solution sol;
- ListStore listStore;
- List<SolutionItem> startupItems;
-
- public StartupOptionsPanelWidget (Solution sol)
- {
- this.Build();
- this.sol = sol;
-
- startupItems = new List<SolutionItem> ();
- foreach (SolutionItem it in sol.GetAllItems<SolutionItem> ()) {
- // Include in the list if it can run in any of the existing execution modes and configurations
- foreach (IExecutionModeSet mset in Runtime.ProcessService.GetExecutionModes ()) {
- bool matched = false;
- foreach (IExecutionMode mode in mset.ExecutionModes) {
- foreach (SolutionConfiguration sc in sol.Configurations) {
- if (it.CanExecute (new ExecutionContext (mode, null, IdeApp.Workspace.ActiveExecutionTarget), sc.Selector)) {
- startupItems.Add (it);
- matched = true;
- break;
- }
- }
- if (matched)
- break;
- }
- if (matched)
- break;
- }
- }
-
- listStore = new ListStore (typeof(SolutionFolderItem), typeof(bool), typeof(string));
- treeItems.Model = listStore;
- treeItems.SearchColumn = -1; // disable the interactive search
-
- CellRendererToggle crt = new CellRendererToggle ();
- treeItems.AppendColumn ("", crt, "active", 1);
- treeItems.AppendColumn (GettextCatalog.GetString ("Project"), new CellRendererText (), "text", 2);
-
- if (startupItems.Count > 0) {
- for (int n=0; n<startupItems.Count; n++) {
- SolutionItem it = startupItems [n];
- comboItems.AppendText (it.Name);
- listStore.AppendValues (it, sol.MultiStartupItems.Contains (it), it.Name);
- if (sol.StartupItem == it)
- comboItems.Active = n;
- }
- }
- else {
- comboItems.AppendText (GettextCatalog.GetString ("The solution does not contain any executable project"));
- comboItems.Active = 0;
- comboItems.Sensitive = false;
- radioMulti.Sensitive = false;
- radioSingle.Sensitive = false;
- }
-
- radioSingle.Active = sol.SingleStartup;
- radioMulti.Active = !sol.SingleStartup;
- UpdateButtons ();
-
- crt.Toggled += OnItemToggled;
- treeItems.Selection.Changed += OnSelectionChanged;
- }
-
- void UpdateButtons ()
- {
- TreeIter iter;
- if (radioSingle.Active || !treeItems.Selection.GetSelected (out iter)) {
- buttonUp.Sensitive = false;
- buttonDown.Sensitive = false;
- }
- else {
- TreeIter first;
- listStore.GetIterFirst (out first);
- buttonUp.Sensitive = !listStore.GetPath (iter).Equals (listStore.GetPath (first));
- buttonDown.Sensitive = listStore.IterNext (ref iter);
- }
-
- treeItems.Sensitive = !radioSingle.Active;
- comboItems.Sensitive = radioSingle.Active;
- }
-
- void OnItemToggled (object s, ToggledArgs args)
- {
- Gtk.TreeIter it;
- listStore.GetIterFromString (out it, args.Path);
- bool run = (bool) listStore.GetValue (it, 1);
- listStore.SetValue (it, 1, !run);
- }
-
- protected virtual void OnButtonUpClicked (object sender, System.EventArgs e)
- {
- TreeIter iter;
- if (!treeItems.Selection.GetSelected (out iter))
- return;
-
- TreePath tp = listStore.GetPath (iter);
- Gtk.TreeIter pi;
- if (tp.Prev () && listStore.GetIter (out pi, tp)) {
- listStore.Swap (pi, iter);
- treeItems.ScrollToCell (listStore.GetPath (iter), treeItems.Columns[0], false, 0, 0);
- UpdateButtons ();
- }
- }
-
- protected virtual void OnButtonDownClicked (object sender, System.EventArgs e)
- {
- TreeIter iter;
- if (!treeItems.Selection.GetSelected (out iter))
- return;
-
- TreeIter pit = iter;
- listStore.IterNext (ref iter);
- listStore.Swap (pit, iter);
- treeItems.ScrollToCell (listStore.GetPath (pit), treeItems.Columns[0], false, 0, 0);
- UpdateButtons ();
- }
-
- void OnSelectionChanged (object s, EventArgs args)
- {
- UpdateButtons ();
- }
-
- public void ApplyChanges ()
- {
- sol.SingleStartup = radioSingle.Active;
- sol.MultiStartupItems.Clear ();
-
- if (sol.SingleStartup) {
- if (comboItems.Active != -1 && startupItems.Count > 0)
- sol.StartupItem = startupItems [comboItems.Active];
- else
- sol.StartupItem = null;
- } else {
- TreeIter it;
- if (listStore.GetIterFirst (out it)) {
- do {
- if ((bool) listStore.GetValue (it, 1))
- sol.MultiStartupItems.Add ((SolutionItem) listStore.GetValue (it, 0));
- } while (listStore.IterNext (ref it));
- }
- sol.StartupItem = null;
- }
- }
-
- protected virtual void OnRadioSingleToggled (object sender, System.EventArgs e)
- {
- UpdateButtons ();
- }
- }
-
- class StartupOptionsPanel: ItemOptionsPanel
- {
- StartupOptionsPanelWidget widget;
-
- public override Control CreatePanelWidget ()
- {
- return widget = new StartupOptionsPanelWidget (ConfiguredSolution);
- }
-
- public override void ApplyChanges ()
- {
- widget.ApplyChanges ();
- }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index 2c1d93b97b..2575987ef9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -1,4 +1,4 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -8509,7 +8509,6 @@
<Compile Include="gtk-gui\MonoDevelop.Ide.Projects.OptionPanels.RunOptionsPanelWidget.cs" />
<Compile Include="gtk-gui\MonoDevelop.Ide.Projects.OptionPanels.RuntimeOptionsPanelWidget.cs" />
<Compile Include="gtk-gui\MonoDevelop.Ide.Projects.OptionPanels.CombineEntryConfigurationsPanelWidget.cs" />
- <Compile Include="gtk-gui\MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget.cs" />
<Compile Include="MonoDevelop.Ide.Projects.OptionPanels\BaseDirectoryPanel.cs" />
<Compile Include="MonoDevelop.Ide.Projects.OptionPanels\BaseDirectoryPanelWidget.cs" />
<Compile Include="MonoDevelop.Ide.Projects.OptionPanels\CodeFormattingPanel.cs" />
@@ -8526,7 +8525,6 @@
<Compile Include="MonoDevelop.Ide.Projects.OptionPanels\RunOptionsPanel.cs" />
<Compile Include="MonoDevelop.Ide.Projects.OptionPanels\RuntimeOptionsPanel.cs" />
<Compile Include="MonoDevelop.Ide.Projects.OptionPanels\SolutionItemConfigurationsPanel.cs" />
- <Compile Include="MonoDevelop.Ide.Projects.OptionPanels\StartupOptionsPanel.cs" />
<Compile Include="gtk-gui\MonoDevelop.Ide.Projects.AddMimeTypeDialog.cs" />
<Compile Include="gtk-gui\MonoDevelop.Ide.Projects.ConfirmProjectDeleteDialog.cs" />
<Compile Include="gtk-gui\MonoDevelop.Ide.Projects.DeleteConfigDialog.cs" />
@@ -9072,6 +9070,8 @@
<Compile Include="gtk-gui\MonoDevelop.Ide.Editor.TextMate.TextMateBundleOptionsPanelWidget.cs" />
<Compile Include="MonoDevelop.Ide.Editor.Highlighting\LanguageBundle.cs" />
<Compile Include="MonoDevelop.Ide.Editor.Highlighting\StackMatchExpression.cs" />
+ <Compile Include="MonoDevelop.Ide.Projects.OptionPanels\SolutionRunConfigurationsPanel.cs" />
+ <Compile Include="MonoDevelop.Ide.Projects.OptionPanels\SolutionRunConfigurationPanel.cs" />
<Compile Include="MonoDevelop.Ide.GettingStarted\GettingStarted.cs" />
<Compile Include="MonoDevelop.Ide.GettingStarted\GettingStartedNode.cs" />
<Compile Include="MonoDevelop.Ide.GettingStarted\GettingStartedNodeBuilder.cs" />
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
index adea023c87..dd1d1601b0 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
@@ -66,9 +66,9 @@ namespace MonoDevelop.Ide
public class ProjectOperations
{
AsyncOperation<BuildResult> currentBuildOperation = new AsyncOperation<BuildResult> (Task.FromResult (BuildResult.CreateSuccess ()), null);
- AsyncOperation currentRunOperation = AsyncOperation.CompleteOperation;
+ MultipleAsyncOperation currentRunOperation = MultipleAsyncOperation.CompleteMultipleOperation;
IBuildTarget currentBuildOperationOwner;
- IBuildTarget currentRunOperationOwner;
+ List<IBuildTarget> currentRunOperationOwners = new List<IBuildTarget> ();
SelectReferenceDialog selDialog = null;
@@ -160,9 +160,21 @@ namespace MonoDevelop.Ide
public AsyncOperation CurrentRunOperation {
get { return currentRunOperation; }
- set {
- currentRunOperation = value ?? AsyncOperation.CompleteOperation;
+ set { AddRunOperation (value); }
+ }
+
+ public void AddRunOperation (AsyncOperation runOperation)
+ {
+ if (runOperation == null)
+ return;
+ if (runOperation.IsCompleted)//null or complete doesn't change anything, just ignore
+ return;
+ if (currentRunOperation.IsCompleted) {//if MultipleAsyncOperations is complete, we can't just restart Task.. start new one
+ currentRunOperation = new MultipleAsyncOperation ();
+ currentRunOperation.AddOperation (runOperation);
OnCurrentRunOperationChanged (EventArgs.Empty);
+ } else {//Some process is already running... attach this one to it...
+ currentRunOperation.AddOperation (runOperation);
}
}
@@ -171,11 +183,15 @@ namespace MonoDevelop.Ide
var owner = currentBuildOperationOwner as WorkspaceObject;
return owner != null && !currentBuildOperation.IsCompleted && ContainsTarget (ob, owner);
}
-
+
public bool IsRunning (WorkspaceObject target)
{
- var owner = currentRunOperationOwner as WorkspaceObject;
- return owner != null && !currentRunOperation.IsCompleted && ContainsTarget (target, owner);
+ foreach (var currentRunOperationOwner in currentRunOperationOwners) {
+ var owner = currentRunOperationOwner as WorkspaceObject;
+ if (owner != null && !currentRunOperation.IsCompleted && ContainsTarget (target, owner))
+ return true;
+ }
+ return false;
}
internal static bool ContainsTarget (WorkspaceObject owner, WorkspaceObject target)
@@ -1023,8 +1039,6 @@ namespace MonoDevelop.Ide
public AsyncOperation Execute (IBuildTarget entry, ExecutionContext context, bool buildBeforeExecuting = true)
{
- if (currentRunOperation != null && !currentRunOperation.IsCompleted) return currentRunOperation;
-
var cs = new CancellationTokenSource ();
return new AsyncOperation (ExecuteAsync (entry, context, cs, IdeApp.Workspace.ActiveConfiguration, null, buildBeforeExecuting), cs);
}
@@ -1061,15 +1075,15 @@ namespace MonoDevelop.Ide
var t = ExecuteSolutionItemAsync (monitor, entry, context, configuration, runConfiguration);
var op = new AsyncOperation (t, cs);
- CurrentRunOperation = op;
- currentRunOperationOwner = entry;
+ AddRunOperation (op);
+ currentRunOperationOwners.Add (entry);
await t;
var error = monitor.Errors.FirstOrDefault ();
if (error != null)
IdeApp.Workbench.StatusBar.ShowError (error.DisplayMessage);
- currentRunOperationOwner = null;
+ currentRunOperationOwners.Remove (entry);
}
async Task ExecuteSolutionItemAsync (ProgressMonitor monitor, IBuildTarget entry, ExecutionContext context, ConfigurationSelector configuration, RunConfiguration runConfiguration)
@@ -2233,7 +2247,7 @@ namespace MonoDevelop.Ide
if (IsRunning (args.Item)) {
if (MessageService.Confirm (GettextCatalog.GetString (
"The project '{0}' is currently running and will have to be stopped. Do you want to continue closing it?",
- currentRunOperationOwner.Name),
+ args.Item.Name),
new AlertButton (GettextCatalog.GetString ("Close Project")))) {
CurrentRunOperation.Cancel ();
} else
@@ -2304,6 +2318,45 @@ namespace MonoDevelop.Ide
ITextDocument GetEditableTextFile (FilePath filePath);
}
+ class MultipleAsyncOperation : AsyncOperation
+ {
+ public static MultipleAsyncOperation CompleteMultipleOperation = new MultipleAsyncOperation (true);
+
+ List<AsyncOperation> Operations = new List<AsyncOperation> ();
+ TaskCompletionSource<int> TaskCompletionSource = new TaskCompletionSource<int> ();
+
+ public MultipleAsyncOperation ()
+ {
+ Task = TaskCompletionSource.Task;
+ CancellationTokenSource.Token.Register (MultiCancel);
+ }
+
+ MultipleAsyncOperation (bool completed)
+ {
+ if (completed)
+ TaskCompletionSource.SetResult (0);
+ }
+
+ public void AddOperation (AsyncOperation op)
+ {
+ Operations.Add (op);
+ op.Task.ContinueWith (CheckForCompletion);
+ }
+
+ void CheckForCompletion (Task obj)
+ {
+ if (Operations.All (op => op.IsCompleted))
+ TaskCompletionSource.SetResult (0);
+ }
+
+ void MultiCancel ()
+ {
+ foreach (var op in Operations) {
+ op.Cancel ();
+ }
+ }
+ }
+
public class TextFileProvider : ITextFileProvider
{
static TextFileProvider instance = new TextFileProvider ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
index 3dac774169..73be2cc5b8 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
@@ -108,6 +108,11 @@ namespace MonoDevelop.Ide
ActiveConfigurationChanged (this, EventArgs.Empty);
}
+ public ExecutionTarget GetActiveExecutionTarget (SolutionItem project)
+ {
+ return (activeExecutionTarget as MultiProjectExecutionTarget)?.GetTarget (project) ?? activeExecutionTarget;
+ }
+
ExecutionTarget activeExecutionTarget;
public ExecutionTarget ActiveExecutionTarget {
get { return activeExecutionTarget; }
diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget.cs b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget.cs
deleted file mode 100644
index 9657683f0b..0000000000
--- a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-
-// This file has been generated by the GUI designer. Do not modify.
-namespace MonoDevelop.Ide.Projects.OptionPanels
-{
- internal partial class StartupOptionsPanelWidget
- {
- private global::Gtk.VBox vbox2;
- private global::Gtk.RadioButton radioSingle;
- private global::Gtk.HBox hbox2;
- private global::Gtk.Label label1;
- private global::Gtk.ComboBox comboItems;
- private global::Gtk.RadioButton radioMulti;
- private global::Gtk.HBox hbox1;
- private global::Gtk.Label label2;
- private global::Gtk.ScrolledWindow GtkScrolledWindow;
- private global::Gtk.TreeView treeItems;
- private global::Gtk.VBox vbox3;
- private global::Gtk.Button buttonUp;
- private global::Gtk.Button buttonDown;
-
- protected virtual void Build ()
- {
- global::Stetic.Gui.Initialize (this);
- // Widget MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget
- global::Stetic.BinContainer.Attach (this);
- this.Name = "MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget";
- // Container child MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget.Gtk.Container+ContainerChild
- this.vbox2 = new global::Gtk.VBox ();
- this.vbox2.Name = "vbox2";
- this.vbox2.Spacing = 6;
- // Container child vbox2.Gtk.Box+BoxChild
- this.radioSingle = new global::Gtk.RadioButton (global::Mono.Unix.Catalog.GetString ("Single startup project:"));
- this.radioSingle.CanFocus = true;
- this.radioSingle.Name = "radioSingle";
- this.radioSingle.DrawIndicator = true;
- this.radioSingle.UseUnderline = true;
- this.radioSingle.Group = new global::GLib.SList (global::System.IntPtr.Zero);
- this.vbox2.Add (this.radioSingle);
- global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.radioSingle]));
- w1.Position = 0;
- w1.Expand = false;
- w1.Fill = false;
- // Container child vbox2.Gtk.Box+BoxChild
- this.hbox2 = new global::Gtk.HBox ();
- this.hbox2.Name = "hbox2";
- this.hbox2.Spacing = 6;
- // Container child hbox2.Gtk.Box+BoxChild
- this.label1 = new global::Gtk.Label ();
- this.label1.WidthRequest = 12;
- this.label1.Name = "label1";
- this.hbox2.Add (this.label1);
- global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.label1]));
- w2.Position = 0;
- w2.Expand = false;
- w2.Fill = false;
- // Container child hbox2.Gtk.Box+BoxChild
- this.comboItems = global::Gtk.ComboBox.NewText ();
- this.comboItems.Name = "comboItems";
- this.hbox2.Add (this.comboItems);
- global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.comboItems]));
- w3.Position = 1;
- this.vbox2.Add (this.hbox2);
- global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox2]));
- w4.Position = 1;
- w4.Expand = false;
- w4.Fill = false;
- // Container child vbox2.Gtk.Box+BoxChild
- this.radioMulti = new global::Gtk.RadioButton (global::Mono.Unix.Catalog.GetString ("Multiple startup projects:"));
- this.radioMulti.CanFocus = true;
- this.radioMulti.Name = "radioMulti";
- this.radioMulti.DrawIndicator = true;
- this.radioMulti.UseUnderline = true;
- this.radioMulti.Group = this.radioSingle.Group;
- this.vbox2.Add (this.radioMulti);
- global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.radioMulti]));
- w5.Position = 2;
- w5.Expand = false;
- w5.Fill = false;
- // Container child vbox2.Gtk.Box+BoxChild
- this.hbox1 = new global::Gtk.HBox ();
- this.hbox1.Name = "hbox1";
- this.hbox1.Spacing = 6;
- // Container child hbox1.Gtk.Box+BoxChild
- this.label2 = new global::Gtk.Label ();
- this.label2.WidthRequest = 12;
- this.label2.Name = "label2";
- this.hbox1.Add (this.label2);
- global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.label2]));
- w6.Position = 0;
- w6.Expand = false;
- w6.Fill = false;
- // Container child hbox1.Gtk.Box+BoxChild
- this.GtkScrolledWindow = new global::Gtk.ScrolledWindow ();
- this.GtkScrolledWindow.Name = "GtkScrolledWindow";
- this.GtkScrolledWindow.ShadowType = ((global::Gtk.ShadowType)(1));
- // Container child GtkScrolledWindow.Gtk.Container+ContainerChild
- this.treeItems = new global::Gtk.TreeView ();
- this.treeItems.CanFocus = true;
- this.treeItems.Name = "treeItems";
- this.GtkScrolledWindow.Add (this.treeItems);
- this.hbox1.Add (this.GtkScrolledWindow);
- global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.GtkScrolledWindow]));
- w8.Position = 1;
- // Container child hbox1.Gtk.Box+BoxChild
- this.vbox3 = new global::Gtk.VBox ();
- this.vbox3.Name = "vbox3";
- this.vbox3.Spacing = 6;
- // Container child vbox3.Gtk.Box+BoxChild
- this.buttonUp = new global::Gtk.Button ();
- this.buttonUp.CanFocus = true;
- this.buttonUp.Name = "buttonUp";
- this.buttonUp.UseStock = true;
- this.buttonUp.UseUnderline = true;
- this.buttonUp.Label = "gtk-go-up";
- this.vbox3.Add (this.buttonUp);
- global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.buttonUp]));
- w9.Position = 0;
- w9.Expand = false;
- w9.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.buttonDown = new global::Gtk.Button ();
- this.buttonDown.CanFocus = true;
- this.buttonDown.Name = "buttonDown";
- this.buttonDown.UseStock = true;
- this.buttonDown.UseUnderline = true;
- this.buttonDown.Label = "gtk-go-down";
- this.vbox3.Add (this.buttonDown);
- global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.buttonDown]));
- w10.Position = 1;
- w10.Expand = false;
- w10.Fill = false;
- this.hbox1.Add (this.vbox3);
- global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.vbox3]));
- w11.Position = 2;
- w11.Expand = false;
- w11.Fill = false;
- this.vbox2.Add (this.hbox1);
- global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox1]));
- w12.Position = 3;
- this.Add (this.vbox2);
- if ((this.Child != null)) {
- this.Child.ShowAll ();
- }
- this.Hide ();
- this.radioSingle.Toggled += new global::System.EventHandler (this.OnRadioSingleToggled);
- this.buttonUp.Clicked += new global::System.EventHandler (this.OnButtonUpClicked);
- this.buttonDown.Clicked += new global::System.EventHandler (this.OnButtonDownClicked);
- }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic b/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic
index 711ad58b13..c4c962dfed 100644
--- a/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic
+++ b/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic
@@ -8690,175 +8690,6 @@ All solutions</property>
</widget>
</child>
</widget>
- <widget class="Gtk.Bin" id="MonoDevelop.Ide.Projects.OptionPanels.StartupOptionsPanelWidget" design-size="458 300">
- <property name="MemberName" />
- <property name="Visible">False</property>
- <property name="GeneratePublic">False</property>
- <child>
- <widget class="Gtk.VBox" id="vbox2">
- <property name="MemberName" />
- <property name="Spacing">6</property>
- <child>
- <widget class="Gtk.RadioButton" id="radioSingle">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Single startup project:</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- <property name="Group">group1</property>
- <signal name="Toggled" handler="OnRadioSingleToggled" />
- </widget>
- <packing>
- <property name="Position">0</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.HBox" id="hbox2">
- <property name="MemberName" />
- <property name="Spacing">6</property>
- <child>
- <widget class="Gtk.Label" id="label1">
- <property name="MemberName" />
- <property name="WidthRequest">12</property>
- </widget>
- <packing>
- <property name="Position">0</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.ComboBox" id="comboItems">
- <property name="MemberName" />
- <property name="IsTextCombo">True</property>
- <property name="Items" translatable="yes" />
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">False</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.RadioButton" id="radioMulti">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Multiple startup projects:</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- <property name="Group">group1</property>
- </widget>
- <packing>
- <property name="Position">2</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.HBox" id="hbox1">
- <property name="MemberName" />
- <property name="Spacing">6</property>
- <child>
- <widget class="Gtk.Label" id="label2">
- <property name="MemberName" />
- <property name="WidthRequest">12</property>
- </widget>
- <packing>
- <property name="Position">0</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.ScrolledWindow" id="GtkScrolledWindow">
- <property name="MemberName" />
- <property name="ShadowType">In</property>
- <child>
- <widget class="Gtk.TreeView" id="treeItems">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="ShowScrollbars">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">True</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.VBox" id="vbox3">
- <property name="MemberName" />
- <property name="Spacing">6</property>
- <child>
- <widget class="Gtk.Button" id="buttonUp">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="UseStock">True</property>
- <property name="Type">StockItem</property>
- <property name="StockId">gtk-go-up</property>
- <signal name="Clicked" handler="OnButtonUpClicked" />
- <property name="label">gtk-go-up</property>
- </widget>
- <packing>
- <property name="Position">0</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.Button" id="buttonDown">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="UseStock">True</property>
- <property name="Type">StockItem</property>
- <property name="StockId">gtk-go-down</property>
- <signal name="Clicked" handler="OnButtonDownClicked" />
- <property name="label">gtk-go-down</property>
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <placeholder />
- </child>
- </widget>
- <packing>
- <property name="Position">2</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="Position">3</property>
- <property name="AutoSize">False</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
<widget class="Gtk.Bin" id="MonoDevelop.Ide.Projects.OptionPanels.RunOptionsPanelWidget" design-size="473 371">
<property name="MemberName" />
<child>