Browse Source

Merge remote branch 'eusebiu/Parallel'

Conflicts:
	data/resources/StringResources.resx
	data/resources/image/BitmapResources/BitmapResources.res
	src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
	src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs
	src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs
	src/Main/StartUp/Project/Resources/BitmapResources.resources
pull/15/head
Eusebiu Marcu 15 years ago
parent
commit
31df59031a
  1. 8
      data/resources/StringResources.resx
  2. BIN
      data/resources/image/BitmapResources/BitmapResources-data/Icons.48x48.CurrentFrame.png
  3. 6
      data/resources/image/BitmapResources/BitmapResources.res
  4. BIN
      data/resources/image/BitmapResources/PadIcons/MethodView.png
  5. BIN
      data/resources/image/BitmapResources/PadIcons/Parallel.png
  6. BIN
      data/resources/image/BitmapResources/PadIcons/ZoomControl.png
  7. 25
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
  8. 32
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  9. 1
      src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs
  10. 92
      src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs
  11. 0
      src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs
  12. 0
      src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs
  13. 27
      src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs
  14. 7
      src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs
  15. 10
      src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
  16. 6
      src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs
  17. 147
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml
  18. 71
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml.cs
  19. 679
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
  20. 38
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStacksGraph.cs
  21. 54
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/SelectedFrameBookmark.cs
  22. 132
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml
  23. 340
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs
  24. 11
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs
  25. 11
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
  26. 3
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Controls/DragScrollViewer.cs
  27. 14
      src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs
  28. BIN
      src/Main/StartUp/Project/Resources/BitmapResources.resources

8
data/resources/StringResources.resx

@ -5950,7 +5950,13 @@ Shows the full callstack of the error.</comment>
<value>Object Graph</value> <value>Object Graph</value>
</data> </data>
<data name="MainWindow.Windows.Debug.ParallelStack" xml:space="preserve"> <data name="MainWindow.Windows.Debug.ParallelStack" xml:space="preserve">
<value>Parallel Stack</value> <value>Parallel Stacks</value>
</data>
<data name="MainWindow.Windows.Debug.ToggleMethodView" xml:space="preserve">
<value>Toggle Method View</value>
</data>
<data name="MainWindow.Windows.Debug.HideZoomControl" xml:space="preserve">
<value>Show/Hide Zoom Control</value>
</data> </data>
<data name="MainWindow.Windows.Debug.RunToCursor" xml:space="preserve"> <data name="MainWindow.Windows.Debug.RunToCursor" xml:space="preserve">
<value>Run to cursor</value> <value>Run to cursor</value>

BIN
data/resources/image/BitmapResources/BitmapResources-data/Icons.48x48.CurrentFrame.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

6
data/resources/image/BitmapResources/BitmapResources.res

@ -37,6 +37,10 @@ ProjectBrowser.WebReferenceFolder.Closed = ProjectBrowserIcons\WebReferenceFolde
ProjectBrowser.WebReferenceFolder.Open = ProjectBrowserIcons\WebReferenceFolder.Open.png ProjectBrowser.WebReferenceFolder.Open = ProjectBrowserIcons\WebReferenceFolder.Open.png
ProjectBrowser.WebReference = ProjectBrowserIcons\WebReference.png ProjectBrowser.WebReference = ProjectBrowserIcons\WebReference.png
#Parallel Stacks pad
ParallelStacks.MethodView = PadIcons\MethodView.png
ParallelStacks.ZoomControl = PadIcons\ZoomControl.png
#Output pad #Output pad
OutputPad.Toolbar.ClearOutputWindow = OutputPadIcons\ClearOutputWindow.png 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.HtmlElements.FieldSetElement = BitmapResources-data\Icons.16x16.HtmlElements.FieldSetElement.png
Icons.16x16.SplitWindow = BitmapResources-data\Icons.16x16.SplitWindow.png Icons.16x16.SplitWindow = BitmapResources-data\Icons.16x16.SplitWindow.png
Icons.16x16.DeleteHistory = BitmapResources-data\Icons.16x16.DeleteHistory.png Icons.16x16.DeleteHistory = BitmapResources-data\Icons.16x16.DeleteHistory.png
Icons.48x48.CurrentFrame = BitmapResources-data\Icons.48x48.CurrentFrame.png
Icons.16x16.Refresh = BitmapResources-data\Icons.16x16.Refresh.png Icons.16x16.Refresh = BitmapResources-data\Icons.16x16.Refresh.png
Icons.Magnifier = BitmapResources-data\magnifier.png Icons.Magnifier = BitmapResources-data\magnifier.png
@ -249,6 +254,7 @@ PadIcons.LocalVariables = PadIcons\LocalVariables.png
PadIcons.Threads = PadIcons\Threads.png PadIcons.Threads = PadIcons\Threads.png
PadIcons.Exceptions = PadIcons\Exceptions.png PadIcons.Exceptions = PadIcons\Exceptions.png
PadIcons.XPathQuery = PadIcons\XPathQuery.png PadIcons.XPathQuery = PadIcons\XPathQuery.png
PadIcons.Parallel = PadIcons\Parallel.png
#SharpQuery icons #SharpQuery icons
Icons.16x16.SharpQuery.DataBaseRoot = SharpQueryIcons\Icons.16x16.SharpQuery.Database.png Icons.16x16.SharpQuery.DataBaseRoot = SharpQueryIcons\Icons.16x16.SharpQuery.Database.png

BIN
data/resources/image/BitmapResources/PadIcons/MethodView.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
data/resources/image/BitmapResources/PadIcons/Parallel.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
data/resources/image/BitmapResources/PadIcons/ZoomControl.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

25
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin

