Browse Source

Refactored Threads Pad

newNRvisualizers
David Srbecký 14 years ago
parent
commit
13e147a480
  1. 4
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
  2. 3
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  3. 10
      src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml
  4. 106
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs
  5. 66
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs
  6. 145
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs
  7. 138
      src/AddIns/Debugger/Debugger.AddIn/Pads/ThreadsPad.cs
  8. 2
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

4
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin

@ -89,11 +89,11 @@
class = "ICSharpCode.SharpDevelop.Gui.Pads.LoadedModulesPad" class = "ICSharpCode.SharpDevelop.Gui.Pads.LoadedModulesPad"
defaultPosition = "Bottom, Hidden" /> defaultPosition = "Bottom, Hidden" />
<Pad id = "RunningThreadsPad" <Pad id = "ThreadsPad"
category = "Debugger" category = "Debugger"
title = "${res:MainWindow.Windows.Debug.Threads}" title = "${res:MainWindow.Windows.Debug.Threads}"
icon = "PadIcons.Threads" icon = "PadIcons.Threads"
class = "ICSharpCode.SharpDevelop.Gui.Pads.RunningThreadsPad" class = "ICSharpCode.SharpDevelop.Gui.Pads.ThreadsPad"
defaultPosition = "Bottom, Hidden" /> defaultPosition = "Bottom, Hidden" />
<Pad id = "LocalVarPad" <Pad id = "LocalVarPad"

3
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj

@ -141,7 +141,7 @@
</Compile> </Compile>
<Compile Include="Pads\LoadedModulesPad.cs" /> <Compile Include="Pads\LoadedModulesPad.cs" />
<Compile Include="Pads\LocalVarPad.cs" /> <Compile Include="Pads\LocalVarPad.cs" />
<Compile Include="Pads\RunningThreadsPad.cs" /> <Compile Include="Pads\ThreadsPad.cs" />
<Compile Include="Pads\WatchPad.cs"> <Compile Include="Pads\WatchPad.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
@ -249,7 +249,6 @@
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs"> <Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link> <Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="Pads\RunningThreadsPad.Menu.cs" />
<Compile Include="TreeModel\ValueNode.cs" /> <Compile Include="TreeModel\ValueNode.cs" />
<Compile Include="TreeModel\Utils.cs" /> <Compile Include="TreeModel\Utils.cs" />
<Compile Include="Visualizers\Graph\Drawing\CanvasLocationAdapter.cs" /> <Compile Include="Visualizers\Graph\Drawing\CanvasLocationAdapter.cs" />

10
src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml

@ -87,5 +87,13 @@
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Modules.OrderColumn}" Width="80" DisplayMemberBinding="{Binding Order}"/> <GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Modules.OrderColumn}" Width="80" DisplayMemberBinding="{Binding Order}"/>
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Modules.SymbolsColumn}" Width="130" DisplayMemberBinding="{Binding Symbols}"/> <GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Modules.SymbolsColumn}" Width="130" DisplayMemberBinding="{Binding Symbols}"/>
</GridView> </GridView>
<!-- Threads -->
<GridView x:Key="theadsGridView">
<GridViewColumn Header="{core:Localize Global.ID}" Width="100" DisplayMemberBinding="{Binding ID}"/>
<GridViewColumn Header="{core:Localize Global.Name}" Width="300" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Threads.Priority}" Width="120" DisplayMemberBinding="{Binding Priority}"/>
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Threads.Frozen}" Width="80" DisplayMemberBinding="{Binding Frozen}"/>
</GridView>
</ResourceDictionary> </ResourceDictionary>

106
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs

@ -63,110 +63,4 @@ namespace Debugger.AddIn.Pads.ParallelPad
} }
} }
} }
public class ThreadModel : ViewModelBase
{
Thread thread;
public ThreadModel(Thread thread)
{
if (thread == null)
throw new ArgumentNullException("thread");
this.thread = thread;
}
public Thread Thread {
get { return thread; }
}
public uint ID {
get { return thread.ID; }
}
public string Name {
get { return thread.Name; }
}
public string Priority {
get {
switch (thread.Priority) {
case System.Threading.ThreadPriority.Highest:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Highest");
case System.Threading.ThreadPriority.AboveNormal:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.AboveNormal");
case System.Threading.ThreadPriority.Normal:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Normal");
case System.Threading.ThreadPriority.BelowNormal:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.BelowNormal");
case System.Threading.ThreadPriority.Lowest:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Lowest");
default:
return thread.Priority.ToString();
}
}
}
public string Location {
get {
if (thread.Process.IsPaused && thread.MostRecentStackFrame != null)
return thread.MostRecentStackFrame.MethodInfo.Name;
return ResourceService.GetString("Global.NA");
}
}
public string Frozen {
get {
return ResourceService.GetString(thread.Suspended ? "Global.Yes" : "Global.No");
}
}
}
public class ModuleModel : ViewModelBase
{
Module module;
public ModuleModel(Module module)
{
if (module == null)
throw new ArgumentNullException("module");
this.module = module;
}
public Module Module {
get { return module; }
}
public string Name {
get { return module.Name; }
}
public string Address {
get { return string.Format("{0:X8}", module.BaseAdress); }
}
public string Path {
get {
if (module.IsDynamic)
return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.DynamicModule}");
if (module.IsInMemory)
return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.InMemoryModule}");
return module.FullPath;
}
}
public string Order {
get {
return module.OrderOfLoading.ToString();
}
}
public string Symbols {
get {
if (module.HasSymbols)
return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasSymbols}");
return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasNoSymbols}");
}
}
}
} }

66
src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs

@ -1,66 +0,0 @@
// 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.Collections;
using System.Dynamic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Debugger;
using Debugger.AddIn.Pads.ParallelPad;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Services;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public partial class RunningThreadsPad
{
ContextMenu CreateContextMenuStrip()
{
ContextMenu menu = new ContextMenu();
menu.Opened += FillContextMenuStrip;
return menu;
}
void FillContextMenuStrip(object sender, RoutedEventArgs e)
{
var items = runningThreadsList.SelectedItems;
if (items == null || items.Count == 0) {
e.Handled = true;
return;
}
ThreadModel item = items[0] as ThreadModel;
if (item == null)
return;
ContextMenu menu = sender as ContextMenu;
menu.Items.Clear();
MenuItem freezeItem;
freezeItem = new MenuItem();
freezeItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.Threads.Freeze");
freezeItem.IsChecked = item.Thread.Suspended;
freezeItem.Click +=
delegate {
if (items == null || items.Count == 0) {
e.Handled = true;
return;
}
bool suspended = item.Thread.Suspended;
if (WindowsDebugger.CurrentProcess == null || WindowsDebugger.CurrentProcess.IsRunning) {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotFreezeWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.Freeze}");
return;
}
foreach(ThreadModel current in items.OfType<ThreadModel>()) {
current.Thread.Suspended = !suspended;
}
WindowsDebugger.RefreshPads();
};
menu.Items.Add(freezeItem);
}
}
}

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

@ -1,145 +0,0 @@
// 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 System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Threading;
using Debugger;
using Debugger.AddIn.Pads.Controls;
using Debugger.AddIn.Pads.ParallelPad;
using Debugger.AddIn.TreeModel;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Services;
using Exception = System.Exception;
using Thread = Debugger.Thread;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public partial class RunningThreadsPad : AbstractPadContent
{
DockPanel panel;
ListView runningThreadsList;
ObservableCollection<ThreadModel> runningThreads;
public override object Control {
get { return panel; }
}
public RunningThreadsPad()
{
this.panel = new DockPanel();
runningThreads = new ObservableCollection<ThreadModel>();
runningThreadsList = new ListView();
runningThreadsList.ContextMenu = CreateContextMenuStrip();
runningThreadsList.MouseDoubleClick += RunningThreadsListItemActivate;
runningThreadsList.ItemsSource = runningThreads;
runningThreadsList.View = new GridView();
panel.Children.Add(runningThreadsList);
RedrawContent();
ResourceService.LanguageChanged += delegate { RedrawContent(); };
WindowsDebugger.RefreshingPads += RefreshPad;
RefreshPad();
}
public void RedrawContent()
{
runningThreadsList.ClearColumns();
runningThreadsList.AddColumn(ResourceService.GetString("Global.ID"),
new Binding { Path = new PropertyPath("ID") },
100);
runningThreadsList.AddColumn(ResourceService.GetString("Global.Name"),
new Binding { Path = new PropertyPath("Name") },
300);
runningThreadsList.AddColumn(ResourceService.GetString("AddIns.HtmlHelp2.Location"),
new Binding { Path = new PropertyPath("Location") },
250);
runningThreadsList.AddColumn(ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority"),
new Binding { Path = new PropertyPath("Priority") },
120);
runningThreadsList.AddColumn(ResourceService.GetString("MainWindow.Windows.Debug.Threads.Frozen"),
new Binding { Path = new PropertyPath("Frozen") },
80);
}
protected void RefreshPad()
{
Process process = WindowsDebugger.CurrentProcess;
if (process == null || process.IsRunning) {
runningThreads.Clear();
} else {
process.EnqueueForEach(
Dispatcher.CurrentDispatcher,
process.Threads.ToList(),
t => AddThread(t)
);
}
}
void RunningThreadsListItemActivate(object sender, EventArgs e)
{
ThreadModel obj = runningThreadsList.SelectedItems[0] as ThreadModel;
if (WindowsDebugger.CurrentProcess != null) {
if (WindowsDebugger.CurrentProcess.IsPaused) {
WindowsDebugger.CurrentThread = obj.Thread;
WindowsDebugger.RefreshPads();
// TODO: Jump to current line
} else {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}");
}
}
}
void AddThread(Thread thread)
{
if (thread == null) return;
// remove the object if exists
RemoveThread(thread);
ThreadModel obj = new ThreadModel(thread);
runningThreads.Add(obj);
}
void RemoveThread(Thread thread)
{
if (thread == null)
return;
runningThreads.RemoveWhere(model => model.Thread == thread);
}
}
static class ListViewExtensions
{
public static void ClearColumns(this ListView view)
{
if (view == null)
throw new ArgumentNullException("view");
if (view.View is GridView)
((GridView)view.View).Columns.Clear();
}
public static void AddColumn(this ListView view, string header, Binding binding, double width)
{
if (view == null)
throw new ArgumentNullException("view");
if (view.View is GridView) {
GridViewColumn column = new GridViewColumn {
Width = width,
DisplayMemberBinding = binding,
Header = header };
((GridView)view.View).Columns.Add(column);
}
}
}
}

