diff --git a/data/resources/StringResources.resx b/data/resources/StringResources.resx index 8e9516f3a6..9665493f99 100644 --- a/data/resources/StringResources.resx +++ b/data/resources/StringResources.resx @@ -5935,7 +5935,13 @@ Shows the full callstack of the error. Object Graph - Parallel Stack + Parallel Stacks + + + Toggle Method View + + + Show/Hide Zoom Control Run to cursor diff --git a/data/resources/image/BitmapResources/BitmapResources-data/Icons.48x48.CurrentFrame.png b/data/resources/image/BitmapResources/BitmapResources-data/Icons.48x48.CurrentFrame.png new file mode 100644 index 0000000000..ab2c0923f2 Binary files /dev/null and b/data/resources/image/BitmapResources/BitmapResources-data/Icons.48x48.CurrentFrame.png differ diff --git a/data/resources/image/BitmapResources/BitmapResources.res b/data/resources/image/BitmapResources/BitmapResources.res index e9c1149a08..8993abed40 100644 --- a/data/resources/image/BitmapResources/BitmapResources.res +++ b/data/resources/image/BitmapResources/BitmapResources.res @@ -37,6 +37,10 @@ ProjectBrowser.WebReferenceFolder.Closed = ProjectBrowserIcons\WebReferenceFolde ProjectBrowser.WebReferenceFolder.Open = ProjectBrowserIcons\WebReferenceFolder.Open.png ProjectBrowser.WebReference = ProjectBrowserIcons\WebReference.png +#Parallel Stacks pad +ParallelStacks.MethodView = PadIcons\MethodView.png +ParallelStacks.ZoomControl = PadIcons\ZoomControl.png + #Output pad OutputPad.Toolbar.ClearOutputWindow = OutputPadIcons\ClearOutputWindow.png @@ -226,6 +230,7 @@ Icons.16x16.OpenFileIcon = BitmapResources-data\Icons.1 Icons.16x16.HtmlElements.FieldSetElement = BitmapResources-data\Icons.16x16.HtmlElements.FieldSetElement.png Icons.16x16.SplitWindow = BitmapResources-data\Icons.16x16.SplitWindow.png Icons.16x16.DeleteHistory = BitmapResources-data\Icons.16x16.DeleteHistory.png +Icons.48x48.CurrentFrame = BitmapResources-data\Icons.48x48.CurrentFrame.png #pad icons PadIcons.ErrorList = PadIcons\ErrorList.png diff --git a/data/resources/image/BitmapResources/PadIcons/MethodView.png b/data/resources/image/BitmapResources/PadIcons/MethodView.png new file mode 100644 index 0000000000..a830304afa Binary files /dev/null and b/data/resources/image/BitmapResources/PadIcons/MethodView.png differ diff --git a/data/resources/image/BitmapResources/PadIcons/ZoomControl.png b/data/resources/image/BitmapResources/PadIcons/ZoomControl.png new file mode 100644 index 0000000000..5d73c69855 Binary files /dev/null and b/data/resources/image/BitmapResources/PadIcons/ZoomControl.png differ diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin index 80db53ae4d..d68b472f09 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin @@ -128,7 +128,7 @@ category = "Debugger" title = "${res:MainWindow.Windows.Debug.ParallelStack}" icon = "PadIcons.Parallel" - class = "Debugger.AddIn.Pads.ParallelPad.ParallelStackPad" + class = "ICSharpCode.SharpDevelop.Gui.Pads.ParallelStackPad" defaultPosition = "Bottom, Hidden" /> @@ -166,6 +166,24 @@ type="ComboBox" id="SelectLanguageCommand" /> + + + + + + /> + + diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj index 142e3e98a3..c84a269c14 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj @@ -104,6 +104,9 @@ CallStackPad.xaml Code + + + ConditionCell.xaml @@ -150,8 +153,6 @@ DebuggingSymbolsPanel.cs - - UserControl @@ -398,6 +399,7 @@ ICSharpCode.Core.WinForms False + diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs new file mode 100644 index 0000000000..ae5748f9d9 --- /dev/null +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs @@ -0,0 +1,92 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Windows.Controls; +using ICSharpCode.Core; + +namespace ICSharpCode.SharpDevelop.Gui.Pads +{ + public sealed class ShowZoomControlCommand : AbstractCheckableMenuCommand + { + ParallelStackPad pad; + + public override object Owner { + get { return base.Owner; } + set { + if (!(value is ParallelStackPad)) + throw new Exception("Owner has to be a AbstractConsolePad"); + pad = value as ParallelStackPad; + base.Owner = value; + } + } + + public override bool IsChecked { + get { return pad.IsZoomControlVisible; } + set { pad.IsZoomControlVisible = value; } + } + + public override void Run() + { + IsChecked = !IsChecked; + } + } + + public sealed class ToggleMethodViewCommand : AbstractCheckableMenuCommand + { + ParallelStackPad pad; + + public override object Owner { + get { return base.Owner; } + set { + if (!(value is ParallelStackPad)) + throw new Exception("Owner has to be a AbstractConsolePad"); + pad = value as ParallelStackPad; + base.Owner = value; + } + } + + public override bool IsChecked { + get { return pad.IsMethodView; } + set { pad.IsMethodView = value; } + } + + public override void Run() + { + IsChecked = !IsChecked; + } + } + + public sealed class ParallelStacksViewCommand : AbstractComboBoxCommand + { + ParallelStackPad pad; + ComboBox box; + + protected override void OnOwnerChanged(EventArgs e) + { + this.pad = this.Owner as ParallelStackPad; + if (this.pad == null) + return; + + box = this.ComboBox as ComboBox; + + if (this.box == null) + return; + + foreach (var name in Enum.GetNames(typeof(ParallelStacksView))) + box.Items.Add(name); + + box.SelectedIndex = 0; + + base.OnOwnerChanged(e); + } + + public override void Run() + { + if (this.pad != null && this.box != null) { + pad.ParallelStacksView = (ParallelStacksView)Enum.Parse(typeof(ParallelStacksView), box.SelectedValue.ToString()); + } + base.Run(); + } + } +} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/SelectLanguageCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs similarity index 96% rename from src/AddIns/Debugger/Debugger.AddIn/Pads/SelectLanguageCommand.cs rename to src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs index 8cddba8ae9..b117571b31 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/SelectLanguageCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs @@ -1,47 +1,47 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System; -using Debugger; -using Debugger.AddIn; -using ICSharpCode.Core; -using ICSharpCode.NRefactory; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; -using System.Windows.Controls; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - class SelectLanguageCommand : AbstractComboBoxCommand - { - ConsolePad pad; - ComboBox box; - - protected override void OnOwnerChanged(EventArgs e) - { - this.pad = this.Owner as ConsolePad; - if (this.pad == null) - return; - - box = this.ComboBox as ComboBox; - - if (this.box == null) - return; - - foreach (var name in Enum.GetNames(typeof(SupportedLanguage))) - box.Items.Add(name); - - box.SelectedIndex = 0; - - base.OnOwnerChanged(e); - } - - public override void Run() - { - if (this.pad != null && this.box != null) { - pad.SelectedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), box.SelectedValue.ToString()); - } - base.Run(); - } - } -} +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) + +using System; +using Debugger; +using Debugger.AddIn; +using ICSharpCode.Core; +using ICSharpCode.NRefactory; +using ICSharpCode.SharpDevelop.Debugging; +using ICSharpCode.SharpDevelop.Services; +using System.Windows.Controls; + +namespace ICSharpCode.SharpDevelop.Gui.Pads +{ + class SelectLanguageCommand : AbstractComboBoxCommand + { + ConsolePad pad; + ComboBox box; + + protected override void OnOwnerChanged(EventArgs e) + { + this.pad = this.Owner as ConsolePad; + if (this.pad == null) + return; + + box = this.ComboBox as ComboBox; + + if (this.box == null) + return; + + foreach (var name in Enum.GetNames(typeof(SupportedLanguage))) + box.Items.Add(name); + + box.SelectedIndex = 0; + + base.OnOwnerChanged(e); + } + + public override void Run() + { + if (this.pad != null && this.box != null) { + pad.SelectedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), box.SelectedValue.ToString()); + } + base.Run(); + } + } +} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs similarity index 100% rename from src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs rename to src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs index 54afe42de7..1076c8e141 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs @@ -1,41 +1,66 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using Debugger; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public abstract class DebuggerPad: AbstractPadContent - { - protected WindowsDebugger debugger; - - public DebuggerPad() - { - debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - InitializeComponents(); - - debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { - SelectProcess(e.Process); - }; - SelectProcess(debugger.DebuggedProcess); - } - - protected virtual void InitializeComponents() - { - - } - - protected virtual void SelectProcess(Process process) - { - - } - - public virtual void RefreshPad() - { - - } - } -} +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) + +using System.Windows.Controls; +using Debugger; +using ICSharpCode.SharpDevelop.Debugging; +using ICSharpCode.SharpDevelop.Services; + +namespace ICSharpCode.SharpDevelop.Gui.Pads +{ + public abstract class DebuggerPad : AbstractPadContent + { + protected DockPanel panel; + ToolBar toolbar; + protected WindowsDebugger debugger; + + public override object Control { + get { + return panel; + } + } + + public DebuggerPad() + { + // UI + this.panel = new DockPanel(); + this.toolbar = BuildToolBar(); + + if (this.toolbar != null) { + this.toolbar.SetValue(DockPanel.DockProperty, Dock.Top); + + this.panel.Children.Add(toolbar); + } + + // logic + debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; + + InitializeComponents(); + + debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { + SelectProcess(e.Process); + }; + SelectProcess(debugger.DebuggedProcess); + } + + protected virtual void InitializeComponents() + { + + } + + protected virtual void SelectProcess(Process process) + { + + } + + public virtual void RefreshPad() + { + + } + + protected virtual ToolBar BuildToolBar() + { + return null; + } + } +} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs index 0ccfc5c182..b93cf95ed0 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs @@ -17,15 +17,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads SimpleListViewControl loadedModulesList; Process debuggedProcess; - public override object Control { - get { - return loadedModulesList; - } - } - protected override void InitializeComponents() { loadedModulesList = new SimpleListViewControl(); + panel.Children.Add(loadedModulesList); RedrawContent(); ResourceService.LanguageChanged += delegate { RedrawContent(); }; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs index 4b64b1caea..a1d2965326 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs @@ -26,15 +26,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads get { return instance; } } - /// - /// This is not used anywhere, but it is neccessary to be overridden in children of AbstractPadContent. - /// - public override object Control { - get { - return localVarList; - } - } - public Process Process { get { return debuggedProcess; } } @@ -42,6 +33,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads protected override void InitializeComponents() { localVarList = new WatchList(); + panel.Children.Add(localVarList); } protected override void SelectProcess(Process process) diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs index 5a11ca25e7..06384cdebb 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs @@ -1,76 +1,72 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using ICSharpCode.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using Debugger; -using Debugger.AddIn.Visualizers.Graph; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - /// - /// Description of ObjectGraphPad. - /// - public class ObjectGraphPad : DebuggerPad - { - Process debuggedProcess; - ObjectGraphControl objectGraphControl; - static ObjectGraphPad instance; - - public ObjectGraphPad() - { - instance = this; - } - - /// Always check if Instance is null, might be null if pad is not opened! - public static ObjectGraphPad Instance { - get { return instance; } - } - - protected override void InitializeComponents() - { - objectGraphControl = new ObjectGraphControl(); - } - - public override object Control { - get { - return objectGraphControl; - } - } - - public override void RefreshPad() - { - // BUG: if pad window is undocked and floats standalone, IsVisible == false (so pad won't refresh) - // REQUEST: need to refresh when pad becomes visible -> VisibleChanged event? - if (!objectGraphControl.IsVisible) - { - return; - } - if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) { - this.objectGraphControl.Clear(); - return; - } - this.objectGraphControl.Refresh(); - } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - } - RefreshPad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - RefreshPad(); - } - } -} +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) + +using ICSharpCode.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using Debugger; +using Debugger.AddIn.Visualizers.Graph; + +namespace ICSharpCode.SharpDevelop.Gui.Pads +{ + /// + /// Description of ObjectGraphPad. + /// + public class ObjectGraphPad : DebuggerPad + { + Process debuggedProcess; + ObjectGraphControl objectGraphControl; + static ObjectGraphPad instance; + + public ObjectGraphPad() + { + instance = this; + } + + /// Always check if Instance is null, might be null if pad is not opened! + public static ObjectGraphPad Instance { + get { return instance; } + } + + protected override void InitializeComponents() + { + objectGraphControl = new ObjectGraphControl(); + panel.Children.Add(objectGraphControl); + } + + + public override void RefreshPad() + { + // BUG: if pad window is undocked and floats standalone, IsVisible == false (so pad won't refresh) + // REQUEST: need to refresh when pad becomes visible -> VisibleChanged event? + if (!objectGraphControl.IsVisible) + { + return; + } + if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) { + this.objectGraphControl.Clear(); + return; + } + this.objectGraphControl.Refresh(); + } + + protected override void SelectProcess(Process process) + { + if (debuggedProcess != null) { + debuggedProcess.Paused -= debuggedProcess_Paused; + } + debuggedProcess = process; + if (debuggedProcess != null) { + debuggedProcess.Paused += debuggedProcess_Paused; + } + RefreshPad(); + } + + void debuggedProcess_Paused(object sender, ProcessEventArgs e) + { + RefreshPad(); + } + } +} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml index ee865e00f0..8b367d0316 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml @@ -79,11 +79,11 @@ + Width="Auto" /> - currentThreadStacks = new List(); + private ParallelStacksView parallelStacksView; + private StackFrame selectedFrame; + private bool isMethodView; #region Overrides protected override void InitializeComponents() { surface = new DrawSurface(); - } - - public override object Control { - get { - return surface; - } + + panel.Children.Add(surface); } protected override void SelectProcess(Process process) @@ -60,54 +66,125 @@ namespace Debugger.AddIn.Pads.ParallelPad if (debuggedProcess == null || debuggedProcess.IsRunning) { return; } + OnReset(null, EventArgs.Empty); - using(new PrintTimes("Parallel stack refresh")) { - try { - OnReset(null, EventArgs.Empty); - // create all simple ThreadStacks - foreach (Thread thread in debuggedProcess.Threads) { - if (debuggedProcess.IsPaused) { - Utils.DoEvents(debuggedProcess); + if (ParallelStacksView == ParallelStacksView.Threads) + { + if (isMethodView) + { + // build method view for threads + using(new PrintTimes("Parallel stack - method view + threads refresh")) { + try { + // create all simple ThreadStacks + foreach (Thread thread in debuggedProcess.Threads) { + if (debuggedProcess.IsPaused) { + Utils.DoEvents(debuggedProcess); + } + CreateThreadStack(thread); + } + + CreateMethodViewStacks(); + } + catch(AbortedBecauseDebuggeeResumedException) { } + catch(System.Exception) { + if (debuggedProcess == null || debuggedProcess.HasExited) { + // Process unexpectedly exited + } else { + throw; + } } - - CreateThreadStack(thread); } - - CreateCommonStacks(); } - catch(AbortedBecauseDebuggeeResumedException) { } - catch(System.Exception) { - if (debuggedProcess == null || debuggedProcess.HasExited) { - // Process unexpectedly exited - } else { - throw; + else + { + // normal view + using(new PrintTimes("Parallel stack - threads refresh")) { + try { + // create all simple ThreadStacks + foreach (Thread thread in debuggedProcess.Threads) { + if (debuggedProcess.IsPaused) { + Utils.DoEvents(debuggedProcess); + } + CreateThreadStack(thread); + } + + CreateCommonStacks(); + } + catch(AbortedBecauseDebuggeeResumedException) { } + catch(System.Exception) { + if (debuggedProcess == null || debuggedProcess.HasExited) { + // Process unexpectedly exited + } else { + throw; + } + } } } - } - - using(new PrintTimes("Graph refresh")) { - // paint the ThreadStaks - graph = new ParallelStacksGraph(); - foreach (var stack in this.currentThreadStacks) - { - if (stack == null) - continue; - if (stack.ThreadStackParent != null && - (stack.ThreadStackChildren == null || stack.ThreadStackChildren.Count == 0)) - continue; - - graph.AddVertex(stack); + + using(new PrintTimes("Graph refresh")) { + // paint the ThreadStaks + graph = new ParallelStacksGraph(); + foreach (var stack in this.currentThreadStacks.FindAll(ts => ts.ThreadStackParent == null)) + { + graph.AddVertex(stack); + + // add the children + AddChildren(stack); + } - // add the children - AddChildren(stack); + surface.SetGraph(graph); } + } + else + { + MessageBox.Show( + "Not yet supported", "Tasks view", MessageBoxButton.OK, MessageBoxImage.Information); - surface.SetGraph(graph); + // TODO : hadle tasks here + if (isMethodView) + { + // build method view for tasks + } + else + { + // normal + } + surface.SetGraph(new ParallelStacksGraph()); } } + + protected override ToolBar BuildToolBar() + { + return ToolBarService.CreateToolBar(this, "/SharpDevelop/Pads/ParallelStacksPad/ToolBar"); + } #endregion + #region Public Properties + + public ParallelStacksView ParallelStacksView { + get { return parallelStacksView; } + set { + parallelStacksView = value; + RefreshPad(); + } + } + + public bool IsMethodView { + get { return isMethodView; } + set { + isMethodView = value; + RefreshPad(); + } + } + + public bool IsZoomControlVisible { + get { return surface.IsZoomControlVisible; } + set { surface.IsZoomControlVisible = value; } + } + + #endregion + #region Private Methods private void OnReset(object sender, EventArgs e) @@ -260,7 +337,8 @@ namespace Debugger.AddIn.Pads.ParallelPad commonParent.UpdateThreadIds(threadIds.ToArray()); commonParent.ItemCollection = parentItems.ToObservable(); commonParent.Process = debuggedProcess; - commonParent.FrameSelected += threadStack_FrameSelected; + commonParent.StackSelected += OnThreadStackSelected; + commonParent.FrameSelected += OnFrameSelected; commonParent.IsSelected = commonParent.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); // add new children foreach (var stack in listOfCurrentStacks) { @@ -283,17 +361,7 @@ namespace Debugger.AddIn.Pads.ParallelPad // update thread ids var parent = commonParent.ThreadStackParent; if (parent != null) { - if (parent.ThreadIds != null) - { - var list = new List(); - foreach (uint id in commonParent.ThreadIds) { - if (!parent.ThreadIds.Contains(id)) { - list.Add(id); - } - } - - parent.UpdateThreadIds(list.ToArray()); - } + parent.UpdateThreadIds(commonParent.ThreadIds.ToArray()); } stack.ThreadStackParent = commonParent; @@ -324,6 +392,73 @@ namespace Debugger.AddIn.Pads.ParallelPad break; } } + + private void CreateMethodViewStacks() + { + var list = + new List, ObservableCollection, List>>(); + + // find all threadstacks that contains the selected frame + for (int i = currentThreadStacks.Count - 1; i >= 0; --i) { + var tuple = currentThreadStacks[i].ItemCollection.SplitStack(selectedFrame, currentThreadStacks[i].ThreadIds); + if (tuple != null) + list.Add(tuple); + } + + currentThreadStacks.Clear(); + + // common + ThreadStack common = new ThreadStack(); + var observ = new ObservableCollection(); + bool dummy = false; + dynamic obj = CreateItem(selectedFrame, selectedFrame.Thread, ref dummy); + obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source; + observ.Add(obj); + common.ItemCollection = observ; + common.StackSelected += OnThreadStackSelected; + common.FrameSelected += OnFrameSelected; + common.UpdateThreadIds(selectedFrame.Thread.ID); + common.Process = debuggedProcess; + common.ThreadStackChildren = new List(); + + // for all thread stacks, split them in 2 : + // one that invokes the method frame, second that get's invoked by current method frame + foreach (var tuple in list) { + // add top + if (tuple.Item1.Count > 0) + { + ThreadStack topStack = new ThreadStack(); + topStack.ItemCollection = tuple.Item1; + topStack.StackSelected += OnThreadStackSelected; + topStack.FrameSelected += OnFrameSelected; + topStack.UpdateThreadIds(tuple.Item3.ToArray()); + common.UpdateThreadIds(tuple.Item3.ToArray()); + topStack.Process = debuggedProcess; + topStack.ThreadStackParent = common; + + currentThreadStacks.Add(topStack); + common.ThreadStackChildren.Add(topStack); + } + + // add bottom + if(tuple.Item2.Count > 0) + { + ThreadStack bottomStack = new ThreadStack(); + bottomStack.ItemCollection = tuple.Item2; + bottomStack.StackSelected += OnThreadStackSelected; + bottomStack.FrameSelected += OnFrameSelected; + bottomStack.UpdateThreadIds(tuple.Item3.ToArray()); + bottomStack.Process = debuggedProcess; + bottomStack.ThreadStackChildren = new List(); + bottomStack.ThreadStackChildren.Add(common); + + currentThreadStacks.Add(bottomStack); + } + } + + currentThreadStacks.Add(common); + common.IsSelected = true; + } private void CreateThreadStack(Thread thread) { @@ -332,22 +467,19 @@ namespace Debugger.AddIn.Pads.ParallelPad return; ThreadStack threadStack = new ThreadStack(); - threadStack.FrameSelected += threadStack_FrameSelected; + threadStack.StackSelected += OnThreadStackSelected; + threadStack.FrameSelected += OnFrameSelected; threadStack.UpdateThreadIds(thread.ID); threadStack.Process = debuggedProcess; - currentThreadStacks.Add(threadStack); - threadStack.ItemCollection = items; - if (debuggedProcess.SelectedThread != null) + + if (debuggedProcess.SelectedThread != null) { threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); - } - - private void threadStack_FrameSelected(object sender, EventArgs e) - { - foreach (var ts in this.currentThreadStacks) { - ts.IsSelected = false; - ts.ClearImages(); + if (selectedFrame == null) + selectedFrame = debuggedProcess.SelectedStackFrame; } + + currentThreadStacks.Add(threadStack); } private ObservableCollection CreateItems(Thread thread) @@ -355,34 +487,9 @@ namespace Debugger.AddIn.Pads.ParallelPad bool lastItemIsExternalMethod = false; var result = new ObservableCollection(); foreach (StackFrame frame in thread.GetCallstack(100)) { - dynamic obj = new ExpandoObject(); - string fullName; - if (frame.HasSymbols) { - // Show the method in the list - fullName = frame.GetMethodName(); - lastItemIsExternalMethod = false; - obj.FontWeight = FontWeights.Normal; - obj.Foreground = Brushes.Black; - } else { - // Show [External methods] in the list - if (lastItemIsExternalMethod) continue; - fullName = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods").Trim(); - obj.FontWeight = FontWeights.Normal; - obj.Foreground = Brushes.Gray; - lastItemIsExternalMethod = true; - } - - if (thread.SelectedStackFrame != null && - thread.ID == debuggedProcess.SelectedThread.ID && - thread.SelectedStackFrame.IP == frame.IP && - thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) - obj.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source; - else - obj.Image = null; - - obj.MethodName = fullName; - - result.Add(obj); + dynamic obj = CreateItem(frame, thread, ref lastItemIsExternalMethod); + if (obj != null) + result.Add(obj); } Utils.DoEvents(debuggedProcess); @@ -390,6 +497,61 @@ namespace Debugger.AddIn.Pads.ParallelPad return result; } + private ExpandoObject CreateItem(StackFrame frame, Thread thread, ref bool lastItemIsExternalMethod) + { + dynamic obj = new ExpandoObject(); + string fullName; + if (frame.HasSymbols) { + // Show the method in the list + fullName = frame.GetMethodName(); + lastItemIsExternalMethod = false; + obj.FontWeight = FontWeights.Normal; + obj.Foreground = Brushes.Black; + } else { + // Show [External methods] in the list + if (lastItemIsExternalMethod) return null; + fullName = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods").Trim(); + obj.FontWeight = FontWeights.Normal; + obj.Foreground = Brushes.Gray; + lastItemIsExternalMethod = true; + } + + if (thread.SelectedStackFrame != null && + thread.ID == debuggedProcess.SelectedThread.ID && + thread.SelectedStackFrame.IP == frame.IP && + thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) { + obj.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source; + obj.IsRunningStackFrame = true; + } + else { + if (selectedFrame != null && frame.GetMethodName() == selectedFrame.GetMethodName()) + obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source; + else + obj.Image = null; + obj.IsRunningStackFrame = false; + } + + obj.MethodName = fullName; + + return obj; + } + + private void OnThreadStackSelected(object sender, EventArgs e) + { + foreach (var ts in this.currentThreadStacks) { + ts.IsSelected = false; + ts.ClearImages(); + } + } + + private void OnFrameSelected(object sender, FrameSelectedEventArgs e) + { + selectedFrame = e.Item; + + if (isMethodView) + RefreshPad(); + } + #endregion } @@ -434,5 +596,34 @@ namespace Debugger.AddIn.Pads.ParallelPad return result; } + + internal static Tuple, ObservableCollection, List> + SplitStack(this ObservableCollection source, StackFrame frame, List threadIds) + { + var bottom = new ObservableCollection(); + var top = new ObservableCollection(); + + int found = 0; + + foreach (dynamic item in source) + { + if (item.MethodName == frame.GetMethodName()) + found = 1; + + if (found >= 1) { + if(found > 1) + bottom.Add(item); + + found++; + } + else + top.Add(item); + } + + var result = + new Tuple, ObservableCollection, List>(top, bottom, threadIds); + + return found > 1 ? result : null; + } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs index 8a360a8c25..ecae0a7f3a 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics; using System.Dynamic; using System.Windows; using System.Windows.Controls; @@ -12,12 +11,24 @@ using System.Windows.Input; using System.Windows.Media; using ICSharpCode.Core.Presentation; -using ICSharpCode.SharpDevelop.Debugging; +using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Gui.Pads; -using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn.Pads.ParallelPad { + public class FrameSelectedEventArgs : EventArgs + { + public StackFrame Item { + get; + private set; + } + + public FrameSelectedEventArgs(StackFrame item) + { + Item = item; + } + } + public partial class ThreadStack : UserControl { public static SolidColorBrush SelectedBrush = new SolidColorBrush(Color.FromRgb(84, 169, 255)); @@ -26,7 +37,9 @@ namespace Debugger.AddIn.Pads.ParallelPad DependencyProperty.Register("IsSelected", typeof(bool), typeof(ThreadStack), new FrameworkPropertyMetadata()); - public event EventHandler FrameSelected; + public event EventHandler StackSelected; + + public event EventHandler FrameSelected; private ObservableCollection itemCollection = new ObservableCollection(); @@ -93,7 +106,13 @@ namespace Debugger.AddIn.Pads.ParallelPad public void UpdateThreadIds(params uint[] threadIds) { - this.threadIds.AddRange(threadIds); + var list = new List(); + foreach (uint id in threadIds) { + if (!this.threadIds.Contains(id)) { + list.Add(id); + } + } + this.threadIds.AddRange(list); if (this.threadIds.Count > 1) this.HeaderText.Text = this.threadIds.Count.ToString() + " Threads"; @@ -104,7 +123,8 @@ namespace Debugger.AddIn.Pads.ParallelPad public void ClearImages() { foreach(dynamic item in itemCollection) { - item.Image = null; + if (!item.IsRunningStackFrame) + item.Image = null; } } @@ -164,20 +184,29 @@ namespace Debugger.AddIn.Pads.ParallelPad if (thread == null) return; - if (FrameSelected != null) - FrameSelected(this, EventArgs.Empty); + if (StackSelected != null) + StackSelected(this, EventArgs.Empty); this.IsSelected = true; dynamic obj = selectedItem; - Process.SelectedThread = thread; + foreach(var frame in thread.Callstack) { if (frame.GetMethodName() == obj.MethodName) { - Process.SelectedThread.SelectedStackFrame = frame; - obj.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source; - ((WindowsDebugger)DebuggerService.CurrentDebugger).JumpToCurrentLine(); + if (!obj.IsRunningStackFrame) + obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source; + + SourcecodeSegment nextStatement = frame.NextStatement; + if (nextStatement != null) { + FileService.JumpToFilePosition( + nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn); + } + + if (FrameSelected != null) + FrameSelected(this, new FrameSelectedEventArgs(frame)); + break; } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs index 8feb17ef46..df3099f8c0 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs @@ -20,17 +20,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads SimpleListViewControl runningThreadsList; Process debuggedProcess; - public override object Control { - get { - return runningThreadsList; - } - } - protected override void InitializeComponents() { runningThreadsList = new SimpleListViewControl(); runningThreadsList.ContextMenu = CreateContextMenuStrip(); runningThreadsList.ItemActivated += RunningThreadsListItemActivate; + panel.Children.Add(runningThreadsList); RedrawContent(); ResourceService.LanguageChanged += delegate { RedrawContent(); }; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs index e6e43021b2..75cbb0bc55 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs @@ -35,15 +35,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads instance = this; } - /// - /// This is not used anywhere, but it is neccessary to be overridden in children of AbstractPadContent. - /// - public override object Control { - get { - return watchList; - } - } - public Process Process { get { return debuggedProcess; } } @@ -58,6 +49,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads watchList.DragEnter += watchList_DragOver; watchList.Drop += watchList_Drop; watchList.KeyUp += watchList_KeyUp; + + panel.Children.Add(watchList); } void watchList_KeyUp(object sender, KeyEventArgs e) diff --git a/src/Main/StartUp/Project/Resources/BitmapResources.resources b/src/Main/StartUp/Project/Resources/BitmapResources.resources index f3ce3bcf6a..b22cc4a10d 100644 Binary files a/src/Main/StartUp/Project/Resources/BitmapResources.resources and b/src/Main/StartUp/Project/Resources/BitmapResources.resources differ