@ -130,6 +130,13 @@
icon = "PadIcons.LocalVariables" icon = "PadIcons.LocalVariables"
class = "ICSharpCode.SharpDevelop.Gui.Pads.ObjectGraphPad" class = "ICSharpCode.SharpDevelop.Gui.Pads.ObjectGraphPad"
defaultPosition = "Bottom, Hidden" /> defaultPosition = "Bottom, Hidden" />
<Pad id = "ParallelStacksPad"
category = "Debugger"
title = "${res:MainWindow.Windows.Debug.ParallelStack}"
icon = "PadIcons.Parallel"
class = "ICSharpCode.SharpDevelop.Gui.Pads.ParallelStackPad"
defaultPosition = "Bottom, Hidden" />
</Path> </Path>
<Path name ="/SharpDevelop/Pads/WatchPad/ContextMenu"> <Path name ="/SharpDevelop/Pads/WatchPad/ContextMenu">
@ -166,6 +173,24 @@
type="ComboBox" id="SelectLanguageCommand" /> type="ComboBox" id="SelectLanguageCommand" />
</Path> </Path>
<Path name="/SharpDevelop/Pads/ParallelStacksPad/ToolBar">
<ToolbarItem id="View" type="ComboBox" class="ICSharpCode.SharpDevelop.Gui.Pads.ParallelStacksViewCommand"/>
<ToolbarItem id="Separator" type="Separator"/>
<ToolbarItem
id="MethodView"
type="CheckBox"
tooltip="${res:MainWindow.Windows.Debug.ToggleMethodView}"
icon="ParallelStacks.MethodView"
class="ICSharpCode.SharpDevelop.Gui.Pads.ToggleMethodViewCommand"/>
<ToolbarItem
id="ZoomControl"
type="CheckBox"
tooltip="${res:MainWindow.Windows.Debug.HideZoomControl}"
icon="ParallelStacks.ZoomControl"
class="ICSharpCode.SharpDevelop.Gui.Pads.ShowZoomControlCommand"/>
/>
</Path>
<Path name="/SharpDevelop/Services/DebuggerService/Visualizers"> <Path name="/SharpDevelop/Services/DebuggerService/Visualizers">
<Class class="Debugger.AddIn.Visualizers.TextVisualizerDescriptor" /> <Class class="Debugger.AddIn.Visualizers.TextVisualizerDescriptor" />
<Class class="Debugger.AddIn.Visualizers.XmlVisualizerDescriptor" /> <Class class="Debugger.AddIn.Visualizers.XmlVisualizerDescriptor" />

32
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj

@ -58,6 +58,15 @@
<StartProgram>..\..\..\..\bin\SharpDevelop.exe</StartProgram> <StartProgram>..\..\..\..\bin\SharpDevelop.exe</StartProgram>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="GraphSharp">
<HintPath>..\..\..\Libraries\GraphSharp\GraphSharp.dll</HintPath>
</Reference>
<Reference Include="GraphSharp.Controls">
<HintPath>..\..\..\Libraries\GraphSharp\GraphSharp.Controls.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Contracts">
<HintPath>..\..\..\Libraries\GraphSharp\Microsoft.Contracts.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="PresentationCore"> <Reference Include="PresentationCore">
<RequiredTargetFramework>3.0</RequiredTargetFramework> <RequiredTargetFramework>3.0</RequiredTargetFramework>
@ -68,6 +77,9 @@
<Reference Include="PresentationFramework.Aero"> <Reference Include="PresentationFramework.Aero">
<RequiredTargetFramework>3.0</RequiredTargetFramework> <RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="QuickGraph">
<HintPath>..\..\..\Libraries\GraphSharp\QuickGraph.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
@ -89,6 +101,9 @@
<DependentUpon>CallStackPad.xaml</DependentUpon> <DependentUpon>CallStackPad.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Pads\Commands\ParallelStacksViewCommands.cs" />
<Compile Include="Pads\Commands\SelectLanguageCommand.cs" />
<Compile Include="Pads\Commands\WatchPadCommands.cs" />
<Compile Include="Pads\Controls\ConditionCell.xaml.cs"> <Compile Include="Pads\Controls\ConditionCell.xaml.cs">
<DependentUpon>ConditionCell.xaml</DependentUpon> <DependentUpon>ConditionCell.xaml</DependentUpon>
</Compile> </Compile>
@ -101,6 +116,17 @@
<Compile Include="Pads\Controls\WatchList.xaml.cs"> <Compile Include="Pads\Controls\WatchList.xaml.cs">
<DependentUpon>WatchList.xaml</DependentUpon> <DependentUpon>WatchList.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Pads\ParallelPad\DrawSurface.xaml.cs">
<DependentUpon>DrawSurface.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Pads\ParallelPad\ParallelStackPad.cs" />
<Compile Include="Pads\ParallelPad\ParallelStacksGraph.cs" />
<Compile Include="Pads\ParallelPad\SelectedFrameBookmark.cs" />
<Compile Include="Pads\ParallelPad\ThreadStack.xaml.cs">
<DependentUpon>ThreadStack.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Pads\WatchInputBox.xaml.cs"> <Compile Include="Pads\WatchInputBox.xaml.cs">
<DependentUpon>WatchInputBox.xaml</DependentUpon> <DependentUpon>WatchInputBox.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
@ -125,8 +151,6 @@
<DependentUpon>DebuggingSymbolsPanel.cs</DependentUpon> <DependentUpon>DebuggingSymbolsPanel.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Pads\ObjectGraphPad.cs" /> <Compile Include="Pads\ObjectGraphPad.cs" />
<Compile Include="Pads\SelectLanguageCommand.cs" />
<Compile Include="Pads\WatchPadCommands.cs" />
<Compile Include="Pads\BreakPointsPad.cs" /> <Compile Include="Pads\BreakPointsPad.cs" />
<Compile Include="Pads\ConsolePad.cs"> <Compile Include="Pads\ConsolePad.cs">
<SubType>UserControl</SubType> <SubType>UserControl</SubType>
@ -367,6 +391,8 @@
<Page Include="Pads\Controls\ConditionCell.xaml" /> <Page Include="Pads\Controls\ConditionCell.xaml" />
<Page Include="Pads\Controls\SimpleListViewControl.xaml" /> <Page Include="Pads\Controls\SimpleListViewControl.xaml" />
<Page Include="Pads\Controls\WatchList.xaml" /> <Page Include="Pads\Controls\WatchList.xaml" />
<Page Include="Pads\ParallelPad\DrawSurface.xaml" />
<Page Include="Pads\ParallelPad\ThreadStack.xaml" />
<Page Include="Pads\WatchInputBox.xaml" /> <Page Include="Pads\WatchInputBox.xaml" />
<Page Include="Service\EditBreakpointScriptWindow.xaml" /> <Page Include="Service\EditBreakpointScriptWindow.xaml" />
<Page Include="Tooltips\DebuggerTooltipControl.xaml" /> <Page Include="Tooltips\DebuggerTooltipControl.xaml" />
@ -394,7 +420,9 @@
<Name>ICSharpCode.Core.WinForms</Name> <Name>ICSharpCode.Core.WinForms</Name>
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
<Folder Include="Pads\Commands" />
<Folder Include="Pads\Controls" /> <Folder Include="Pads\Controls" />
<Folder Include="Pads\ParallelPad" />
<Folder Include="Tooltips" /> <Folder Include="Tooltips" />
<Folder Include="Visualizers\Graph" /> <Folder Include="Visualizers\Graph" />
<Folder Include="Visualizers\Graph\Drawing" /> <Folder Include="Visualizers\Graph\Drawing" />

