8 changed files with 151 additions and 323 deletions
@ -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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -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"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue