You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
5.5 KiB
211 lines
5.5 KiB
// 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.SharpDevelop.Debugging; |
|
using ICSharpCode.SharpDevelop.Gui.Pads; |
|
using ICSharpCode.SharpDevelop.Services; |
|
|
|
namespace Debugger.AddIn.Pads.ParallelPad |
|
{ |
|
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 FrameSelected; |
|
|
|
private ObservableCollection<ExpandoObject> itemCollection = new ObservableCollection<ExpandoObject>(); |
|
|
|
private ToolTip toolTip = new ToolTip(); |
|
|
|
public ThreadStack() |
|
{ |
|
InitializeComponent(); |
|
ToolTip = toolTip; |
|
ToolTipOpening += new ToolTipEventHandler(OnToolTipOpening); |
|
} |
|
|
|
public Process Process { 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 ThreadStack ThreadStackParent { get; set; } |
|
|
|
public ThreadStack[] ThreadStackChildren { get; set; } |
|
|
|
public List<uint> ThreadIds { get; set; } |
|
|
|
public ObservableCollection<ExpandoObject> ItemCollection { |
|
get { |
|
return itemCollection; |
|
} |
|
|
|
set { |
|
itemCollection = value; |
|
this.datagrid.ItemsSource = itemCollection; |
|
|
|
if (ThreadIds.Count > 1) |
|
this.HeaderText.Text = ThreadIds.Count.ToString() + " Threads"; |
|
else |
|
this.HeaderText.Text = "1 Thread"; |
|
} |
|
} |
|
|
|
public void ClearImages() |
|
{ |
|
foreach(dynamic item in itemCollection) { |
|
item.Image = null; |
|
} |
|
} |
|
|
|
void SelectParent(bool isSelected) |
|
{ |
|
var ts = this.ThreadStackParent; |
|
while(ts != null) { |
|
ts.IsSelected = isSelected; |
|
ts = ts.ThreadStackParent; |
|
} |
|
} |
|
|
|
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); |
|
} |
|
} |
|
} |
|
|
|
void SelectFrame(uint threadId, ExpandoObject selectedItem) |
|
{ |
|
if (selectedItem == null) |
|
return; |
|
|
|
var thread = Process.Threads.Find(t => t.ID == threadId); |
|
if (thread == null) |
|
return; |
|
|
|
if (FrameSelected != null) |
|
FrameSelected(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(); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
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; |
|
} |
|
|
|
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; |
|
} |
|
|
|
void OnToolTipOpening(object sender, ToolTipEventArgs e) |
|
{ |
|
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()) |
|
{ |
|
// TODO : get method parameter values |
|
TextBlock tb = new TextBlock(); |
|
tb.Text = thread.ID + ": " + CallStackPadContent.GetFullName(frame); |
|
panel.Children.Add(tb); |
|
} |
|
} |
|
} |
|
} |
|
|
|
this.toolTip.Content = panel; |
|
} |
|
} |
|
} |