138
src/AddIns/Debugger/Debugger.AddIn/Pads/ThreadsPad.cs

@ -0,0 +1,138 @@
// 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 System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Debugger;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Services;
using Thread = Debugger.Thread;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class ThreadsPad : AbstractPadContent
{
ListView listView;
public override object Control {
get { return listView; }
}
public ThreadsPad()
{
var res = new CommonResources();
res.InitializeComponent();
ContextMenu contextMenu = new ContextMenu();
contextMenu.Opened += FillContextMenuStrip;
listView = new ListView();
listView.View = (GridView)res["theadsGridView"];
listView.ContextMenu = contextMenu;
listView.MouseDoubleClick += listView_MouseDoubleClick;
WindowsDebugger.RefreshingPads += RefreshPad;
RefreshPad();
}
void RefreshPad()
{
Process process = WindowsDebugger.CurrentProcess;
if (process == null || process.IsRunning) {
listView.ItemsSource = null;
} else {
List<ThreadItem> items = new List<ThreadItem>();
foreach(var thread in process.Threads) {
items.Add(new ThreadItem(thread));
}
listView.ItemsSource = items;
}
}
void listView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ThreadItem item = listView.SelectedItem as ThreadItem;
if (WindowsDebugger.CurrentProcess != null) {
if (WindowsDebugger.CurrentProcess.IsPaused) {
WindowsDebugger.CurrentThread = item.Thread;
WindowsDebugger.Instance.JumpToCurrentLine();
WindowsDebugger.RefreshPads();
} else {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}");
}
}
}
void FillContextMenuStrip(object sender, RoutedEventArgs e)
{
var items = listView.SelectedItems.OfType<ThreadItem>();
// Suspended property is safe to access at any point
bool suspended = items.All(t => t.Thread.Suspended);
ContextMenu menu = sender as ContextMenu;
menu.Items.Clear();
MenuItem freezeItem;
freezeItem = new MenuItem();
freezeItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.Threads.Freeze");
freezeItem.IsChecked = suspended;
freezeItem.Click += delegate {
if (WindowsDebugger.CurrentProcess == null || WindowsDebugger.CurrentProcess.IsRunning) {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotFreezeWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.Freeze}");
return;
}
foreach(ThreadItem item in items.OfType<ThreadItem>()) {
item.Thread.Suspended = !suspended;
}
WindowsDebugger.RefreshPads();
};
menu.Items.Add(freezeItem);
}
}
public class ThreadItem
{
public Thread Thread { get; private set; }
public uint ID { get; private set; }
public string Name { get; private set; }
public string Priority { get; private set; }
public string Frozen { get; private set; }
public ThreadItem(Thread thread)
{
// We want to egarly evaluate the properties while the process is paused
// rather then wait until the GUI acesses them at some unspecified point
this.Thread = thread;
this.ID = thread.ID;
this.Name = thread.Name;
this.Priority = PriorityToString(thread.Priority);
this.Frozen = ResourceService.GetString(thread.Suspended ? "Global.Yes" : "Global.No");
}
static string PriorityToString(System.Threading.ThreadPriority priority)
{
switch (priority) {
case System.Threading.ThreadPriority.Highest:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Highest");
case System.Threading.ThreadPriority.AboveNormal:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.AboveNormal");
case System.Threading.ThreadPriority.Normal:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Normal");
case System.Threading.ThreadPriority.BelowNormal:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.BelowNormal");
case System.Threading.ThreadPriority.Lowest:
return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Lowest");
default:
return ResourceService.GetString("Global.NA");
}
}
}
}

2
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -596,7 +596,7 @@ namespace ICSharpCode.SharpDevelop.Services
CurrentProcess = e.Process; CurrentProcess = e.Process;
CurrentThread = e.Thread; CurrentThread = e.Thread;
CurrentStackFrame = CurrentThread.MostRecentUserStackFrame; CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentUserStackFrame : null;
LoggingService.Info("Jump to current line"); LoggingService.Info("Jump to current line");
JumpToCurrentLine(); JumpToCurrentLine();

Loading…
Cancel
Save