1
src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs

@ -216,7 +216,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
bool showModuleNames = DebuggingOptions.Instance.ShowModuleNames; bool showModuleNames = DebuggingOptions.Instance.ShowModuleNames;
StringBuilder name = new StringBuilder(); StringBuilder name = new StringBuilder();
name.Append(frame.MethodInfo.DeclaringType.FullName); name.Append(frame.MethodInfo.DeclaringType.FullName);
name.Append('.'); name.Append('.');
name.Append(frame.MethodInfo.Name); name.Append(frame.MethodInfo.Name);

92
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 ParallelStackPad");
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();
}
}
}

0
src/AddIns/Debugger/Debugger.AddIn/Pads/SelectLanguageCommand.cs → src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs

0
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs → src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs

27
src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs

@ -1,18 +1,38 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // 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) // 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 Debugger;
using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Services; using ICSharpCode.SharpDevelop.Services;
namespace ICSharpCode.SharpDevelop.Gui.Pads namespace ICSharpCode.SharpDevelop.Gui.Pads
{ {
public abstract class DebuggerPad: AbstractPadContent public abstract class DebuggerPad : AbstractPadContent
{ {
protected DockPanel panel;
ToolBar toolbar;
protected WindowsDebugger debugger; protected WindowsDebugger debugger;
public override object Control {
get {
return panel;
}
}
public DebuggerPad() 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; debugger = (WindowsDebugger)DebuggerService.CurrentDebugger;
InitializeComponents(); InitializeComponents();
@ -37,5 +57,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{ {
} }
protected virtual ToolBar BuildToolBar()
{
return null;
}
} }
} }

7
src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs

@ -17,15 +17,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
SimpleListViewControl loadedModulesList; SimpleListViewControl loadedModulesList;
Process debuggedProcess; Process debuggedProcess;
public override object Control {
get {
return loadedModulesList;
}
}
protected override void InitializeComponents() protected override void InitializeComponents()
{ {
loadedModulesList = new SimpleListViewControl(); loadedModulesList = new SimpleListViewControl();
panel.Children.Add(loadedModulesList);
RedrawContent(); RedrawContent();
ResourceService.LanguageChanged += delegate { RedrawContent(); }; ResourceService.LanguageChanged += delegate { RedrawContent(); };
} }

10
src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs

@ -27,15 +27,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
get { return instance; } get { return instance; }
} }
/// <remarks>
/// This is not used anywhere, but it is neccessary to be overridden in children of AbstractPadContent.
/// </remarks>
public override object Control {
get {
return localVarList;
}
}
public Process Process { public Process Process {
get { return debuggedProcess; } get { return debuggedProcess; }
} }
@ -43,6 +34,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
protected override void InitializeComponents() protected override void InitializeComponents()
{ {
localVarList = new WatchList(); localVarList = new WatchList();
panel.Children.Add(localVarList);
} }
protected override void SelectProcess(Process process) protected override void SelectProcess(Process process)

6
src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs

@ -33,13 +33,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
protected override void InitializeComponents() protected override void InitializeComponents()
{ {
objectGraphControl = new ObjectGraphControl(); objectGraphControl = new ObjectGraphControl();
panel.Children.Add(objectGraphControl);
} }
public override object Control {
get {
return objectGraphControl;
}
}
public override void RefreshPad() public override void RefreshPad()
{ {

147
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="Debugger.AddIn.Pads.ParallelPad.DrawSurface" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Debugger.AddIn.Pads.ParallelPad"
xmlns:visControls="clr-namespace:Debugger.AddIn.Visualizers.Controls"
Background="White">
<UserControl.Resources>
<LinearGradientBrush
x:Key="SilverBrushKey"
EndPoint="0,1"
StartPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStop
Offset="0.7"
Color="White" />
<GradientStop
Offset="1"
Color="LightGray" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush
x:Key="SilverPressedBrushKey"
EndPoint="0,1"
StartPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStop
Offset="0.3"
Color="White" />
<GradientStop
Offset="0"
Color="LightGray" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<ControlTemplate
x:Key="ButtonTemplate"
TargetType="Button">
<Border
Width="28"
Height="17"
Name="TheBorder"
CornerRadius="2,2,2,2"
BorderThickness="1"
BorderBrush="LightGray">
<Canvas>
<TextBlock
Canvas.Top="2"
Canvas.Left="1"
Text="Reset"
FontSize="9"
Foreground="LightGray" />
</Canvas>
</Border>
<ControlTemplate.Triggers>
<Trigger
Property="ButtonBase.IsMouseOver"
Value="True">
<Setter
TargetName="TheBorder"
Property="Background"
Value="{StaticResource SilverBrushKey}" />
<Setter
TargetName="TheBorder"
Property="BorderBrush"
Value="Silver" />
</Trigger>
<Trigger
Property="ButtonBase.IsPressed"
Value="True">
<Setter
TargetName="TheBorder"
Property="Background"
Value="{StaticResource SilverPressedBrushKey}" />
<Setter
TargetName="TheBorder"
Property="BorderBrush"
Value="Silver" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="Auto" />
<ColumnDefinition
Width="*" />
</Grid.ColumnDefinitions>
<Canvas x:Name="ZoomControl" Width="40" Visibility="Hidden"
Margin="3,3">
<TextBlock
Foreground="LightGray"
x:Name="PercentText"
HorizontalAlignment="Center">100%</TextBlock>
<Line
X1="0"
Y1="20"
X2="28"
Y2="20"
StrokeThickness="2"
Stroke="LightGray" />
<Slider
Canvas.Top="23"
Name="SliderControl"
Ticks="1,2,3,4,5,6,7,8,9,10"
Opacity=".4"
Value="5"
Interval="1"
TickPlacement="BottomRight"
Minimum="1"
Maximum="10"
Height="100"
Width="30"
Orientation="Vertical"
ValueChanged="SliderControl_ValueChanged" />
<Line
X1="0"
Y1="125"
X2="28"
Y2="125"
StrokeThickness="2"
Stroke="LightGray" />
<Button
Canvas.Top="130"
Name="Reset"
Click="Reset_Click"
Template="{StaticResource ButtonTemplate}" />
</Canvas>
<visControls:DragScrollViewer
x:Name="drawingSurface"
Grid.Column="1">
<Grid
x:Name="ContentControl"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<local:ParallelStacksGraphLayout
x:Name="ParallelStacksLayout"
ShowAllStates="False"
LayoutAlgorithmType="Tree"
IsAnimationEnabled="False"
EdgeRoutingAlgorithmType="Automatic"
EdgeRoutingConstraint="Automatic"
OverlapRemovalConstraint="Automatic"
OverlapRemovalAlgorithmType="FSA" />
</Grid>
</visControls:DragScrollViewer>
</Grid>
</UserControl>

71
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml.cs

@ -0,0 +1,71 @@
// 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;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using Microsoft.Windows.Themes;
namespace Debugger.AddIn.Pads.ParallelPad
{
public partial class DrawSurface : UserControl
{
private ScaleTransform zoom = new ScaleTransform();
public DrawSurface()
{
InitializeComponent();
ContentControl.LayoutTransform = zoom;
}
public void SetGraph(ParallelStacksGraph graph)
{
this.ParallelStacksLayout.Graph = graph;
if (graph == null)
this.ParallelStacksLayout.CancelLayout();
else
this.ParallelStacksLayout.Relayout();
}
public bool IsZoomControlVisible {
get { return ZoomControl.Visibility == Visibility.Visible; }
set {
if (value)
ZoomControl.Visibility = Visibility.Visible;
else
ZoomControl.Visibility = Visibility.Hidden;
}
}
#region Zoom
void SliderControl_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (e.OldValue == 0)
return;
double value = (e.NewValue / 5d) * 100;
this.PercentText.Text = string.Format("{0}%", value);
// zoom canvas
zoom.ScaleX = e.NewValue / 5d;
zoom.ScaleY = e.NewValue / 5d;
zoom.CenterX = drawingSurface.ActualWidth / 2d;
zoom.CenterY = drawingSurface.ActualHeight / 2d;
}
void Reset_Click(object sender, RoutedEventArgs e)
{
this.SliderControl.Value = 5;
}
#endregion
}
}

679
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs

@ -0,0 +1,679 @@
// 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.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Debugger;
using Debugger.AddIn.Pads.ParallelPad;
using Debugger.AddIn.TreeModel;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui.Pads;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public enum ParallelStacksView
{
Threads,
Tasks
}
public class ParallelStackPad : DebuggerPad
{
private DrawSurface surface;
private Process debuggedProcess;
private ParallelStacksGraph graph;
private List<ThreadStack> currentThreadStacks = new List<ThreadStack>();
private ParallelStacksView parallelStacksView;
private StackFrame selectedFrame;
private bool isMethodView;
#region Overrides
protected override void InitializeComponents()
{
surface = new DrawSurface();
panel.Children.Add(surface);
}
protected override void SelectProcess(Process process)
{
if (debuggedProcess != null) {
debuggedProcess.Paused -= OnProcessPaused;
}
debuggedProcess = process;
if (debuggedProcess != null) {
debuggedProcess.Paused += OnProcessPaused;
}
DebuggerService.DebugStarted += OnReset;
DebuggerService.DebugStopped += OnReset;
RefreshPad();
}
public override void RefreshPad()
{
if (debuggedProcess == null || debuggedProcess.IsRunning) {
return;
}
LoggingService.InfoFormatted("Start refresh: {0}" + Environment.NewLine, parallelStacksView);
currentThreadStacks.Clear();
using(new PrintTimes("Create stacks")) {
try {
// create all simple ThreadStacks
foreach (Thread thread in debuggedProcess.Threads) {
if (debuggedProcess.IsPaused) {
Utils.DoEvents(debuggedProcess);
}
CreateThreadStack(thread);
}
}
catch(AbortedBecauseDebuggeeResumedException) { }
catch(System.Exception) {
if (debuggedProcess == null || debuggedProcess.HasExited) {
// Process unexpectedly exited
} else {
throw;
}
}
}
using(new PrintTimes("Run algorithm")) {
if (isMethodView)
{
// build method view for threads
CreateMethodViewStacks();
}
else
{
// normal view
CreateCommonStacks();
}
}
using(new PrintTimes("Graph refresh")) {
// paint the ThreadStaks
graph = new ParallelStacksGraph();
foreach (var stack in this.currentThreadStacks.FindAll(ts => ts.ThreadStackParents == null ))
{
graph.AddVertex(stack);
// add the children
AddChildren(stack);
}
surface.SetGraph(graph);
}
}
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)
{
currentThreadStacks.Clear();
selectedFrame = null;
// remove all
BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark);
}
private void OnProcessPaused(object sender, ProcessEventArgs e)
{
RefreshPad();
}
private void AddChildren(ThreadStack parent)
{
if(parent.ThreadStackChildren == null || parent.ThreadStackChildren.Count == 0)
return;
foreach (var ts in parent.ThreadStackChildren)
{
if (ts == null) continue;
graph.AddVertex(ts);
graph.AddEdge(new ParallelStacksEdge(parent, ts));
if (ts.ThreadStackChildren == null || ts.ThreadStackChildren.Count == 0)
continue;
AddChildren(ts);
}
}
private void CreateCommonStacks()
{
// stack.ItemCollection order
// 0 -> top of stack = S.C
// 1 -> ............ = S.B
// .......................
// n -> bottom of stack = [External Methods]
// ThreadStacks with common frame
var commonFrameThreads = new Dictionary<string, List<ThreadStack>>();
bool isOver = false;
while (true) {
for (int i = currentThreadStacks.Count - 1; i >=0; --i) {
var stack = currentThreadStacks[i];
if (stack.ItemCollection.Count == 0) {
currentThreadStacks.Remove(stack);
continue;
}
}
//get all thread stacks with common start frame
foreach (var stack in currentThreadStacks) {
int count = stack.ItemCollection.Count;
dynamic frame = stack.ItemCollection[count - 1];
string fullname = frame.MethodName + stack.Level.ToString();
if (!commonFrameThreads.ContainsKey(fullname))
commonFrameThreads.Add(fullname, new List<ThreadStack>());
if (!commonFrameThreads[fullname].Contains(stack))
commonFrameThreads[fullname].Add(stack);
}
// for every list of common stacks, find split place and add them to currentThreadStacks
foreach (var frameName in commonFrameThreads.Keys) {
var listOfCurrentStacks = commonFrameThreads[frameName];
if (listOfCurrentStacks.Count == 1) // just skip the parents
{
isOver = true; // we finish when all are pseodo-parents: no more spliting
continue;
}
isOver = false;
// find the frameIndex where we can split
int frameIndex = 0;
string fn = string.Empty;
bool canContinue = true;
while(canContinue) {
for (int i = 0; i < listOfCurrentStacks.Count; ++i) {
var stack = listOfCurrentStacks[i];
if (stack.ItemCollection.Count == frameIndex)
{
canContinue = false;
break;
}
dynamic item = stack.ItemCollection[stack.ItemCollection.Count - frameIndex - 1];
string currentName = item.MethodName;
if (i == 0) {
fn = currentName;
continue;
}
if (fn == currentName)
continue;
else {
canContinue = false;
break;
}
}
if (canContinue)
frameIndex++;
}
// remove last [frameIndex] and create a new ThreadStack as the parent of what remained in the children
var threadIds = new List<uint>();
var parentItems = new Stack<ExpandoObject>();
while (frameIndex > 0) {
for (int i = 0 ; i < listOfCurrentStacks.Count; ++i) {
var stack = listOfCurrentStacks[i];
int indexToRemove = stack.ItemCollection.Count - 1;
#if DEBUG
dynamic d_item = stack.ItemCollection[indexToRemove];
string name = d_item.MethodName;
#endif
if (i == 0)
parentItems.Push(stack.ItemCollection[indexToRemove]);
stack.ItemCollection.RemoveAt(indexToRemove);
}
frameIndex--;
}
// update thread ids
for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
threadIds.AddRange(listOfCurrentStacks[i].ThreadIds);
// remove stacks with no items
for (int i = listOfCurrentStacks.Count - 1; i >= 0; --i) {
var stack = listOfCurrentStacks[i];
if (stack.ItemCollection.Count == 0)
listOfCurrentStacks.Remove(stack);
}
// increase the Level
for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
listOfCurrentStacks[i].Level++;
// create new parent stack
ThreadStack commonParent = new ThreadStack();
commonParent.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, threadIds.ToArray());
commonParent.ItemCollection = parentItems.ToObservable();
commonParent.Process = debuggedProcess;
commonParent.StackSelected += OnThreadStackSelected;
commonParent.FrameSelected += OnFrameSelected;
commonParent.IsSelected = commonParent.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
// add new children
foreach (var stack in listOfCurrentStacks) {
if (stack.ItemCollection.Count == 0)
{
currentThreadStacks.Remove(stack);
continue;
}
dynamic item = stack.ItemCollection[stack.ItemCollection.Count - 1];
// add the parent to the parent
if (stack.ThreadStackParents != null) {
// remove stack from it's parent because it will have the commonParent as parent
stack.ThreadStackParents[0].ThreadStackChildren.Remove(stack);
commonParent.ThreadStackParents = stack.ThreadStackParents.Clone();
commonParent.ThreadStackParents[0].ThreadStackChildren.Add(commonParent);
// set level
commonParent.Level = stack.Level - 1;
}
else
stack.ThreadStackParents = new List<ThreadStack>();
// update thread ids
if (commonParent.ThreadStackParents != null) {
commonParent.ThreadStackParents[0].UpdateThreadIds(
parallelStacksView == ParallelStacksView.Tasks,
commonParent.ThreadIds.ToArray());
}
stack.ThreadStackParents.Clear();
stack.ThreadStackParents.Add(commonParent);
string currentName = item.MethodName + stack.Level.ToString();;
// add name or add to list
if (!commonFrameThreads.ContainsKey(currentName)) {
var newList = new List<ThreadStack>();
newList.Add(stack);
commonFrameThreads.Add(currentName, newList);
}
else {
var list = commonFrameThreads[currentName];
list.Add(stack);
}
}
commonParent.ThreadStackChildren = listOfCurrentStacks.Clone();
commonFrameThreads[frameName].Clear();
commonFrameThreads[frameName].Add(commonParent);
currentThreadStacks.Add(commonParent);
// exit and retry
break;
}
if (isOver || currentThreadStacks.Count == 0)
break;
}
}
private void CreateMethodViewStacks()
{
var list =
new List<Tuple<ObservableCollection<ExpandoObject>, ObservableCollection<ExpandoObject>, List<uint>>>();
// 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<ExpandoObject>();
bool dummy = false;
dynamic obj = CreateItemForFrame(selectedFrame, ref dummy);
obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
observ.Add(obj);
common.ItemCollection = observ;
common.StackSelected += OnThreadStackSelected;
common.FrameSelected += OnFrameSelected;
common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, selectedFrame.Thread.ID);
common.Process = debuggedProcess;
common.ThreadStackChildren = new List<ThreadStack>();
common.ThreadStackParents = new List<ThreadStack>();
// 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(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
topStack.Process = debuggedProcess;
topStack.ThreadStackParents = new List<ThreadStack>();
topStack.ThreadStackParents.Add(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(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
bottomStack.Process = debuggedProcess;
bottomStack.ThreadStackChildren = new List<ThreadStack>();
bottomStack.ThreadStackChildren.Add(common);
common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
common.ThreadStackParents.Add(bottomStack);
currentThreadStacks.Add(bottomStack);
}
}
currentThreadStacks.Add(common);
common.IsSelected = true;
}
private void CreateThreadStack(Thread thread)
{
var items = CreateItems(thread);
if (items == null || items.Count == 0)
return;
ThreadStack threadStack = new ThreadStack();
threadStack.StackSelected += OnThreadStackSelected;
threadStack.FrameSelected += OnFrameSelected;
threadStack.Process = debuggedProcess;
threadStack.ItemCollection = items;
threadStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, thread.ID);
if (debuggedProcess.SelectedThread != null) {
threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
if (selectedFrame == null)
selectedFrame = debuggedProcess.SelectedStackFrame;
}
currentThreadStacks.Add(threadStack);
}
private ObservableCollection<ExpandoObject> CreateItems(Thread thread)
{
bool lastItemIsExternalMethod = false;
int noTasks = 0;
var result = new ObservableCollection<ExpandoObject>();
var callstack = thread.GetCallstack(100);
if (parallelStacksView == ParallelStacksView.Threads) {
foreach (StackFrame frame in callstack) {
dynamic obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod);
if (obj != null)
result.Add(obj);
}
} else {
for (int i = 0 ; i < callstack.Length; ++i) {
StackFrame frame = callstack[i];
dynamic obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod);
if (frame.MethodInfo.FullName.IndexOf("System.Threading.Tasks.Task.ExecuteEntry") != -1) {
noTasks++;
}
if (noTasks == 1) {
if (frame.HasSymbols) {
// create thread stack for the items collected until now
ThreadStack threadStack = new ThreadStack();
threadStack.StackSelected += OnThreadStackSelected;
threadStack.FrameSelected += OnFrameSelected;
threadStack.Process = debuggedProcess;
threadStack.ItemCollection = result.Clone();
threadStack.UpdateThreadIds(true, frame.Thread.ID);
if (debuggedProcess.SelectedThread != null) {
threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
if (selectedFrame == null)
selectedFrame = debuggedProcess.SelectedStackFrame;
}
currentThreadStacks.Add(threadStack);
// reset
result.Clear();
noTasks = 0;
}
}
if (obj != null)
result.Add(obj);
}
Utils.DoEvents(debuggedProcess);
// return null if we are dealing with a simple thread
return noTasks == 0 ? null : result;
}
Utils.DoEvents(debuggedProcess);
return result;
}
private ExpandoObject CreateItemForFrame(StackFrame frame, 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 (frame.Thread.SelectedStackFrame != null &&
frame.Thread.ID == debuggedProcess.SelectedThread.ID &&
frame.Thread.SelectedStackFrame.IP == frame.IP &&
frame.Thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) {
obj.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source;
obj.IsRunningStackFrame = true;
} else {
if (selectedFrame != null && frame.Thread.ID == selectedFrame.Thread.ID &&
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 ToggleSelectedFrameBookmark(Location location)
{
// remove all
BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark);
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider;
if (provider != null) {
ITextEditor editor = provider.TextEditor;
BookmarkManager.AddMark(new SelectedFrameBookmark(editor.FileName, location));
}
}
private void OnThreadStackSelected(object sender, EventArgs e)
{
foreach (var ts in this.currentThreadStacks) {
if (ts.IsSelected)
ts.IsSelected = false;
ts.ClearImages();
}
}
private void OnFrameSelected(object sender, FrameSelectedEventArgs e)
{
selectedFrame = e.Item;
ToggleSelectedFrameBookmark(e.Location);
if (isMethodView)
RefreshPad();
}
#endregion
}
internal static class StackFrameExtensions
{
internal static string GetMethodName(this StackFrame frame)
{
if (frame == null)
return null;
StringBuilder name = new StringBuilder();
name.Append(frame.MethodInfo.DeclaringType.FullName);
name.Append('.');
name.Append(frame.MethodInfo.Name);
return name.ToString();
}
}
internal static class ParallelStackExtensions
{
internal static List<T> Clone<T>(this List<T> listToClone)
{
if (listToClone == null)
return null;
var result = new List<T>();
foreach (var item in listToClone)
result.Add(item);
return result;
}
internal static ObservableCollection<T> Clone<T>(this ObservableCollection<T> collectionToClone)
{
if (collectionToClone == null)
return null;
var result = new ObservableCollection<T>();
foreach (var item in collectionToClone)
result.Add(item);
return result;
}
internal static ObservableCollection<T> ToObservable<T>(this Stack<T> stack)
{
if (stack == null)
throw new NullReferenceException("Stack is null!");
var result = new ObservableCollection<T>();
while (stack.Count > 0)
result.Add(stack.Pop());
return result;
}
internal static Tuple<ObservableCollection<T>, ObservableCollection<T>, List<uint>>
SplitStack<T>(this ObservableCollection<T> source, StackFrame frame, List<uint> threadIds)
{
var bottom = new ObservableCollection<T>();
var top = new ObservableCollection<T>();
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<T>, ObservableCollection<T>, List<uint>>(top, bottom, threadIds);
return found > 1 ? result : null;
}
}
}

