From 3318da248afffeddc26f0bb0321565d374bfe54a Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Mon, 29 Nov 2010 17:44:33 +0200 Subject: [PATCH] Add method view add toolbar to parallel stacks --- data/resources/StringResources.resx | 8 +- .../Icons.48x48.CurrentFrame.png | Bin 0 -> 1643 bytes .../image/BitmapResources/BitmapResources.res | 5 + .../BitmapResources/PadIcons/MethodView.png | Bin 0 -> 3265 bytes .../BitmapResources/PadIcons/ZoomControl.png | Bin 0 -> 733 bytes .../Debugger.AddIn/Debugger.AddIn.addin | 20 +- .../Debugger.AddIn/Debugger.AddIn.csproj | 6 +- .../Commands/ParallelStacksViewCommands.cs | 92 +++++ .../{ => Commands}/SelectLanguageCommand.cs | 94 ++--- .../Pads/{ => Commands}/WatchPadCommands.cs | 0 .../Debugger.AddIn/Pads/DebuggerPad.cs | 107 +++-- .../Debugger.AddIn/Pads/LoadedModulesPad.cs | 7 +- .../Debugger.AddIn/Pads/LocalVarPad.cs | 10 +- .../Debugger.AddIn/Pads/ObjectGraphPad.cs | 148 ++++--- .../Pads/ParallelPad/DrawSurface.xaml | 4 +- .../Pads/ParallelPad/DrawSurface.xaml.cs | 17 +- .../Pads/ParallelPad/ParallelStackPad.cs | 377 +++++++++++++----- .../Pads/ParallelPad/ThreadStack.xaml.cs | 53 ++- .../Debugger.AddIn/Pads/RunningThreadsPad.cs | 7 +- .../Debugger/Debugger.AddIn/Pads/WatchPad.cs | 11 +- .../Resources/BitmapResources.resources | Bin 602659 -> 606280 bytes 21 files changed, 660 insertions(+), 306 deletions(-) create mode 100644 data/resources/image/BitmapResources/BitmapResources-data/Icons.48x48.CurrentFrame.png create mode 100644 data/resources/image/BitmapResources/PadIcons/MethodView.png create mode 100644 data/resources/image/BitmapResources/PadIcons/ZoomControl.png create mode 100644 src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs rename src/AddIns/Debugger/Debugger.AddIn/Pads/{ => Commands}/SelectLanguageCommand.cs (96%) rename src/AddIns/Debugger/Debugger.AddIn/Pads/{ => Commands}/WatchPadCommands.cs (100%) 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 0000000000000000000000000000000000000000..ab2c0923f210f7fc34a82ea701acc3294b790685 GIT binary patch literal 1643 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 @@ -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 f3ce3bcf6aaa88f659835eb3a592d08603492864..b22cc4a10d8021b67129920f297fd98ee1e28771 100644 GIT binary patch delta 5752 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 delta 2768 zcmYjTX;73`7Crs&qZ>qMux%EBW=EC=i3>W&qJjoQ1-A$yG$1>&NegHc9cJPZjp(h4 z#tk{G3pR4M`NjF5{;wInCMJO9ZifiWz^`L?$Vn1@#_2Dd-tAu?z#7V z-KSSXesn9MyVvcq4p0E9Wo7%2{l`jm2O`vC-GPt+_jCu0u2)n+&wSw0c;GglYu*5K z1AukE0S@SajhQ^R0WpJt;a1>S3J^lHH)a5b#sR;Z3KVd8WB}J@0)=w{pHaZQ*}x_l z@8+vJCHvpn~UH-GQ`J;4AX{ zOB^twjCRBuOur?s11A~Fg*JaJf*DWg7#IWeGl?)77fb>CWu?1s=T^FOb9bLNQz=0- zQ++-V*hPxVjX=k6;5)uYF-$nqctqRbq`4~@@bsiywDAZ79y4uQC<{XQ=1}fsO!E=b zVo(&3+K~#tMET!jN&5NBrsOGkaK~9XwiPoM2^}~%DUz)TY)`efyHjX zmQq6T%sUhKB#~955>upNpvB)9323zZ#-I7K7L~5RITD>Ky#t4Kg5kAkOoLRuCynn& zaW1QIhShr%4rJJXPpQ85EMQR@kk7RA#9l(X@kBht4!Fs?u579vOg^K5XH3D!b360< zfYE-Y1T{Xu#X-bj>N%8Z0lQ#LE;@0PCETq8=7j(+2>dMps%Yp%GTn-R1fS33Hk*Lr zcsdRPR`Tu)OSy&VJSzfzBH1j8@JC8@W+HWD8}A_@-$H6kQ3mns7!w>uoEv$-UbcYu z7~&POfGc9DC;|8L;-B+?j|lwv1YjmX=JWkNn_xWwW{~7p<#NX(tn)ex@lH5vP2uV@ z*kbI7NDtuhNMHy{_BwO0k?#d^`gb|-fE=Q7qL6&afG{!nK2Tz3kMJ5s(doG;0)d4V^^0*MN5BpGJYdp?xdUxJ#-Y zjNQ+C^Eomda$-pTG8DA-5$;qOEHnzd6s4LLGjCR-{b)G?CAJgtV z`o2q6AG6BWsoYMsLo2hm&w*TCB)dHW+)63zL$1AY&NE#-nJ%7QQ9(Lp*+2#E8L0$w z(Wu@gHg-w^uwC-Kd?Vv&afpreCRs&L=K!)k8Ni5Sb&6T_6S7d&dqu0-0y*pzt2-t) zy%KZ2CV|i_;6EgHEgtwS$M3KoaEFra8p4kO2|uNK7D?u@e-qhqmncRu`+av9XR?jq zCZG|G@{XV7K!hj?)niLf$sFEC6R~)0x?|XG0>}OWf4iPO`t3Kk2C^`j8aHc`ipK$DMmYL*zKOc4H3%OBdQLDd{ z7iH19^YXmRPtwbcYQo+AX43R-&7GKs3i=Lp?oWl(|V#s-sm^i!7)PRm<&ilQ2EiMzyV7_EaaS%%wbuRHja`*7%C0#zPJ2 z;%m67f6E!Ms>Y;+tkqK-@48^|tTk!o^?HnP?y_nFRC2eJ)~2e(BHL?|wb0Fa4Ch^} zp$7G+K-X6Btjp4>di4C^@U9yz=W7jW%Qo7E%4cmMc8IY)T`m1Y^6OL8 z@!is0KShh$qerHcwnRu_j=Oj+G;4kP^vH2Wp1d$#>*ZgBNiTOHPT)(2<@mxRb@Vg( zhl;5oRuvwVjD~zI5=QaOlwR~8_q~W<5=zQ z=k&-ET~ns~*yy2_U6kjI(-pp!=}pOM;1yZjl&bxFRgYL{ZVr(>E$-Tm8+wd$?);kr zwdUIn#T<8q%|2@OJ!xo;({?|6W%4;qu03{W;xKv99IRqp#L_at<6AcaM$dqqzl9xg zyxJm7^+xrnhiqtxQOQO*(vqUB^EI&1j78@>?yIlNkp1&BS6fAORCm%?g#Hj-LxVTG2OAHnjSxC0VkwHFRXw zWCKjEOta9ACYrU-EIH@@F0!%ke;2v(Ypbs|X_|qfa?Ea)M7xjXmS;e)b5~?HDAOF- zX!n;+yHVYn$JZEjw^aUYk5;#;<+k0T4mC