diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin index 4352c6bc17..b79f5d4de9 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin @@ -89,11 +89,11 @@ class = "ICSharpCode.SharpDevelop.Gui.Pads.LoadedModulesPad" defaultPosition = "Bottom, Hidden" /> - - + Component @@ -249,7 +249,6 @@ Properties\GlobalAssemblyInfo.cs - diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml index 5eca746fb7..f124ab42f0 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml @@ -87,5 +87,13 @@ - + + + + + + + + + \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs index e7266ebcff..e829345310 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs +++ b/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}"); - } - } - } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs deleted file mode 100644 index f8e50fb269..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs +++ /dev/null @@ -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()) { - current.Thread.Suspended = !suspended; - } - WindowsDebugger.RefreshPads(); - }; - - menu.Items.Add(freezeItem); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs deleted file mode 100644 index 79232a2238..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs +++ /dev/null @@ -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 runningThreads; - - public override object Control { - get { return panel; } - } - - public RunningThreadsPad() - { - this.panel = new DockPanel(); - runningThreads = new ObservableCollection(); - 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); - } - } - } -} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ThreadsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ThreadsPad.cs new file mode 100644 index 0000000000..54817c9a99 --- /dev/null +++ b/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 items = new List(); + 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(); + // 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()) { + 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"); + } + } + } +} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs index dd2366e0eb..93e0811831 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs @@ -596,7 +596,7 @@ namespace ICSharpCode.SharpDevelop.Services CurrentProcess = e.Process; CurrentThread = e.Thread; - CurrentStackFrame = CurrentThread.MostRecentUserStackFrame; + CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentUserStackFrame : null; LoggingService.Info("Jump to current line"); JumpToCurrentLine();