38
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStacksGraph.cs

@ -0,0 +1,38 @@
// 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 QuickGraph;
using GraphSharp.Algorithms.Layout;
using GraphSharp.Algorithms.Layout.Contextual;
using GraphSharp.Algorithms.Layout.Simple.Tree;
using GraphSharp.Controls;
namespace Debugger.AddIn.Pads.ParallelPad
{
public class ParallelStacksEdge : QuickGraph.Edge<ThreadStack>
{
public ParallelStacksEdge(ThreadStack source, ThreadStack target) : base(source, target)
{ }
}
public class ParallelStacksGraph : BidirectionalGraph<ThreadStack, ParallelStacksEdge>
{
public ParallelStacksGraph()
{ }
}
public class ParallelStacksGraphLayout : GraphLayout<ThreadStack, ParallelStacksEdge, ParallelStacksGraph>
{
public ParallelStacksGraphLayout()
{
// TODO : Replace the current tree layout with EfficientSugiyama layout when Direction is available for this type of layout
var par = new SimpleTreeLayoutParameters();
par.LayerGap = 30;
par.VertexGap = 50;
par.Direction = LayoutDirection.BottomToTop;
par.SpanningTreeGeneration = SpanningTreeGeneration.DFS;
this.LayoutParameters = par;
}
}
}

54
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/SelectedFrameBookmark.cs

@ -0,0 +1,54 @@
// 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.Media;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Editor;
namespace Debugger.AddIn.Pads.ParallelPad
{
public class SelectedFrameBookmark : SDMarkerBookmark
{
public static readonly IImage SelectedFrameImage = new ResourceServiceImage("Icons.48x48.CurrentFrame");
public SelectedFrameBookmark(FileName fileName, Location location) : base(fileName, location)
{
this.IsVisibleInBookmarkPad = false;
}
/// <summary>
/// <inheritdoc/>
/// </summary>
public override bool CanToggle {
get {
return false;
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
public override IImage Image {
get {
return SelectedFrameImage;
}
}
/// <summary>
/// <inheritdoc/>
/// </summary>
/// <param name="markerService"><inheritdoc/></param>
/// <returns><inheritdoc/></returns>
protected override ITextMarker CreateMarker(ITextMarkerService markerService)
{
IDocumentLine line = this.Document.GetLine(this.LineNumber);
ITextMarker marker = markerService.Create(line.Offset, line.Length);
marker.BackgroundColor = Color.FromRgb(162, 208, 80);
marker.ForegroundColor = Colors.White;
return marker;
}
}
}

132
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="Debugger.AddIn.Pads.ParallelPad.ThreadStack" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="Auto"
Height="Auto"
Background="Transparent">
<UserControl.Resources>
<LinearGradientBrush x:Key="RowBackground" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#F7F7F7" Offset="0.2"/>
<GradientStop Color="#EAEAEA" Offset=".5"/>
<GradientStop Color="#E5E5E5" Offset=".8"/>
</LinearGradientBrush>
</UserControl.Resources>
<Border
x:Name="BorderParent"
BorderBrush="Black"
BorderThickness="3"
CornerRadius="5"
Height="Auto">
<StackPanel
Background="Transparent"
Margin="-5">
<Border
Height="23"
Margin="5,5,5,0"
CornerRadius="5,5,0,0"
BorderBrush="Transparent">
<Border.Background>
<LinearGradientBrush
StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop
Color="#FFE2F6FE"
Offset="0" />
<GradientStop
Color="White"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<TextBlock
VerticalAlignment="Center"
x:Name="HeaderText"
FontFamily="Khmer UI"
FontSize="12"
Margin="2"
HorizontalAlignment="Center" />
</Border>
<DataGrid
Background="Transparent"
Margin="5,0,5,5"
x:Name="datagrid"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled"
GridLinesVisibility="None"
RowHeight="18"
SelectionMode="Single"
SelectionUnit="FullRow"
ItemsSource="{Binding}"
AutoGenerateColumns="False"
CanUserAddRows="False"
HeadersVisibility="None"
BorderThickness="0"
MouseDoubleClick="Datagrid_MouseDoubleClick"
MouseRightButtonUp="Datagrid_MouseRightButtonUp">
<DataGrid.CellStyle>
<Style
TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="White"/>
<Setter
Property="Focusable"
Value="false" />
<Setter
Property="BorderThickness"
Value="0" />
<Style.Triggers>
<Trigger
Property="IsSelected"
Value="True">
<!-- disable selection highlight -->
<Setter
Property="Foreground"
Value="Black" />
<Setter
Property="Background"
Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Background" Value="White"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource RowBackground}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="0,1,1,0" Width="25" Height="22">
<Image VerticalAlignment="Center" Margin="0,-5,0,0" Width="14" Height="14" HorizontalAlignment="Center"
Source="{Binding Image}" />
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn
Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="0,1,0,0">
<TextBlock Margin="5,0,10,0"
VerticalAlignment="Center"
FontFamily="Khmer UI"
FontSize="12"
Text="{Binding Path=MethodName}"
FontWeight="{Binding Path=FontWeight}"
Foreground="{Binding Path=Foreground}"
/>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</Border>
</UserControl>

340
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs

@ -0,0 +1,340 @@
// 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.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui.Pads;
namespace Debugger.AddIn.Pads.ParallelPad
{
public class FrameSelectedEventArgs : EventArgs
{
public StackFrame Item {
get;
private set;
}
public Location Location {
get;
private set;
}
public FrameSelectedEventArgs(StackFrame item, Location location)
{
Item = item;
Location = location;
}
}
public partial class ThreadStack : UserControl
{
public static SolidColorBrush SelectedBrush = new SolidColorBrush(Color.FromRgb(84, 169, 255));
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.Register("IsSelected", typeof(bool), typeof(ThreadStack),
new FrameworkPropertyMetadata());
public event EventHandler StackSelected;
public event EventHandler<FrameSelectedEventArgs> FrameSelected;
private ObservableCollection<ExpandoObject> itemCollection = new ObservableCollection<ExpandoObject>();
private ToolTip toolTip = new ToolTip();
private List<uint> threadIds = new List<uint>();
public ThreadStack()
{
InitializeComponent();
datagrid.ToolTip = toolTip;
datagrid.ToolTipOpening += OnToolTipOpening;
datagrid.PreviewMouseMove += new MouseEventHandler(datagrid_PreviewMouseMove);
datagrid.MouseLeave += delegate { toolTip.IsOpen = false; };
}
#region Public Properties
public Process Process { get; set; }
public int Level { get; set; }
public bool IsSelected {
get { return (bool)GetValue(IsSelectedProperty); }
set {
if (value) {
BorderParent.BorderBrush = SelectedBrush;
BorderParent.BorderThickness = new Thickness(5);
}
else {
BorderParent.BorderBrush = Brushes.Black;
BorderParent.BorderThickness = new Thickness(3);
}
SetValue(IsSelectedProperty, value);
SelectParent(value);
}
}
public List<ThreadStack> ThreadStackParents { get; set; }
public List<ThreadStack> ThreadStackChildren { get; set; }
public List<uint> ThreadIds {
get {
return threadIds;
}
}
public ObservableCollection<ExpandoObject> ItemCollection {
get {
return itemCollection;
}
set {
itemCollection = value;
this.datagrid.ItemsSource = itemCollection;
}
}
#endregion
#region Public Methods
public void UpdateThreadIds(bool isTask, params uint[] threadIds)
{
var list = new List<uint>();
foreach (uint id in threadIds) {
if (!this.threadIds.Contains(id)) {
list.Add(id);
}
}
this.threadIds.AddRange(list);
if (this.threadIds.Count > 1) {
string suffix = isTask ? " Tasks" : " Threads";
this.HeaderText.Text = this.threadIds.Count.ToString() + suffix;
}
else {
this.HeaderText.Text = isTask ? "1 Task" : "1 Thread";
}
}
public void ClearImages()
{
foreach(dynamic item in itemCollection) {
if (!item.IsRunningStackFrame)
item.Image = null;
}
}
#endregion
#region Private Methods
private void SelectParent(bool isSelected)
{
if (this.ThreadStackParents == null || this.ThreadStackParents.Count == 0)
return;
foreach (var ts in this.ThreadStackParents)
if (ts != null)
ts.IsSelected = isSelected;
}
void datagrid_PreviewMouseMove(object sender, MouseEventArgs e)
{
var result = VisualTreeHelper.HitTest(this, e.GetPosition(this));
if (result != null)
{
var row = TryFindParent<DataGridRow>(result.VisualHit);
if (row != null)
{
datagrid.SelectedItem = row.DataContext;
e.Handled = true;
}
}
}
private void Datagrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (Process.IsRunning) return;
dynamic selectedItem = datagrid.SelectedItem;
if (selectedItem != null) {
if (ThreadIds.Count > 1) {
datagrid.ContextMenu = CreateContextMenu(selectedItem);
datagrid.ContextMenu.IsOpen = true;
}
else
{
SelectFrame(ThreadIds[0], selectedItem);
}
}
}
private void SelectFrame(uint threadId, ExpandoObject selectedItem)
{
if (selectedItem == null)
return;
var thread = Process.Threads.Find(t => t.ID == threadId);
if (thread == null)
return;
if (StackSelected != null)
StackSelected(this, EventArgs.Empty);
this.IsSelected = true;
dynamic obj = selectedItem;
foreach(var frame in thread.Callstack)
{
if (frame.GetMethodName() == obj.MethodName)
{
if (!obj.IsRunningStackFrame)
obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
SourcecodeSegment nextStatement = frame.NextStatement;
if (nextStatement != null) {
var location = new Location(nextStatement.StartColumn, nextStatement.StartLine);
FileService.JumpToFilePosition(
nextStatement.Filename, location.Line, location.Column);
if (FrameSelected != null)
FrameSelected(this, new FrameSelectedEventArgs(frame, location));
}
break;
}
}
}
private void Datagrid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (Process.IsRunning) return;
dynamic selectedItem = datagrid.SelectedItem;
if (selectedItem == null)
return;
datagrid.ContextMenu = CreateContextMenu(selectedItem);
datagrid.ContextMenu.IsOpen = true;
}
private ContextMenu CreateContextMenu(ExpandoObject item)
{
dynamic obj = item;
var menu = new ContextMenu();
foreach (var id in ThreadIds)
{
MenuItem m = new MenuItem();
m.IsCheckable = true;
m.IsChecked = id == Process.SelectedThread.ID;
m.Click += delegate(object sender, RoutedEventArgs e) {
var menuItem = e.OriginalSource as MenuItem;
SelectFrame((uint)menuItem.Tag, item);
};
m.Tag = id;
m.Header = id.ToString() + ":" + obj.MethodName;
menu.Items.Add(m);
}
return menu;
}
private void OnToolTipOpening(object sender, ToolTipEventArgs e)
{
if (Process.IsRunning)
return;
StackPanel panel = new StackPanel();
dynamic selectedItem = datagrid.SelectedItem;
if (selectedItem == null) {
panel.Children.Add(new TextBlock { Text = "No item selected" });
this.toolTip.Content = panel;
return;
}
foreach(var thread in Process.Threads)
{
if (ThreadIds.Contains(thread.ID))
{
foreach (var frame in thread.Callstack)
{
if (selectedItem.MethodName == frame.GetMethodName())
{
TextBlock tb = new TextBlock();
tb.Text = thread.ID + ": " + CallStackPadContent.GetFullName(frame);
panel.Children.Add(tb);
}
}
}
}
this.toolTip.Content = panel;
}
#endregion
#region Static Methods
private static T TryFindParent<T>(DependencyObject child) where T : DependencyObject
{
if (child is T) return child as T;
DependencyObject parentObject = GetParentObject(child);
if (parentObject == null) return null;
var parent = parentObject as T;
if (parent != null && parent is T)
{
return parent;
}
else
{
return TryFindParent<T>(parentObject);
}
}
private static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
DependencyObject parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
FrameworkContentElement fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
FrameworkElement frameworkElement = child as FrameworkElement;
if (frameworkElement != null)
{
DependencyObject parent = frameworkElement.Parent;
if (parent != null) return parent;
}
return VisualTreeHelper.GetParent(child);
}
#endregion
}
}

11
src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs

@ -22,17 +22,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
SimpleListViewControl runningThreadsList; SimpleListViewControl runningThreadsList;
Process debuggedProcess; Process debuggedProcess;
public override object Control {
get {
return runningThreadsList;
}
}
protected override void InitializeComponents() protected override void InitializeComponents()
{ {
runningThreadsList = new SimpleListViewControl(); runningThreadsList = new SimpleListViewControl();
runningThreadsList.ContextMenu = CreateContextMenuStrip(); runningThreadsList.ContextMenu = CreateContextMenuStrip();
runningThreadsList.ItemActivated += RunningThreadsListItemActivate; runningThreadsList.ItemActivated += RunningThreadsListItemActivate;
panel.Children.Add(runningThreadsList);
RedrawContent(); RedrawContent();
ResourceService.LanguageChanged += delegate { RedrawContent(); }; ResourceService.LanguageChanged += delegate { RedrawContent(); };
@ -147,7 +142,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (item == null) return; if (item == null) return;
var thread = item.Tag as Thread; var thread = item.Tag as Thread;
if (thread == null) return; if (thread == null)
return;
item.ID = thread.ID; item.ID = thread.ID;
item.Tag = thread; item.Tag = thread;
StackFrame location = null; StackFrame location = null;

11
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs

@ -36,15 +36,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
instance = this; instance = this;
} }
/// <remarks>
/// This is not used anywhere, but it is neccessary to be overridden in children of AbstractPadContent.
/// </remarks>
public override object Control {
get {
return watchList;
}
}
public Process Process { public Process Process {
get { return debuggedProcess; } get { return debuggedProcess; }
} }
@ -59,6 +50,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
watchList.DragEnter += watchList_DragOver; watchList.DragEnter += watchList_DragOver;
watchList.Drop += watchList_Drop; watchList.Drop += watchList_Drop;
watchList.KeyUp += watchList_KeyUp; watchList.KeyUp += watchList_KeyUp;
panel.Children.Add(watchList);
} }
void watchList_KeyUp(object sender, KeyEventArgs e) void watchList_KeyUp(object sender, KeyEventArgs e)

3
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Controls/DragScrollViewer.cs

@ -19,6 +19,9 @@ namespace Debugger.AddIn.Visualizers.Controls
public DragScrollViewer() : base() public DragScrollViewer() : base()
{ {
this.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
this.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
this.PreviewMouseDown += new System.Windows.Input.MouseButtonEventHandler(DragScrollViewer_PreviewMouseDown); this.PreviewMouseDown += new System.Windows.Input.MouseButtonEventHandler(DragScrollViewer_PreviewMouseDown);
this.PreviewMouseMove += new System.Windows.Input.MouseEventHandler(DragScrollViewer_PreviewMouseMove); this.PreviewMouseMove += new System.Windows.Input.MouseEventHandler(DragScrollViewer_PreviewMouseMove);
this.PreviewMouseUp += new System.Windows.Input.MouseButtonEventHandler(DragScrollViewer_PreviewMouseUp); this.PreviewMouseUp += new System.Windows.Input.MouseButtonEventHandler(DragScrollViewer_PreviewMouseUp);

14
src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs

@ -17,6 +17,20 @@ namespace Debugger
set { selected = value; } set { selected = value; }
} }
public Thread Find(Predicate<Thread> predicate)
{
if (predicate == null)
return null;
foreach (var thread in this)
{
if (predicate(thread))
return thread;
}
return null;
}
internal bool Contains(ICorDebugThread corThread) internal bool Contains(ICorDebugThread corThread)
{ {
foreach(Thread thread in this) { foreach(Thread thread in this) {

BIN
src/Main/StartUp/Project/Resources/BitmapResources.resources

Binary file not shown.
Loading…
Cancel
Save