194 changed files with 3387 additions and 10884 deletions
@ -0,0 +1,210 @@
@@ -0,0 +1,210 @@
|
||||
// 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.Collections.ObjectModel; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using System.Windows.Media; |
||||
using Debugger; |
||||
using Debugger.AddIn.TreeModel; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
||||
{ |
||||
public class CallStackPad : AbstractPadContent |
||||
{ |
||||
ListView listView; |
||||
|
||||
public override object Control { |
||||
get { return this.listView; } |
||||
} |
||||
|
||||
public CallStackPad() |
||||
{ |
||||
var res = new CommonResources(); |
||||
res.InitializeComponent(); |
||||
|
||||
listView = new ListView(); |
||||
listView.View = (GridView)res["callstackGridView"]; |
||||
listView.MouseDoubleClick += listView_MouseDoubleClick; |
||||
|
||||
listView.ContextMenu = CreateMenu(); |
||||
|
||||
WindowsDebugger.RefreshingPads += RefreshPad; |
||||
RefreshPad(); |
||||
} |
||||
|
||||
ContextMenu CreateMenu() |
||||
{ |
||||
MenuItem extMethodsItem = new MenuItem(); |
||||
extMethodsItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowExternalMethods"); |
||||
extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods; |
||||
extMethodsItem.Click += delegate { |
||||
extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods = !DebuggingOptions.Instance.ShowExternalMethods; |
||||
WindowsDebugger.RefreshPads(); |
||||
}; |
||||
|
||||
MenuItem moduleItem = new MenuItem(); |
||||
moduleItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowModuleNames"); |
||||
moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames; |
||||
moduleItem.Click += delegate { |
||||
moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames = !DebuggingOptions.Instance.ShowModuleNames; |
||||
WindowsDebugger.RefreshPads(); |
||||
}; |
||||
|
||||
MenuItem argNamesItem = new MenuItem(); |
||||
argNamesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentNames"); |
||||
argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames; |
||||
argNamesItem.Click += delegate { |
||||
argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames = !DebuggingOptions.Instance.ShowArgumentNames; |
||||
WindowsDebugger.RefreshPads(); |
||||
}; |
||||
|
||||
MenuItem argValuesItem = new MenuItem(); |
||||
argValuesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentValues"); |
||||
argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues; |
||||
argValuesItem.Click += delegate { |
||||
argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues = !DebuggingOptions.Instance.ShowArgumentValues; |
||||
WindowsDebugger.RefreshPads(); |
||||
}; |
||||
|
||||
MenuItem lineItem = new MenuItem(); |
||||
lineItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowLineNumber"); |
||||
lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers; |
||||
lineItem.Click += delegate { |
||||
lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers = !DebuggingOptions.Instance.ShowLineNumbers; |
||||
WindowsDebugger.RefreshPads(); |
||||
}; |
||||
|
||||
return new ContextMenu() { |
||||
Items = { |
||||
extMethodsItem, |
||||
new Separator(), |
||||
moduleItem, |
||||
argNamesItem, |
||||
argValuesItem, |
||||
lineItem |
||||
} |
||||
}; |
||||
} |
||||
|
||||
void listView_MouseDoubleClick(object sender, MouseButtonEventArgs e) |
||||
{ |
||||
CallStackItem item = listView.SelectedItem as CallStackItem; |
||||
if (item == null) |
||||
return; |
||||
|
||||
if (item.Frame.Process.IsPaused) { |
||||
if (item.Frame != null) { |
||||
// check for options - if these options are enabled, selecting the frame should not continue
|
||||
if (!item.Frame.HasSymbols && !item.Frame.Process.Options.DecompileCodeWithoutSymbols) { |
||||
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWithoutSymbolsOrDecompiledCodeOptions}", |
||||
"${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); |
||||
return; |
||||
} |
||||
WindowsDebugger.CurrentStackFrame = item.Frame; |
||||
WindowsDebugger.Instance.JumpToCurrentLine(); |
||||
WindowsDebugger.RefreshPads(); |
||||
} |
||||
} else { |
||||
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); |
||||
} |
||||
} |
||||
|
||||
void RefreshPad() |
||||
{ |
||||
Thread thead = WindowsDebugger.CurrentThread; |
||||
if (thead == null) { |
||||
listView.ItemsSource = null; |
||||
} else { |
||||
var items = new ObservableCollection<CallStackItem>(); |
||||
bool previousItemIsExternalMethod = false; |
||||
WindowsDebugger.CurrentProcess.EnqueueForEach( |
||||
listView.Dispatcher, |
||||
thead.GetCallstack(100), |
||||
f => items.AddIfNotNull(CreateItem(f, ref previousItemIsExternalMethod)) |
||||
); |
||||
listView.ItemsSource = items; |
||||
} |
||||
} |
||||
|
||||
CallStackItem CreateItem(StackFrame frame, ref bool previousItemIsExternalMethod) |
||||
{ |
||||
bool showExternalMethods = DebuggingOptions.Instance.ShowExternalMethods; |
||||
if (frame.HasSymbols || showExternalMethods) { |
||||
// Show the method in the list
|
||||
previousItemIsExternalMethod = false; |
||||
return new CallStackItem() { |
||||
Frame = frame, |
||||
ImageSource = new ResourceServiceImage("Icons.16x16.Method").ImageSource, |
||||
Name = GetFullName(frame) |
||||
}; |
||||
} else { |
||||
// Show [External methods] in the list
|
||||
if (previousItemIsExternalMethod) |
||||
return null; |
||||
previousItemIsExternalMethod = true; |
||||
return new CallStackItem() { |
||||
Name = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods") |
||||
}; |
||||
} |
||||
} |
||||
|
||||
internal static string GetFullName(StackFrame frame) |
||||
{ |
||||
StringBuilder name = new StringBuilder(64); |
||||
if (DebuggingOptions.Instance.ShowModuleNames) { |
||||
name.Append(frame.MethodInfo.DebugModule.ToString()); |
||||
name.Append('!'); |
||||
} |
||||
name.Append(frame.MethodInfo.DeclaringType.FullName); |
||||
name.Append('.'); |
||||
name.Append(frame.MethodInfo.Name); |
||||
if (DebuggingOptions.Instance.ShowArgumentNames || DebuggingOptions.Instance.ShowArgumentValues) { |
||||
name.Append('('); |
||||
for (int i = 0; i < frame.ArgumentCount; i++) { |
||||
if (DebuggingOptions.Instance.ShowArgumentNames) { |
||||
name.Append(frame.MethodInfo.GetParameters()[i].Name); |
||||
if (DebuggingOptions.Instance.ShowArgumentValues) { |
||||
name.Append('='); |
||||
} |
||||
} |
||||
if (DebuggingOptions.Instance.ShowArgumentValues) { |
||||
try { |
||||
name.Append(frame.GetArgumentValue(i).AsString(100)); |
||||
} catch (GetValueException) { |
||||
name.Append(ResourceService.GetString("Global.NA")); |
||||
} |
||||
} |
||||
if (i < frame.ArgumentCount - 1) { |
||||
name.Append(", "); |
||||
} |
||||
} |
||||
name.Append(')'); |
||||
} |
||||
if (DebuggingOptions.Instance.ShowLineNumbers) { |
||||
if (frame.NextStatement != null) { |
||||
name.Append(':'); |
||||
name.Append(frame.NextStatement.StartLine.ToString()); |
||||
} |
||||
} |
||||
return name.ToString(); |
||||
} |
||||
} |
||||
|
||||
public class CallStackItem |
||||
{ |
||||
public StackFrame Frame { get; set; } |
||||
public ImageSource ImageSource { get; set; } |
||||
public string Name { get; set; } |
||||
|
||||
public Brush FontColor { |
||||
get { return this.Frame == null || this.Frame.HasSymbols ? Brushes.Black : Brushes.Gray; } |
||||
} |
||||
} |
||||
} |
@ -1,41 +0,0 @@
@@ -1,41 +0,0 @@
|
||||
<UserControl x:Class="ICSharpCode.SharpDevelop.Gui.Pads.CallStackPadContent" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:sd="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
<DockPanel> |
||||
<ListView Name="view" MouseLeftButtonUp="View_MouseLeftButtonUp" KeyDown="View_KeyDown"> |
||||
<ListView.View> |
||||
<GridView> |
||||
<GridViewColumn Header="{sd:Localize MainWindow.Windows.Debug.CallStack.Module}"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<TextBlock Text="{Binding ModuleName}" Foreground="{Binding FontColor}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{sd:Localize Global.Name}"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<TextBlock Text="{Binding Name}" Foreground="{Binding FontColor}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{sd:Localize Global.TextLine}"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<TextBlock Text="{Binding Line}" Foreground="{Binding FontColor}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{sd:Localize MainWindow.Windows.Debug.CallStack.Language}"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<TextBlock Text="{Binding Language}" Foreground="{Binding FontColor}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
</GridView> |
||||
</ListView.View> |
||||
</ListView> |
||||
</DockPanel> |
||||
</UserControl> |
@ -1,306 +0,0 @@
@@ -1,306 +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.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using System.Windows.Media; |
||||
using Debugger; |
||||
using Debugger.AddIn.TreeModel; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Gui.Pads; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
||||
{ |
||||
/// <summary>
|
||||
/// Interaction logic for CallStackPadContent.xaml
|
||||
/// </summary>
|
||||
public partial class CallStackPadContent : UserControl |
||||
{ |
||||
CallStackPad callStackPad; |
||||
Process debuggedProcess; |
||||
|
||||
public CallStackPadContent(CallStackPad pad) |
||||
{ |
||||
this.callStackPad = pad; |
||||
InitializeComponent(); |
||||
|
||||
view.ContextMenu = CreateMenu(); |
||||
|
||||
((GridView)view.View).Columns[0].Width = DebuggingOptions.Instance.ShowModuleNames ? 100d : 0d; |
||||
((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d; |
||||
} |
||||
|
||||
ContextMenu CreateMenu() |
||||
{ |
||||
MenuItem extMethodsItem = new MenuItem(); |
||||
extMethodsItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowExternalMethods"); |
||||
extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods; |
||||
extMethodsItem.Click += delegate { |
||||
extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods = !DebuggingOptions.Instance.ShowExternalMethods; |
||||
callStackPad.InvalidatePad(); |
||||
}; |
||||
|
||||
MenuItem moduleItem = new MenuItem(); |
||||
moduleItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowModuleNames"); |
||||
moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames; |
||||
moduleItem.Click += delegate { |
||||
moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames = !DebuggingOptions.Instance.ShowModuleNames; |
||||
((GridView)view.View).Columns[0].Width = DebuggingOptions.Instance.ShowModuleNames ? 100d : 0d; |
||||
callStackPad.InvalidatePad(); |
||||
}; |
||||
|
||||
MenuItem argNamesItem = new MenuItem(); |
||||
argNamesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentNames"); |
||||
argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames; |
||||
argNamesItem.Click += delegate { |
||||
argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames = !DebuggingOptions.Instance.ShowArgumentNames; |
||||
callStackPad.InvalidatePad(); |
||||
}; |
||||
|
||||
MenuItem argValuesItem = new MenuItem(); |
||||
argValuesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentValues"); |
||||
argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues; |
||||
argValuesItem.Click += delegate { |
||||
argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues = !DebuggingOptions.Instance.ShowArgumentValues; |
||||
callStackPad.InvalidatePad(); |
||||
}; |
||||
|
||||
MenuItem lineItem = new MenuItem(); |
||||
lineItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowLineNumber"); |
||||
lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers; |
||||
lineItem.Click += delegate { |
||||
lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers = !DebuggingOptions.Instance.ShowLineNumbers; |
||||
((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d; |
||||
callStackPad.InvalidatePad(); |
||||
}; |
||||
|
||||
return new ContextMenu() { |
||||
Items = { |
||||
extMethodsItem, |
||||
new Separator(), |
||||
moduleItem, |
||||
argNamesItem, |
||||
argValuesItem, |
||||
lineItem |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public void SelectProcess(Process process) |
||||
{ |
||||
if (debuggedProcess != null) { |
||||
debuggedProcess.Paused -= debuggedProcess_Paused; |
||||
} |
||||
debuggedProcess = process; |
||||
if (debuggedProcess != null) { |
||||
debuggedProcess.Paused += debuggedProcess_Paused; |
||||
} |
||||
callStackPad.InvalidatePad(); |
||||
} |
||||
|
||||
void debuggedProcess_Paused(object sender, ProcessEventArgs e) |
||||
{ |
||||
callStackPad.InvalidatePad(); |
||||
} |
||||
|
||||
void View_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) |
||||
{ |
||||
if (debuggedProcess == null) |
||||
return; |
||||
if (debuggedProcess.IsPaused) { |
||||
CallStackItem item = view.SelectedItem as CallStackItem; |
||||
|
||||
if (item == null) |
||||
return; |
||||
|
||||
if (item.Frame != null && debuggedProcess.SelectedThread != null) { |
||||
// check for options - if these options are enabled, selecting the frame should not continue
|
||||
if (!item.Frame.HasSymbols && !debuggedProcess.Options.DecompileCodeWithoutSymbols) { |
||||
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWithoutSymbolsOrDecompiledCodeOptions}", |
||||
"${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); |
||||
return; |
||||
} |
||||
debuggedProcess.SelectedThread.SelectedStackFrame = item.Frame; |
||||
debuggedProcess.PauseSession.PausedReason = PausedReason.CurrentFunctionChanged; |
||||
debuggedProcess.OnPaused(); // Force refresh of pads - artificial pause
|
||||
} |
||||
} else { |
||||
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); |
||||
} |
||||
} |
||||
|
||||
void View_KeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
if (e.Key == Key.Enter) { |
||||
View_MouseLeftButtonUp(sender, null); |
||||
e.Handled = true; |
||||
} |
||||
} |
||||
|
||||
internal void RefreshPad() |
||||
{ |
||||
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) { |
||||
view.ItemsSource = null; |
||||
return; |
||||
} |
||||
|
||||
var items = new ObservableCollection<CallStackItem>(); |
||||
using(new PrintTimes("Callstack refresh")) { |
||||
bool showExternalMethods = DebuggingOptions.Instance.ShowExternalMethods; |
||||
bool previousItemIsExternalMethod = false; |
||||
|
||||
debuggedProcess.EnqueueForEach( |
||||
Dispatcher, |
||||
debuggedProcess.SelectedThread.GetCallstack(100), |
||||
f => items.AddIfNotNull(CreateItem(f, showExternalMethods, ref previousItemIsExternalMethod)) |
||||
); |
||||
} |
||||
view.ItemsSource = items; |
||||
} |
||||
|
||||
CallStackItem CreateItem(StackFrame frame, bool showExternalMethods, ref bool previousItemIsExternalMethod) |
||||
{ |
||||
CallStackItem item; |
||||
|
||||
// line number
|
||||
string lineNumber = string.Empty; |
||||
if (DebuggingOptions.Instance.ShowLineNumbers) { |
||||
if (frame.NextStatement != null) |
||||
lineNumber = frame.NextStatement.StartLine.ToString(); |
||||
} |
||||
|
||||
// show modules names
|
||||
string moduleName = string.Empty; |
||||
if (DebuggingOptions.Instance.ShowModuleNames) { |
||||
moduleName = frame.MethodInfo.DebugModule.ToString(); |
||||
} |
||||
|
||||
if (frame.HasSymbols || showExternalMethods) { |
||||
// Show the method in the list
|
||||
|
||||
item = new CallStackItem() { |
||||
Name = GetFullName(frame), Language = "", Line = lineNumber, ModuleName = moduleName |
||||
}; |
||||
previousItemIsExternalMethod = false; |
||||
item.Frame = frame; |
||||
} else { |
||||
// Show [External methods] in the list
|
||||
if (previousItemIsExternalMethod) return null; |
||||
item = new CallStackItem() { |
||||
Name = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods"), |
||||
Language = "" |
||||
}; |
||||
previousItemIsExternalMethod = true; |
||||
} |
||||
|
||||
return item; |
||||
} |
||||
|
||||
internal static string GetFullName(StackFrame frame) |
||||
{ |
||||
bool showArgumentNames = DebuggingOptions.Instance.ShowArgumentNames; |
||||
bool showArgumentValues = DebuggingOptions.Instance.ShowArgumentValues; |
||||
bool showLineNumber = DebuggingOptions.Instance.ShowLineNumbers; |
||||
bool showModuleNames = DebuggingOptions.Instance.ShowModuleNames; |
||||
|
||||
StringBuilder name = new StringBuilder(); |
||||
name.Append(frame.MethodInfo.DeclaringType.FullName); |
||||
name.Append('.'); |
||||
name.Append(frame.MethodInfo.Name); |
||||
if (showArgumentNames || showArgumentValues) { |
||||
name.Append("("); |
||||
for (int i = 0; i < frame.ArgumentCount; i++) { |
||||
string parameterName = null; |
||||
string argValue = null; |
||||
if (showArgumentNames) { |
||||
try { |
||||
parameterName = frame.MethodInfo.GetParameters()[i].Name; |
||||
} catch { } |
||||
if (parameterName == "") parameterName = null; |
||||
} |
||||
if (showArgumentValues) { |
||||
try { |
||||
argValue = frame.GetArgumentValue(i).AsString(100); |
||||
} catch { } |
||||
} |
||||
if (parameterName != null && argValue != null) { |
||||
name.Append(parameterName); |
||||
name.Append("="); |
||||
name.Append(argValue); |
||||
} |
||||
if (parameterName != null && argValue == null) { |
||||
name.Append(parameterName); |
||||
} |
||||
if (parameterName == null && argValue != null) { |
||||
name.Append(argValue); |
||||
} |
||||
if (parameterName == null && argValue == null) { |
||||
name.Append(ResourceService.GetString("Global.NA")); |
||||
} |
||||
if (i < frame.ArgumentCount - 1) { |
||||
name.Append(", "); |
||||
} |
||||
} |
||||
name.Append(")"); |
||||
} |
||||
|
||||
return name.ToString(); |
||||
} |
||||
} |
||||
|
||||
public class CallStackItem |
||||
{ |
||||
public string Name { get; set; } |
||||
public string Language { get; set; } |
||||
public StackFrame Frame { get; set; } |
||||
public string Line { get; set; } |
||||
public string ModuleName { get; set; } |
||||
|
||||
public Brush FontColor { |
||||
get { return Frame == null || Frame.HasSymbols ? Brushes.Black : Brushes.Gray; } |
||||
} |
||||
} |
||||
|
||||
public class CallStackPad : DebuggerPad |
||||
{ |
||||
CallStackPadContent callStackList; |
||||
|
||||
static CallStackPad instance; |
||||
|
||||
public static CallStackPad Instance { |
||||
get { return instance; } |
||||
} |
||||
|
||||
public CallStackPad() |
||||
{ |
||||
instance = this; |
||||
} |
||||
|
||||
public override object Control { |
||||
get { |
||||
return callStackList; |
||||
} |
||||
} |
||||
|
||||
protected override void InitializeComponents() |
||||
{ |
||||
callStackList = new CallStackPadContent(this); |
||||
} |
||||
|
||||
protected override void SelectProcess(Process process) |
||||
{ |
||||
callStackList.SelectProcess(process); |
||||
} |
||||
|
||||
protected override void RefreshPad() |
||||
{ |
||||
callStackList.RefreshPad(); |
||||
} |
||||
} |
||||
} |
@ -1,127 +0,0 @@
@@ -1,127 +0,0 @@
|
||||
// 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 System.Windows.Input; |
||||
|
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
||||
{ |
||||
public sealed class JumpToAddressCommand : AbstractComboBoxCommand |
||||
{ |
||||
MemoryPad pad; |
||||
ComboBox comboBox; |
||||
|
||||
protected override void OnOwnerChanged(EventArgs e) |
||||
{ |
||||
this.pad = this.Owner as MemoryPad; |
||||
if (this.pad == null) |
||||
return; |
||||
|
||||
comboBox = this.ComboBox as ComboBox; |
||||
|
||||
if (this.comboBox == null) |
||||
return; |
||||
|
||||
comboBox.KeyUp += (s, ea) => { if (ea.Key == Key.Enter) Run(); }; |
||||
comboBox.IsEditable = true; |
||||
comboBox.Width = 130; |
||||
|
||||
base.OnOwnerChanged(e); |
||||
} |
||||
|
||||
public override void Run() |
||||
{ |
||||
if (this.pad != null && this.comboBox != null) { |
||||
pad.JumpToAddress(comboBox.Text); |
||||
} |
||||
base.Run(); |
||||
} |
||||
} |
||||
|
||||
public abstract class ItemMemoryCommand : AbstractCommand |
||||
{ |
||||
protected MemoryPad pad; |
||||
|
||||
protected override void OnOwnerChanged(EventArgs e) |
||||
{ |
||||
this.pad = this.Owner as MemoryPad; |
||||
if (this.pad == null) |
||||
return; |
||||
|
||||
base.OnOwnerChanged(e); |
||||
} |
||||
} |
||||
|
||||
public sealed class RefreshAddressCommand : ItemMemoryCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
if (this.pad == null) |
||||
return; |
||||
|
||||
this.pad.Refresh(); |
||||
} |
||||
} |
||||
|
||||
public sealed class NextAddressCommand : ItemMemoryCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
if (this.pad == null) |
||||
return; |
||||
|
||||
this.pad.MoveToNextAddress(); |
||||
} |
||||
} |
||||
|
||||
public sealed class PreviousAddressCommand : ItemMemoryCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
if (this.pad == null) |
||||
return; |
||||
|
||||
this.pad.MoveToPreviousAddress(); |
||||
} |
||||
} |
||||
|
||||
public sealed class DisplayByteSizeCommand : AbstractComboBoxCommand |
||||
{ |
||||
MemoryPad pad; |
||||
ComboBox comboBox; |
||||
|
||||
protected override void OnOwnerChanged(EventArgs e) |
||||
{ |
||||
this.pad = this.Owner as MemoryPad; |
||||
if (this.pad == null) |
||||
return; |
||||
|
||||
comboBox = this.ComboBox as ComboBox; |
||||
|
||||
if (this.comboBox == null) |
||||
return; |
||||
|
||||
comboBox.SelectionChanged += (s, ea) => { Run(); }; |
||||
|
||||
comboBox.Items.Add(1); |
||||
comboBox.Items.Add(2); |
||||
comboBox.Items.Add(4); |
||||
comboBox.Text = "1"; |
||||
comboBox.Width = 30; |
||||
comboBox.IsEditable = false; |
||||
|
||||
base.OnOwnerChanged(e); |
||||
} |
||||
|
||||
public override void Run() |
||||
{ |
||||
if (this.pad != null && this.comboBox != null) { |
||||
pad.DisplayByteSize = Convert.ToByte(this.comboBox.SelectedValue); |
||||
pad.DisplayMemory(); |
||||
} |
||||
base.Run(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
// 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.Threading; |
||||
using ICSharpCode.AvalonEdit; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.Pads.Controls |
||||
{ |
||||
public class AutoCompleteTextBox : UserControl |
||||
{ |
||||
TextEditor editor; |
||||
ITextEditor editorAdapter; |
||||
|
||||
public static readonly DependencyProperty TextProperty = |
||||
DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox), |
||||
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, TextChanged)); |
||||
|
||||
public static readonly DependencyProperty IsEditableProperty = |
||||
DependencyProperty.Register("IsEditable", typeof(bool), typeof(AutoCompleteTextBox), |
||||
new FrameworkPropertyMetadata(true, IsEditableChanged)); |
||||
|
||||
public string Text { |
||||
get { return (string)GetValue(TextProperty); } |
||||
set { SetValue(TextProperty, value); } |
||||
} |
||||
|
||||
public bool IsEditable { |
||||
get { return (bool)GetValue(IsEditableProperty); } |
||||
set { SetValue(IsEditableProperty, value); } |
||||
} |
||||
|
||||
static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
||||
{ |
||||
((AutoCompleteTextBox)d).editor.Text = (string)e.NewValue; |
||||
} |
||||
|
||||
static void IsEditableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
||||
{ |
||||
((AutoCompleteTextBox)d).editor.IsReadOnly = !(bool)e.NewValue; |
||||
} |
||||
|
||||
public AutoCompleteTextBox() |
||||
{ |
||||
object tmp; |
||||
this.editorAdapter = EditorControlService.CreateEditor(out tmp); |
||||
this.editor = (TextEditor)tmp; |
||||
|
||||
this.editor.Background = Brushes.Transparent; |
||||
this.editor.ShowLineNumbers = false; |
||||
this.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; |
||||
this.editor.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden; |
||||
this.editor.TextArea.GotKeyboardFocus += delegate { |
||||
this.Background = Brushes.White; |
||||
}; |
||||
this.editor.TextArea.LostKeyboardFocus += delegate { |
||||
this.Background = Brushes.Transparent; |
||||
this.Text = this.editor.Text; |
||||
this.editor.Select(0, 0); |
||||
}; |
||||
this.editor.TextArea.PreviewKeyDown += editor_TextArea_PreviewKeyDown; |
||||
this.editor.TextArea.TextEntered += editor_TextArea_TextEntered; |
||||
|
||||
this.Content = this.editor; |
||||
} |
||||
|
||||
void editor_TextArea_PreviewKeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
if (e.Key == Key.Return || e.Key == Key.Escape) { |
||||
if (e.Key == Key.Return) |
||||
this.Text = this.editor.Text; |
||||
|
||||
e.Handled = true; |
||||
} |
||||
} |
||||
|
||||
void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
StackFrame frame = WindowsDebugger.CurrentStackFrame; |
||||
if (e.Text == "." && frame != null) |
||||
ShowDotCompletion(frame, this.editor.Text); |
||||
} |
||||
|
||||
private void ShowDotCompletion(StackFrame frame, string currentText) |
||||
{ |
||||
string language = ProjectService.CurrentProject == null ? "C#" : ProjectService.CurrentProject.Language; |
||||
NRefactoryResolver resolver = new NRefactoryResolver(LanguageProperties.GetLanguage(language)); |
||||
|
||||
var seg = frame.NextStatement; |
||||
|
||||
var expressionFinder = ParserService.GetExpressionFinder(seg.Filename); |
||||
var info = ParserService.GetParseInformation(seg.Filename); |
||||
|
||||
string text = ParserService.GetParseableFileContent(seg.Filename).Text; |
||||
|
||||
int currentOffset = this.editor.CaretOffset; |
||||
|
||||
var expr = expressionFinder.FindExpression(currentText, currentOffset); |
||||
|
||||
expr.Region = new DomRegion(seg.StartLine, seg.StartColumn, seg.EndLine, seg.EndColumn); |
||||
|
||||
var rr = resolver.Resolve(expr, info, text); |
||||
|
||||
if (rr != null) { |
||||
editorAdapter.ShowCompletionWindow(new DotCodeCompletionItemProvider().GenerateCompletionListForResolveResult(rr, expr.Context)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
<ResourceDictionary |
||||
x:Class="CommonResources" |
||||
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.Controls" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:tv="http://icsharpcode.net/sharpdevelop/treeview" |
||||
> |
||||
|
||||
<!-- Local Variables Pad and Watch Pad --> |
||||
<tv:SharpGridView x:Key="variableGridView"> |
||||
<GridView.Columns> |
||||
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.LocalVariables.NameColumn}" Width="200"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<StackPanel Orientation="Horizontal"> |
||||
<tv:SharpTreeNodeView/> |
||||
<local:AutoCompleteTextBox Margin="-6 0 0 0" Text="{Binding Node.Name}" IsEditable="{Binding Node.CanSetName}"/> |
||||
</StackPanel> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.LocalVariables.ValueColumn}" Width="200"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<local:AutoCompleteTextBox Text="{Binding Node.Value}" IsEditable="{Binding Node.CanSetValue}"/> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.LocalVariables.TypeColumn}" Width="200"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<local:AutoCompleteTextBox Text="{Binding Node.Type}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
</GridView.Columns> |
||||
</tv:SharpGridView> |
||||
|
||||
<!-- Callstack --> |
||||
<GridView x:Key="callstackGridView"> |
||||
<GridViewColumn Header="{core:Localize Global.Name}" Width="400"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<StackPanel Orientation="Horizontal"> |
||||
<Image Source="{Binding ImageSource}" Margin="1, 1, 5, 1" /> |
||||
<TextBlock Text="{Binding Name}" Foreground="{Binding FontColor}" /> |
||||
</StackPanel> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
</GridView> |
||||
|
||||
<!-- Breakpoints Pad --> |
||||
<GridView x:Key="breakpointsGridView"> |
||||
<GridViewColumn Header="" Width="Auto"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<CheckBox IsChecked="{Binding Path=IsEnabled, Mode=TwoWay}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{core:Localize MainWindow.Windows.BookmarkPad.LocationText}" Width="Auto"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<StackPanel Orientation="Horizontal"> |
||||
<Image Source="{Binding ImageSource}" Margin="1, 1, 5, 1" /> |
||||
<TextBlock Text="{Binding FileNameAndLineNumber}" /> |
||||
</StackPanel> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Conditional.Breakpoints.ConditionalColumnHeader}" Width="Auto"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<local:AutoCompleteTextBox Text="{Binding Condition}" MinWidth="100" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
</GridView> |
||||
|
||||
<!-- Loaded Modules --> |
||||
<GridView x:Key="loadedModulesGridView"> |
||||
<GridViewColumn Header="{core:Localize Global.Name}" Width="250" DisplayMemberBinding="{Binding Name}"/> |
||||
<GridViewColumn Header="{core:Localize MainWindow.Windows.Debug.Modules.AddressColumn}" Width="100" DisplayMemberBinding="{Binding Address}"/> |
||||
<GridViewColumn Header="{core:Localize Global.Path}" Width="250" DisplayMemberBinding="{Binding Path}"/> |
||||
<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}"/> |
||||
</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> |
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
<UserControl x:Class="Debugger.AddIn.Pads.Controls.ConditionCell" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:SDGui="clr-namespace:ICSharpCode.SharpDevelop.Gui;assembly=ICSharpCode.SharpDevelop" |
||||
xmlns:local="clr-namespace:Debugger.AddIn.Pads.Controls"> |
||||
<UserControl.Resources> |
||||
<DataTemplate x:Key="ConditionCellTemplate"> |
||||
<Grid HorizontalAlignment="Stretch"> |
||||
<local:ConditionCell |
||||
CommandText="{Binding Path=Condition, UpdateSourceTrigger=LostFocus}" |
||||
Tag="{Binding Path=Tag, Mode=TwoWay}"/> |
||||
</Grid> |
||||
</DataTemplate> |
||||
</UserControl.Resources> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto" MinWidth="200"/> |
||||
</Grid.ColumnDefinitions> |
||||
<ContentPresenter |
||||
Name="ConsolePanel" /> |
||||
</Grid> |
||||
</UserControl> |
@ -1,196 +0,0 @@
@@ -1,196 +0,0 @@
|
||||
// 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.IO; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
|
||||
using ICSharpCode.AvalonEdit; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Bookmarks.Pad.Controls; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace Debugger.AddIn.Pads.Controls |
||||
{ |
||||
public partial class ConditionCell : UserControl |
||||
{ |
||||
private string language; |
||||
|
||||
protected ConsoleControl console; |
||||
|
||||
public static readonly DependencyProperty CommandTextProperty = |
||||
DependencyProperty.Register("CommandText", typeof(string), typeof(ConditionCell), |
||||
new UIPropertyMetadata(null, new PropertyChangedCallback(OnCommandTextChanged))); |
||||
|
||||
private NRefactoryResolver resolver; |
||||
|
||||
public ConditionCell() |
||||
{ |
||||
InitializeComponent(); |
||||
|
||||
console = new ConsoleControl(); |
||||
console.TextAreaTextEntered += new TextCompositionEventHandler(consoleControl_TextAreaTextEntered); |
||||
console.TextAreaPreviewKeyDown += new KeyEventHandler(console_TextAreaPreviewKeyDown); |
||||
console.LostFocus += new RoutedEventHandler(console_LostFocus); |
||||
console.HideScrollBar(); |
||||
ConsolePanel.Content = console; |
||||
|
||||
// get language
|
||||
if (ProjectService.CurrentProject == null) |
||||
language = "C#"; |
||||
else |
||||
language = ProjectService.CurrentProject.Language; |
||||
resolver = new NRefactoryResolver(LanguageProperties.GetLanguage(language)); |
||||
|
||||
// FIXME set language
|
||||
if (language == "VB" || language == "VBNet") { |
||||
console.SetHighlighting("VBNET"); |
||||
} |
||||
else { |
||||
console.SetHighlighting("C#"); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the command text displayed at the command prompt.
|
||||
/// </summary>
|
||||
public string CommandText { |
||||
get { return console.CommandText.Trim(); } |
||||
set { console.CommandText = value; } |
||||
} |
||||
|
||||
private BreakpointBookmark Breakpoint { |
||||
get { |
||||
var model = Model; |
||||
return model.Mark as BreakpointBookmark; |
||||
} |
||||
} |
||||
|
||||
private ListViewPadItemModel Model { |
||||
get { return Tag as ListViewPadItemModel; } |
||||
} |
||||
|
||||
private ITextEditor TextEditor { |
||||
get { |
||||
return console.TextEditor; |
||||
} |
||||
} |
||||
|
||||
private void console_TextAreaPreviewKeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
if (e.Key == Key.Return || e.Key == Key.Escape) { |
||||
|
||||
if (e.Key == Key.Escape) |
||||
CommandText = string.Empty; |
||||
else { |
||||
if(!CheckSyntax()) |
||||
return; |
||||
} |
||||
|
||||
UpdateBreakpoint(); |
||||
|
||||
e.Handled = true; |
||||
} |
||||
} |
||||
|
||||
private void console_LostFocus(object sender, RoutedEventArgs e) |
||||
{ |
||||
if (string.IsNullOrEmpty(CommandText) || !this.CheckSyntax()) |
||||
return; |
||||
|
||||
UpdateBreakpoint(); |
||||
} |
||||
|
||||
private void UpdateBreakpoint() |
||||
{ |
||||
Breakpoint.Condition = CommandText; |
||||
Model.Condition = CommandText; |
||||
Breakpoint.ScriptLanguage = language; |
||||
Model.Language = language; |
||||
|
||||
if (!string.IsNullOrEmpty(console.CommandText)) { |
||||
Breakpoint.Action = BreakpointAction.Condition; |
||||
if (Breakpoint.IsEnabled) |
||||
Model.Image = BreakpointBookmark.BreakpointConditionalImage.ImageSource; |
||||
} |
||||
else { |
||||
Breakpoint.Action = BreakpointAction.Break; |
||||
if (Breakpoint.IsEnabled) |
||||
Model.Image = BreakpointBookmark.BreakpointImage.ImageSource; |
||||
} |
||||
} |
||||
|
||||
private bool CheckSyntax() |
||||
{ |
||||
string command = CommandText; |
||||
if (string.IsNullOrEmpty(command)) |
||||
return true; |
||||
|
||||
// FIXME workaround the NRefactory issue that needs a ; at the end
|
||||
if (language == "C#") { |
||||
if(!command.EndsWith(";")) |
||||
command += ";"; |
||||
// FIXME only one string should be available; highlighting expects C#, supproted language, CSharp
|
||||
language = "CSharp"; |
||||
} |
||||
|
||||
SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language.ToString(), true); |
||||
using (var parser = ParserFactory.CreateParser(supportedLanguage, new StringReader(TextEditor.Document.Text))) { |
||||
parser.ParseExpression(); |
||||
if (parser.Errors.Count > 0) { |
||||
MessageService.ShowError(parser.Errors.ErrorOutput); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private void consoleControl_TextAreaTextEntered(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
foreach (char ch in e.Text) { |
||||
if (ch == '.') { |
||||
ShowDotCompletion(console.CommandText); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void ShowDotCompletion(string currentText) |
||||
{ |
||||
var seg = Breakpoint; |
||||
|
||||
var expressionFinder = ParserService.GetExpressionFinder(seg.FileName.ToString()); |
||||
var info = ParserService.GetParseInformation(seg.FileName.ToString()); |
||||
|
||||
string text = ParserService.GetParseableFileContent(seg.FileName.ToString()).Text; |
||||
|
||||
int currentOffset = TextEditor.Caret.Offset - console.CommandOffset - 1; |
||||
|
||||
var expr = expressionFinder.FindExpression(currentText, currentOffset); |
||||
|
||||
expr.Region = new DomRegion(seg.LineNumber, seg.ColumnNumber, seg.LineNumber, seg.ColumnNumber); |
||||
|
||||
var rr = resolver.Resolve(expr, info, text); |
||||
|
||||
if (rr != null) { |
||||
TextEditor.ShowCompletionWindow(new DotCodeCompletionItemProvider().GenerateCompletionListForResolveResult(rr, expr.Context)); |
||||
} |
||||
} |
||||
|
||||
private static void OnCommandTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { |
||||
var cell = d as ConditionCell; |
||||
cell.CommandText = e.NewValue.ToString(); |
||||
} |
||||
} |
||||
} |
@ -1,28 +0,0 @@
@@ -1,28 +0,0 @@
|
||||
// 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.Globalization; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Data; |
||||
using System.Windows.Media; |
||||
|
||||
namespace Debugger.AddIn.Pads.Controls |
||||
{ |
||||
public class BoolToVisibilityConverter : IMultiValueConverter |
||||
{ |
||||
public object Convert(object[] values, Type targetType, |
||||
object parameter, CultureInfo culture) |
||||
{ |
||||
bool val = bool.Parse(parameter.ToString()); |
||||
return val == (bool.Parse(values[0].ToString()) && bool.Parse(values[1].ToString())) ? Visibility.Visible : Visibility.Collapsed; |
||||
} |
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, |
||||
object parameter, CultureInfo culture) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
} |
||||
} |
@ -1,82 +0,0 @@
@@ -1,82 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<UserControl x:Class="Debugger.AddIn.Pads.Controls.WatchList" |
||||
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.Controls" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:tv="http://icsharpcode.net/sharpdevelop/treeview"> |
||||
<UserControl.Resources> |
||||
<local:BoolToVisibilityConverter x:Key="boolToVisibility" /> |
||||
<Style x:Key="BorderStyle" TargetType="Border"> |
||||
<Setter Property="BorderBrush" Value="LightGray" /> |
||||
<Setter Property="BorderThickness" Value="1,0,1,1"></Setter> |
||||
<Setter Property="VerticalAlignment" Value="Center" /> |
||||
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
||||
</Style> |
||||
<Style TargetType="{x:Type TextBox}" x:Key="TextBoxValueStyle"> |
||||
<Setter Property="BorderThickness" Value="0"/> |
||||
<Setter Property="BorderBrush" Value="Transparent"/> |
||||
<Setter Property="Background" Value="White"/> |
||||
<Setter Property="VerticalAlignment" Value="Center" /> |
||||
<Setter Property="Visibility"> |
||||
<Setter.Value> |
||||
<MultiBinding Converter="{StaticResource boolToVisibility}" ConverterParameter="True"> |
||||
<Binding Path="Node.CanSetText" /> |
||||
<Binding Path="IsSelected" /> |
||||
</MultiBinding> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
<Style TargetType="{x:Type TextBlock}" x:Key="TextBlockValueStyle"> |
||||
<Setter Property="VerticalAlignment" Value="Center" /> |
||||
<Setter Property="Visibility"> |
||||
<Setter.Value> |
||||
<MultiBinding Converter="{StaticResource boolToVisibility}" ConverterParameter="False"> |
||||
<Binding Path="Node.CanSetText" /> |
||||
<Binding Path="IsSelected" /> |
||||
</MultiBinding> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
<!-- Value column --> |
||||
<DataTemplate x:Key="CellTemplate_Value"> |
||||
<StackPanel Orientation="Horizontal"> |
||||
<TextBlock VerticalAlignment="Center" MinWidth="200" Text="{Binding Node.Text}" Style="{StaticResource TextBlockValueStyle}" /> |
||||
<TextBox Text="{Binding Node.Text, Mode=OneWay}" Style="{StaticResource TextBoxValueStyle}" KeyUp="OnValueTextBoxKeyUp" /> |
||||
</StackPanel> |
||||
</DataTemplate> |
||||
<!-- Type column --> |
||||
<DataTemplate x:Key="CellTemplate_Type"> |
||||
<TextBlock VerticalAlignment="Center" MinWidth="200" Text="{Binding Node.Type}" /> |
||||
</DataTemplate> |
||||
</UserControl.Resources> |
||||
<DockPanel> |
||||
<tv:SharpTreeView x:Name="myList" ShowRoot="False" PreviewMouseDoubleClick="MyListPreviewMouseDoubleClick" AllowDrop="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=AllowDrop}"> |
||||
<tv:SharpTreeView.View> |
||||
<tv:SharpGridView> |
||||
<GridView.Columns> |
||||
<GridViewColumn Header="{core:Localize Global.Name}" Width="400"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<tv:SharpTreeNodeView> |
||||
<tv:SharpTreeNodeView.CellEditor> |
||||
<local:WatchListAutoCompleteCell |
||||
CommandText="{Binding Node.Name, Mode=OneWay}" |
||||
CommandEntered="WatchListAutoCompleteCellCommandEntered"/> |
||||
</tv:SharpTreeNodeView.CellEditor> |
||||
</tv:SharpTreeNodeView> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{core:Localize Dialog.HighlightingEditor.Properties.Value}" |
||||
CellTemplate="{StaticResource CellTemplate_Value}" |
||||
Width="200" /> |
||||
<GridViewColumn Header="{core:Localize ResourceEditor.ResourceEdit.TypeColumn}" |
||||
CellTemplate="{StaticResource CellTemplate_Type}" |
||||
Width="200" /> |
||||
</GridView.Columns> |
||||
</tv:SharpGridView> |
||||
</tv:SharpTreeView.View> |
||||
</tv:SharpTreeView> |
||||
</DockPanel> |
||||
</UserControl> |
@ -1,94 +0,0 @@
@@ -1,94 +0,0 @@
|
||||
// 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.Linq; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Data; |
||||
using System.Windows.Input; |
||||
using Debugger.AddIn.TreeModel; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Gui.Pads; |
||||
using ICSharpCode.TreeView; |
||||
|
||||
namespace Debugger.AddIn.Pads.Controls |
||||
{ |
||||
public enum WatchListType |
||||
{ |
||||
LocalVar, |
||||
Watch |
||||
} |
||||
|
||||
public partial class WatchList : UserControl |
||||
{ |
||||
public WatchList(WatchListType type) |
||||
{ |
||||
InitializeComponent(); |
||||
WatchType = type; |
||||
if (type == WatchListType.Watch) |
||||
myList.Root = new WatchRootNode(); |
||||
else |
||||
myList.Root = new SharpTreeNode(); |
||||
} |
||||
|
||||
public WatchListType WatchType { get; private set; } |
||||
|
||||
public SharpTreeNodeCollection WatchItems { |
||||
get { return myList.Root.Children; } |
||||
} |
||||
|
||||
public TreeNodeWrapper SelectedNode { |
||||
get { return myList.SelectedItem as TreeNodeWrapper; } |
||||
} |
||||
|
||||
void OnValueTextBoxKeyUp(object sender, KeyEventArgs e) |
||||
{ |
||||
if (e.Key != Key.Enter && e.Key != Key.Escape) { |
||||
e.Handled = true; |
||||
return; |
||||
} |
||||
|
||||
if (e.Key == Key.Enter) { |
||||
if(SelectedNode.Node is ExpressionNode) { |
||||
var node = (ExpressionNode)SelectedNode.Node; |
||||
node.SetText(((TextBox)sender).Text); |
||||
} |
||||
} |
||||
if (e.Key == Key.Enter || e.Key == Key.Escape) { |
||||
myList.UnselectAll(); |
||||
if (LocalVarPad.Instance != null) |
||||
LocalVarPad.Instance.InvalidatePad(); |
||||
if (WatchPad.Instance != null) |
||||
WatchPad.Instance.InvalidatePad(); |
||||
} |
||||
} |
||||
|
||||
void WatchListAutoCompleteCellCommandEntered(object sender, EventArgs e) |
||||
{ |
||||
var selectedNode = SelectedNode; |
||||
if (selectedNode == null) return; |
||||
if (WatchType != WatchListType.Watch) return; |
||||
|
||||
var cell = ((WatchListAutoCompleteCell)sender); |
||||
|
||||
selectedNode.Node.Name = cell.CommandText; |
||||
myList.UnselectAll(); |
||||
if (WatchType == WatchListType.Watch && WatchPad.Instance != null) { |
||||
WatchPad.Instance.InvalidatePad(); |
||||
} |
||||
selectedNode.IsEditing = false; |
||||
} |
||||
|
||||
void MyListPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) |
||||
{ |
||||
if (SelectedNode == null) return; |
||||
if (WatchType != WatchListType.Watch) |
||||
return; |
||||
SelectedNode.IsEditing = true; |
||||
} |
||||
} |
||||
} |
@ -1,175 +0,0 @@
@@ -1,175 +0,0 @@
|
||||
// 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.IO; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
|
||||
using ICSharpCode.AvalonEdit; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Gui.Pads; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.Pads.Controls |
||||
{ |
||||
public partial class WatchListAutoCompleteCell : UserControl |
||||
{ |
||||
string language; |
||||
|
||||
protected ConsoleControl console; |
||||
|
||||
public static readonly DependencyProperty CommandTextProperty = |
||||
DependencyProperty.Register("CommandText", typeof(string), typeof(WatchListAutoCompleteCell), |
||||
new UIPropertyMetadata(null, new PropertyChangedCallback(OnCommandTextChanged))); |
||||
|
||||
NRefactoryResolver resolver; |
||||
|
||||
public event EventHandler CommandEntered; |
||||
|
||||
public WatchListAutoCompleteCell() |
||||
{ |
||||
InitializeComponent(); |
||||
|
||||
console = new ConsoleControl(); |
||||
console.TextAreaTextEntered += new TextCompositionEventHandler(consoleControl_TextAreaTextEntered); |
||||
console.TextAreaPreviewKeyDown += new KeyEventHandler(console_TextAreaPreviewKeyDown); |
||||
console.LostFocus += new RoutedEventHandler(console_LostFocus); |
||||
console.HideScrollBar(); |
||||
ConsolePanel.Content = console; |
||||
|
||||
// get language
|
||||
if (ProjectService.CurrentProject == null) |
||||
language = "C#"; |
||||
else |
||||
language = ProjectService.CurrentProject.Language; |
||||
resolver = new NRefactoryResolver(LanguageProperties.GetLanguage(language)); |
||||
|
||||
// FIXME set language
|
||||
if (language == "VB" || language == "VBNet") { |
||||
console.SetHighlighting("VBNET"); |
||||
} |
||||
else { |
||||
console.SetHighlighting("C#"); |
||||
} |
||||
|
||||
// get process
|
||||
WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; |
||||
|
||||
debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { |
||||
this.Process = e.Process; |
||||
}; |
||||
this.Process = debugger.DebuggedProcess; |
||||
} |
||||
|
||||
Process Process { get; set; } |
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the command text displayed at the command prompt.
|
||||
/// </summary>
|
||||
public string CommandText { |
||||
get { return console.CommandText.Trim(); } |
||||
set { console.CommandText = value; } |
||||
} |
||||
|
||||
ITextEditor TextEditor { |
||||
get { |
||||
return console.TextEditor; |
||||
} |
||||
} |
||||
|
||||
void console_TextAreaPreviewKeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
if (e.Key == Key.Return || e.Key == Key.Escape) { |
||||
|
||||
if (e.Key == Key.Escape) |
||||
CommandText = string.Empty; |
||||
else { |
||||
if(!CheckSyntax()) |
||||
return; |
||||
} |
||||
|
||||
if (CommandEntered != null) |
||||
CommandEntered(this, EventArgs.Empty); |
||||
|
||||
e.Handled = true; |
||||
} |
||||
} |
||||
|
||||
void console_LostFocus(object sender, RoutedEventArgs e) |
||||
{ |
||||
if (string.IsNullOrEmpty(CommandText) || !this.CheckSyntax()) |
||||
return; |
||||
|
||||
if (CommandEntered != null) |
||||
CommandEntered(this, EventArgs.Empty); |
||||
} |
||||
|
||||
bool CheckSyntax() |
||||
{ |
||||
string command = CommandText; |
||||
|
||||
// FIXME workaround the NRefactory issue that needs a ; at the end
|
||||
if (language == "C#" || language == "CSharp") { |
||||
if (!command.EndsWith(";")) |
||||
command += ";"; |
||||
// FIXME only one string should be available; highlighting expects C#, supported language, CSharp
|
||||
language = "CSharp"; |
||||
} |
||||
|
||||
SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language.ToString(), true); |
||||
using (var parser = ParserFactory.CreateParser(supportedLanguage, new StringReader(command))) { |
||||
parser.ParseExpression(); |
||||
if (parser.Errors.Count > 0) { |
||||
MessageService.ShowError(parser.Errors.ErrorOutput); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
void consoleControl_TextAreaTextEntered(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
foreach (char ch in e.Text) { |
||||
if (ch == '.') { |
||||
ShowDotCompletion(console.CommandText); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ShowDotCompletion(string currentText) |
||||
{ |
||||
var seg = Process.SelectedStackFrame.NextStatement; |
||||
var expressionFinder = ParserService.GetExpressionFinder(seg.Filename); |
||||
var info = ParserService.GetParseInformation(seg.Filename); |
||||
string text = ParserService.GetParseableFileContent(seg.Filename).Text; |
||||
int currentOffset = TextEditor.Caret.Offset - console.CommandOffset - 1; |
||||
var expr = expressionFinder.FindExpression(currentText, currentOffset); |
||||
expr.Region = new DomRegion(seg.StartLine, seg.StartColumn, seg.EndLine, seg.EndColumn); |
||||
var rr = resolver.Resolve(expr, info, text); |
||||
|
||||
if (rr != null) { |
||||
TextEditor.ShowCompletionWindow(new DotCodeCompletionItemProvider().GenerateCompletionListForResolveResult(rr, expr.Context)); |
||||
} |
||||
} |
||||
|
||||
static void OnCommandTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
||||
{ |
||||
var cell = d as WatchListAutoCompleteCell; |
||||
if (cell != null && e.NewValue != null) { |
||||
cell.CommandText = e.NewValue.ToString(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,11 +0,0 @@
@@ -1,11 +0,0 @@
|
||||
<UserControl x:Class="Debugger.AddIn.Pads.Controls.WatchListAutoCompleteCell" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto" MinWidth="200"/> |
||||
</Grid.ColumnDefinitions> |
||||
<ContentPresenter |
||||
Name="ConsolePanel" /> |
||||
</Grid> |
||||
</UserControl> |
@ -1,85 +0,0 @@
@@ -1,85 +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.Windows.Controls; |
||||
using Debugger; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
||||
{ |
||||
public abstract class DebuggerPad : AbstractPadContent |
||||
{ |
||||
protected DockPanel panel; |
||||
ToolBar toolbar; |
||||
protected WindowsDebugger debugger; |
||||
|
||||
public override object Control { |
||||
get { |
||||
return panel; |
||||
} |
||||
} |
||||
|
||||
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; |
||||
|
||||
InitializeComponents(); |
||||
|
||||
debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { |
||||
SelectProcess(e.Process); |
||||
}; |
||||
SelectProcess(debugger.DebuggedProcess); |
||||
} |
||||
|
||||
protected virtual void InitializeComponents() |
||||
{ |
||||
|
||||
} |
||||
|
||||
protected virtual void SelectProcess(Process process) |
||||
{ |
||||
|
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Never call this directly. Always use InvalidatePad()
|
||||
/// </summary>
|
||||
protected virtual void RefreshPad() |
||||
{ |
||||
|
||||
} |
||||
|
||||
bool invalidatePadEnqueued; |
||||
|
||||
public void InvalidatePad() |
||||
{ |
||||
WorkbenchSingleton.AssertMainThread(); |
||||
if (invalidatePadEnqueued || WorkbenchSingleton.Workbench == null) |
||||
return; |
||||
invalidatePadEnqueued = true; |
||||
WorkbenchSingleton.SafeThreadAsyncCall( |
||||
delegate { |
||||
invalidatePadEnqueued = false; |
||||
RefreshPad(); |
||||
}); |
||||
|
||||
} |
||||
|
||||
protected virtual ToolBar BuildToolBar() |
||||
{ |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -1,331 +0,0 @@
@@ -1,331 +0,0 @@
|
||||
// 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.ComponentModel; |
||||
using System.Globalization; |
||||
using System.Text; |
||||
using System.Text.RegularExpressions; |
||||
using System.Windows.Controls; |
||||
|
||||
using Debugger; |
||||
using Debugger.Interop; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
||||
{ |
||||
public sealed class MemoryPad : DebuggerPad |
||||
{ |
||||
int currentAddressIndex; |
||||
ConsoleControl console; |
||||
int columnsNumber = 16; |
||||
byte displayByteSize = 1; |
||||
byte[] memory; |
||||
Process debuggedProcess; |
||||
List<Tuple<long, long>> memoryAddresses = new List<Tuple<long, long>>(); |
||||
Dictionary<long, int> addressesMapping = new Dictionary<long, int>(); |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of columns in the display
|
||||
/// </summary>
|
||||
[DefaultValue(16)] |
||||
public int ColumnsNumber { |
||||
get { return columnsNumber; } |
||||
set { |
||||
if (value != columnsNumber) { |
||||
columnsNumber = value; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display byte size: 1, 2, 4
|
||||
/// </summary>
|
||||
[DefaultValue(1)] |
||||
public byte DisplayByteSize { |
||||
get { return displayByteSize; } |
||||
set { |
||||
// check is value is a power of 2 between 1 and 4.
|
||||
if ((value & (value - 1)) != 0) |
||||
return; |
||||
if (value < 1 || value > 4) |
||||
return; |
||||
|
||||
if (displayByteSize != value) { |
||||
displayByteSize = value; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public MemoryPad() |
||||
{ |
||||
this.console = new ConsoleControl(); |
||||
this.panel.Children.Add(console); |
||||
this.console.Encoding = Encoding.Default; |
||||
RefreshPad(); // exception
|
||||
this.console.SetReadonly(); |
||||
|
||||
DebuggerService.DebugStopped += DebuggerService_DebugStopped; |
||||
} |
||||
|
||||
void DebuggerService_DebugStopped(object sender, EventArgs e) |
||||
{ |
||||
memoryAddresses.Clear(); |
||||
addressesMapping.Clear(); |
||||
memory = null; |
||||
} |
||||
|
||||
protected override ToolBar BuildToolBar() |
||||
{ |
||||
return ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/MemoryPad/ToolBar"); |
||||
} |
||||
|
||||
protected override void SelectProcess(Process process) |
||||
{ |
||||
if (process == null) |
||||
return; |
||||
|
||||
debuggedProcess = process; |
||||
memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); |
||||
currentAddressIndex = 0; |
||||
} |
||||
|
||||
public void JumpToAddress(string address) |
||||
{ |
||||
try { |
||||
if (address.StartsWith("0x")) |
||||
address = address.Substring(2); |
||||
|
||||
long addr = Int64.Parse(address, NumberStyles.AllowHexSpecifier); |
||||
|
||||
memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); |
||||
// find index for the address or the near addess
|
||||
currentAddressIndex = memoryAddresses.BinarySearch(addr); |
||||
if (currentAddressIndex == -1) { |
||||
MessageService.ShowMessage( |
||||
string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.AddressNotFound"), address), |
||||
ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad")); |
||||
|
||||
currentAddressIndex = 0; |
||||
return; |
||||
} |
||||
|
||||
// refresh pad
|
||||
if (!Refresh()) |
||||
return; |
||||
|
||||
// find line
|
||||
long mod = addr % (columnsNumber * displayByteSize); |
||||
int line; |
||||
long key = addr - mod; |
||||
//int index = addressesMapping.BinarySearch(key);
|
||||
if (addressesMapping.ContainsKey(key)) |
||||
line = addressesMapping[key]; |
||||
else |
||||
line = 1; |
||||
|
||||
// jump
|
||||
console.SelectText(line, 0, 8); |
||||
console.JumpToLine(line); |
||||
|
||||
} catch (System.Exception ex) { |
||||
LoggingService.Error(ex.Message); |
||||
} |
||||
} |
||||
|
||||
public bool Refresh(bool refreshMemoryAddresses = false) |
||||
{ |
||||
if (console == null) |
||||
return false; |
||||
|
||||
console.Clear(); |
||||
if (debuggedProcess == null || debugger.IsProcessRunning) { |
||||
console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NotDebuggingOrProcessRunning")); |
||||
return false; |
||||
} |
||||
|
||||
if (currentAddressIndex <= -1) { |
||||
console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings")); |
||||
currentAddressIndex = -1; |
||||
return false; |
||||
} |
||||
|
||||
if (refreshMemoryAddresses) |
||||
memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); |
||||
|
||||
if (memoryAddresses.Count == 0) { |
||||
console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings")); |
||||
return false; |
||||
} |
||||
|
||||
if (currentAddressIndex >= memoryAddresses.Count) { |
||||
console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings")); |
||||
currentAddressIndex = memoryAddresses.Count ; |
||||
return false; |
||||
} |
||||
|
||||
RetrieveMemory(); |
||||
return true; |
||||
} |
||||
|
||||
void RetrieveMemory() |
||||
{ |
||||
// refresh data
|
||||
addressesMapping.Clear(); |
||||
|
||||
// get current address
|
||||
var item = memoryAddresses[currentAddressIndex]; |
||||
long address = item.Item1; |
||||
long size = item.Item2; |
||||
|
||||
memory = debuggedProcess.ReadProcessMemory(address, size); |
||||
if (memory == null) { |
||||
console.Append(string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.UnableToReadFormat"), address.ToString("X8"), size)); |
||||
return; |
||||
} |
||||
|
||||
DisplayMemory(); |
||||
} |
||||
|
||||
public void DisplayMemory() |
||||
{ |
||||
if (memory == null || memory.Length == 0) |
||||
return; |
||||
|
||||
if (console == null) |
||||
return; |
||||
|
||||
console.Clear(); |
||||
addressesMapping.Clear(); |
||||
var item = memoryAddresses[currentAddressIndex]; |
||||
long address = item.Item1; |
||||
|
||||
int totalBytesPerRow = columnsNumber * displayByteSize; |
||||
int numberOfLines = memory.Length / totalBytesPerRow; |
||||
int remainingMemory = memory.Length % totalBytesPerRow; |
||||
int currentLine = 2;// line in the console
|
||||
int index = 0;// index in memory arrray of current line
|
||||
|
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.Append(string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.ReadingFromFormat"), address.ToString("X8"), (address + memory.Length).ToString("X8"), memory.Length)); |
||||
sb.Append(Environment.NewLine); |
||||
|
||||
while (index < numberOfLines) { |
||||
addressesMapping.Add(address, currentLine); |
||||
// write address
|
||||
sb.Append(address.ToString("X8")); |
||||
address += (long)totalBytesPerRow; |
||||
sb.Append(" "); |
||||
|
||||
// write bytes
|
||||
int start = index * totalBytesPerRow; |
||||
for (int i = 0; i < columnsNumber; ++i) { |
||||
for (int j = 0; j < displayByteSize; ++j) { |
||||
sb.Append(memory[start++].ToString("X2")); |
||||
} |
||||
sb.Append(" "); |
||||
} |
||||
|
||||
// write chars
|
||||
start = index * totalBytesPerRow; |
||||
StringBuilder sb1 = new StringBuilder(); |
||||
for (int i = 0; i < totalBytesPerRow; ++i) { |
||||
sb1.Append(((char)memory[start++]).ToString()); |
||||
} |
||||
string s = sb1.ToString(); |
||||
s = Regex.Replace(s, "\\r\\n", string.Empty); |
||||
s = Regex.Replace(s, "\\n", string.Empty); |
||||
s = Regex.Replace(s, "\\r", string.Empty); |
||||
sb.Append(s); |
||||
sb.Append(Environment.NewLine); |
||||
currentLine++; |
||||
index++; |
||||
} |
||||
|
||||
// write the rest of memory
|
||||
if (remainingMemory != 0) { |
||||
addressesMapping.Add(address, currentLine); |
||||
// write address
|
||||
sb.Append(address.ToString("X8")); |
||||
sb.Append(" "); |
||||
|
||||
// write bytes
|
||||
int start = index * remainingMemory * displayByteSize; |
||||
for (int i = 0; i < remainingMemory; ++i) { |
||||
for (int j = 0; j < displayByteSize; j++) { |
||||
sb.Append(memory[start++].ToString("X2")); |
||||
} |
||||
sb.Append(" "); |
||||
} |
||||
|
||||
// write chars
|
||||
start = index * remainingMemory * displayByteSize; |
||||
StringBuilder sb1 = new StringBuilder(); |
||||
for (int i = 0; i < remainingMemory * displayByteSize; ++i) { |
||||
sb1.Append(((char)memory[start++]).ToString()); |
||||
} |
||||
string s = sb1.ToString(); |
||||
s = Regex.Replace(s, "\\r\\n", string.Empty); |
||||
s = Regex.Replace(s, "\\n", string.Empty); |
||||
s = Regex.Replace(s, "\\r", string.Empty); |
||||
sb.Append(s); |
||||
} |
||||
|
||||
console.Append(sb.ToString()); |
||||
} |
||||
|
||||
public void MoveToPreviousAddress() |
||||
{ |
||||
currentAddressIndex--; |
||||
Refresh(); |
||||
} |
||||
|
||||
public void MoveToNextAddress() |
||||
{ |
||||
currentAddressIndex++; |
||||
Refresh(); |
||||
} |
||||
} |
||||
|
||||
internal static class MemoryPadExtensions |
||||
{ |
||||
/// <summary>
|
||||
/// Does a binary search when the Item1 from Tuple is sorted.
|
||||
/// </summary>
|
||||
/// <param name="source">Source of data.</param>
|
||||
/// <param name="item1">Item to search.</param>
|
||||
/// <returns>The nearest index.</returns>
|
||||
internal static int BinarySearch<T>(this List<Tuple<long, T>> source, long item1) |
||||
{ |
||||
// base checks
|
||||
if (source == null) |
||||
throw new NullReferenceException("Source is null!"); |
||||
|
||||
if (source.Count == 0) |
||||
return -1; |
||||
|
||||
if (item1 < source[0].Item1) |
||||
return 0; |
||||
|
||||
if (item1 > source[source.Count - 1].Item1) |
||||
return source.Count; |
||||
|
||||
// do a binary search since the source is sorted
|
||||
int first = 0; int last = source.Count; |
||||
while (first < last - 1) { |
||||
int middle = (first + last) / 2; |
||||
if (source[middle].Item1 == item1) |
||||
return middle; |
||||
else |
||||
if (source[middle].Item1 < item1) |
||||
first = middle; |
||||
else |
||||
last = middle; |
||||
} |
||||
|
||||
return first; |
||||
} |
||||
} |
||||
} |
@ -1,72 +0,0 @@
@@ -1,72 +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 ICSharpCode.Core; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Windows; |
||||
using Debugger; |
||||
using Debugger.AddIn.Visualizers.Graph; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
||||
{ |
||||
/// <summary>
|
||||
/// Description of ObjectGraphPad.
|
||||
/// </summary>
|
||||
public class ObjectGraphPad : DebuggerPad |
||||
{ |
||||
Process debuggedProcess; |
||||
ObjectGraphControl objectGraphControl; |
||||
static ObjectGraphPad instance; |
||||
|
||||
public ObjectGraphPad() |
||||
{ |
||||
instance = this; |
||||
} |
||||
|
||||
/// <remarks>Always check if Instance is null, might be null if pad is not opened!</remarks>
|
||||
public static ObjectGraphPad Instance { |
||||
get { return instance; } |
||||
} |
||||
|
||||
protected override void InitializeComponents() |
||||
{ |
||||
objectGraphControl = new ObjectGraphControl(); |
||||
panel.Children.Add(objectGraphControl); |
||||
} |
||||
|
||||
|
||||
protected override void RefreshPad() |
||||
{ |
||||
// BUG: if pad window is undocked and floats standalone, IsVisible == false (so pad won't refresh)
|
||||
// REQUEST: need to refresh when pad becomes visible -> VisibleChanged event?
|
||||
if (!objectGraphControl.IsVisible) |
||||
{ |
||||
return; |
||||
} |
||||
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) { |
||||
this.objectGraphControl.Clear(); |
||||
return; |
||||
} |
||||
this.objectGraphControl.RefreshView(); |
||||
} |
||||
|
||||
protected override void SelectProcess(Process process) |
||||
{ |
||||
if (debuggedProcess != null) { |
||||
debuggedProcess.Paused -= debuggedProcess_Paused; |
||||
} |
||||
debuggedProcess = process; |
||||
if (debuggedProcess != null) { |
||||
debuggedProcess.Paused += debuggedProcess_Paused; |
||||
} |
||||
InvalidatePad(); |
||||
} |
||||
|
||||
void debuggedProcess_Paused(object sender, ProcessEventArgs e) |
||||
{ |
||||
InvalidatePad(); |
||||
} |
||||
} |
||||
} |
@ -1,65 +0,0 @@
@@ -1,65 +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; |
||||
|
||||
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 (!debuggedProcess.IsPaused) { |
||||
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; |
||||
} |
||||
InvalidatePad(); |
||||
}; |
||||
|
||||
menu.Items.Add(freezeItem); |
||||
} |
||||
} |
||||
} |
@ -1,154 +0,0 @@
@@ -1,154 +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 : DebuggerPad |
||||
{ |
||||
ListView runningThreadsList; |
||||
ObservableCollection<ThreadModel> runningThreads; |
||||
Process debuggedProcess; |
||||
|
||||
protected override void InitializeComponents() |
||||
{ |
||||
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(); }; |
||||
} |
||||
|
||||
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 override void SelectProcess(Process process) |
||||
{ |
||||
if (debuggedProcess != null) { |
||||
debuggedProcess.Paused -= debuggedProcess_Paused; |
||||
debuggedProcess.Threads.Added -= debuggedProcess_ThreadStarted; |
||||
} |
||||
debuggedProcess = process; |
||||
if (debuggedProcess != null) { |
||||
debuggedProcess.Paused += debuggedProcess_Paused; |
||||
debuggedProcess.Threads.Added += debuggedProcess_ThreadStarted; |
||||
} |
||||
runningThreads.Clear(); |
||||
InvalidatePad(); |
||||
} |
||||
|
||||
void debuggedProcess_Paused(object sender, ProcessEventArgs e) |
||||
{ |
||||
InvalidatePad(); |
||||
} |
||||
|
||||
void debuggedProcess_ThreadStarted(object sender, CollectionItemEventArgs<Thread> e) |
||||
{ |
||||
AddThread(e.Item); |
||||
} |
||||
|
||||
protected override void RefreshPad() |
||||
{ |
||||
if (debuggedProcess == null || debuggedProcess.IsRunning) { |
||||
runningThreads.Clear(); |
||||
return; |
||||
} |
||||
|
||||
LoggingService.Info("Threads refresh"); |
||||
|
||||
debuggedProcess.EnqueueForEach( |
||||
Dispatcher.CurrentDispatcher, |
||||
debuggedProcess.Threads.ToList(), |
||||
t => AddThread(t) |
||||
); |
||||
} |
||||
|
||||
void RunningThreadsListItemActivate(object sender, EventArgs e) |
||||
{ |
||||
if (debuggedProcess != null) { |
||||
if (debuggedProcess.IsPaused) { |
||||
ThreadModel obj = runningThreadsList.SelectedItems[0] as ThreadModel; |
||||
Thread thread = obj.Thread; |
||||
|
||||
// check for options - if these options are enabled, selecting the frame should not continue
|
||||
if ((thread.MostRecentStackFrame == null || !thread.MostRecentStackFrame.HasSymbols) && |
||||
!DebuggingOptions.Instance.DecompileCodeWithoutSymbols) { |
||||
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWithoutDecompiledCodeOptions}", |
||||
"${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); |
||||
return; |
||||
} |
||||
|
||||
debuggedProcess.SelectedThread = thread; |
||||
debuggedProcess.SelectedThread.SelectedStackFrame = debuggedProcess.SelectedThread.MostRecentStackFrame; |
||||
if (debuggedProcess.SelectedThread.SelectedStackFrame != null) { |
||||
debuggedProcess.PauseSession.PausedReason = PausedReason.CurrentThreadChanged; |
||||
debuggedProcess.OnPaused(); // Force refresh of pads - artificial pause
|
||||
} else { |
||||
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchOnNAFrame}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); |
||||
} |
||||
} 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); |
||||
thread.Exited += (s, e) => RemoveThread(e.Thread); |
||||
} |
||||
|
||||
void RemoveThread(Thread thread) |
||||
{ |
||||
if (thread == null) |
||||
return; |
||||
|
||||
runningThreads.RemoveWhere(model => model.Thread == thread); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,138 @@
@@ -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"); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<src:BaseWatchBox |
||||
x:Class="Debugger.AddIn.Pads.WatchInputBox" xmlns:src="clr-namespace:ICSharpCode.SharpDevelop.Gui.Pads;assembly=ICSharpCode.SharpDevelop" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:core="http://icsharpcode.net/sharpdevelop/core" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" |
||||
Style="{x:Static core:GlobalStyles.DialogWindowStyle}" |
||||
WindowStartupLocation="CenterScreen" |
||||
WindowState="Normal" |
||||
WindowStyle="ToolWindow" |
||||
Width="300" |
||||
SizeToContent="Height" |
||||
ResizeMode="NoResize"> |
||||
<DockPanel Margin="4"> |
||||
<widgets:UniformGridWithSpacing |
||||
Columns="2" |
||||
DockPanel.Dock="Bottom" |
||||
Margin="0,8" |
||||
Grid.Row="1" |
||||
HorizontalAlignment="Center"> |
||||
<Button |
||||
Name="AcceptButton" |
||||
Style="{x:Static core:GlobalStyles.ButtonStyle}" |
||||
Content="{core:Localize Global.OKButtonText}" |
||||
Click="AcceptButton_Click" |
||||
IsDefault="True" /> |
||||
<Button |
||||
Name="CancelButton" |
||||
Style="{x:Static core:GlobalStyles.ButtonStyle}" |
||||
Content="{core:Localize Global.CancelButtonText}" |
||||
Click="CancelButton_Click" |
||||
IsCancel="True" /> |
||||
</widgets:UniformGridWithSpacing> |
||||
<ContentPresenter |
||||
MaxHeight="75" |
||||
Name="ConsolePanel" /> |
||||
</DockPanel> |
||||
</src:BaseWatchBox> |
@ -1,170 +0,0 @@
@@ -1,170 +0,0 @@
|
||||
// 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.IO; |
||||
using System.Windows; |
||||
using System.Windows.Input; |
||||
|
||||
using ICSharpCode.AvalonEdit; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Gui.Pads; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.Pads |
||||
{ |
||||
/// <summary>
|
||||
/// Interaction logic for WatchBox.xaml
|
||||
/// </summary>
|
||||
public partial class WatchInputBox : BaseWatchBox |
||||
{ |
||||
NRefactoryResolver resolver; |
||||
SupportedLanguage language; |
||||
|
||||
public SupportedLanguage ScriptLanguage { |
||||
get { return language; } |
||||
} |
||||
|
||||
public WatchInputBox(string text, string caption) : base() |
||||
{ |
||||
InitializeComponent(); |
||||
|
||||
// UI
|
||||
text = StringParser.Parse(text); |
||||
this.Title = StringParser.Parse(caption); |
||||
this.ConsolePanel.Content = console; |
||||
|
||||
if (ProjectService.CurrentProject == null) |
||||
language = GetLanguageFromActiveViewContent(); |
||||
else |
||||
language = GetLanguage(ProjectService.CurrentProject.Language); |
||||
|
||||
resolver = new NRefactoryResolver(LanguageProperties.GetLanguage(language.ToString())); |
||||
|
||||
switch (language) { |
||||
case SupportedLanguage.CSharp: |
||||
console.SetHighlighting("C#"); |
||||
break; |
||||
case SupportedLanguage.VBNet: |
||||
console.SetHighlighting("VBNET"); |
||||
break; |
||||
} |
||||
|
||||
// get process
|
||||
this.Process = ((WindowsDebugger)DebuggerService.CurrentDebugger).DebuggedProcess; |
||||
} |
||||
|
||||
private Process Process { get; set; } |
||||
|
||||
protected override void AbstractConsolePadTextEntered(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
if (this.Process == null || this.Process.IsRunning) |
||||
return; |
||||
|
||||
if (this.Process.SelectedStackFrame == null || this.Process.SelectedStackFrame.NextStatement == null) |
||||
return; |
||||
|
||||
foreach (char ch in e.Text) { |
||||
if (ch == '.') { |
||||
ShowDotCompletion(console.CommandText); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ShowDotCompletion(string currentText) |
||||
{ |
||||
var seg = Process.SelectedStackFrame.NextStatement; |
||||
|
||||
var expressionFinder = ParserService.GetExpressionFinder(seg.Filename); |
||||
var info = ParserService.GetParseInformation(seg.Filename); |
||||
|
||||
string text = ParserService.GetParseableFileContent(seg.Filename).Text; |
||||
|
||||
int currentOffset = TextEditor.Caret.Offset - console.CommandOffset - 1; |
||||
|
||||
var expr = expressionFinder.FindExpression(currentText, currentOffset); |
||||
|
||||
expr.Region = new DomRegion(seg.StartLine, seg.StartColumn, seg.EndLine, seg.EndColumn); |
||||
|
||||
var rr = resolver.Resolve(expr, info, text); |
||||
|
||||
if (rr != null) { |
||||
TextEditor.ShowCompletionWindow(new DotCodeCompletionItemProvider().GenerateCompletionListForResolveResult(rr, expr.Context)); |
||||
} |
||||
} |
||||
|
||||
bool CheckSyntax() |
||||
{ |
||||
string command = console.CommandText.Trim(); |
||||
|
||||
// FIXME workaround the NRefactory issue that needs a ; at the end
|
||||
if (language == SupportedLanguage.CSharp && !command.EndsWith(";")) |
||||
command += ";"; |
||||
|
||||
using (var parser = ParserFactory.CreateParser(language, new StringReader(command))) { |
||||
parser.ParseExpression(); |
||||
if (parser.Errors.Count > 0) { |
||||
MessageService.ShowError(parser.Errors.ErrorOutput); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
SupportedLanguage GetLanguage(string language) |
||||
{ |
||||
if ("VBNet".Equals(language, StringComparison.OrdinalIgnoreCase) |
||||
|| "VB".Equals(language, StringComparison.OrdinalIgnoreCase) |
||||
|| "VB.NET".Equals(language, StringComparison.OrdinalIgnoreCase)) |
||||
return SupportedLanguage.VBNet; |
||||
|
||||
return SupportedLanguage.CSharp; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the language used in the currently active view content. This is useful, when there is no project
|
||||
/// opened and we still want to add watches (i.e. the debugger is attached to an existing process without a solution).
|
||||
/// </summary>
|
||||
SupportedLanguage GetLanguageFromActiveViewContent() |
||||
{ |
||||
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; |
||||
|
||||
if (provider != null && provider.TextEditor != null) { |
||||
string extension = Path.GetExtension(provider.TextEditor.FileName).ToLowerInvariant(); |
||||
switch (extension) { |
||||
case ".cs": |
||||
return SupportedLanguage.CSharp; |
||||
case ".vb": |
||||
return SupportedLanguage.VBNet; |
||||
} |
||||
} |
||||
|
||||
return SupportedLanguage.CSharp; |
||||
} |
||||
|
||||
void AcceptButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
if (!this.CheckSyntax()) |
||||
return; |
||||
|
||||
this.DialogResult = true; |
||||
this.Close(); |
||||
} |
||||
|
||||
void CancelButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
DialogResult = false; |
||||
this.Close(); |
||||
} |
||||
} |
||||
} |
@ -1,49 +0,0 @@
@@ -1,49 +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.Text; |
||||
using Debugger.AddIn.TreeModel; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Gui.Pads |
||||
{ |
||||
public class TextNode : TreeNode, ISetText |
||||
{ |
||||
public TextNode(TreeNode parent, string text, SupportedLanguage language) |
||||
: base(parent) |
||||
{ |
||||
this.Name = text; |
||||
this.Language = language; |
||||
} |
||||
|
||||
public override bool CanSetText { |
||||
get { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public override bool SetText(string text) |
||||
{ |
||||
this.Text = text; |
||||
return true; |
||||
} |
||||
|
||||
public bool SetName(string name) |
||||
{ |
||||
this.Name = name; |
||||
return true; |
||||
} |
||||
|
||||
public SupportedLanguage Language { get; set; } |
||||
} |
||||
|
||||
public class ErrorInfoNode : ICorDebug.InfoNode |
||||
{ |
||||
public ErrorInfoNode(string name, string text) : base(null, name, text) |
||||
{ |
||||
IconImage = DebuggerResourceService.GetImage("Icons.16x16.Error"); |
||||
} |
||||
} |
||||
} |
@ -1,82 +0,0 @@
@@ -1,82 +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.IO; |
||||
using System.Reflection; |
||||
using System.Runtime.Remoting; |
||||
using System.Security.Policy; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Services |
||||
{ |
||||
[Serializable] |
||||
class RemotingConfigurationHelpper |
||||
{ |
||||
public string path; |
||||
|
||||
public RemotingConfigurationHelpper(string path) |
||||
{ |
||||
this.path = path; |
||||
} |
||||
|
||||
public static string GetLoadedAssemblyPath(string assemblyName) |
||||
{ |
||||
string path = null; |
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { |
||||
try { |
||||
string fullFilename = assembly.Location; |
||||
if (Path.GetFileName(fullFilename).Equals(assemblyName, StringComparison.OrdinalIgnoreCase)) { |
||||
path = Path.GetDirectoryName(fullFilename); |
||||
break; |
||||
} |
||||
} catch (NotSupportedException) { |
||||
// assembly.Location throws NotSupportedException for assemblies emitted using
|
||||
// Reflection.Emit by custom controls used in the forms designer
|
||||
} |
||||
} |
||||
if (path == null) { |
||||
throw new Exception("Assembly " + assemblyName + " is not loaded"); |
||||
} |
||||
return path; |
||||
} |
||||
|
||||
public void Configure() |
||||
{ |
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; |
||||
|
||||
RemotingConfiguration.Configure(Path.Combine(path, "Client.config"), false); |
||||
|
||||
string baseDir = Directory.GetDirectoryRoot(AppDomain.CurrentDomain.BaseDirectory); |
||||
string relDirs = AppDomain.CurrentDomain.BaseDirectory + ";" + path; |
||||
AppDomain serverAppDomain = AppDomain.CreateDomain("Debugging server", |
||||
new Evidence(AppDomain.CurrentDomain.Evidence), |
||||
baseDir, |
||||
relDirs, |
||||
AppDomain.CurrentDomain.ShadowCopyFiles); |
||||
serverAppDomain.DoCallBack(new CrossAppDomainDelegate(ConfigureServer)); |
||||
} |
||||
|
||||
private void ConfigureServer() |
||||
{ |
||||
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; |
||||
RemotingConfiguration.Configure(Path.Combine(path, "Server.config"), false); |
||||
} |
||||
|
||||
Assembly AssemblyResolve(object sender, ResolveEventArgs args) |
||||
{ |
||||
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { |
||||
try { |
||||
string fullFilename = assembly.Location; |
||||
if (Path.GetFileNameWithoutExtension(fullFilename).Equals(args.Name, StringComparison.OrdinalIgnoreCase) || |
||||
assembly.FullName == args.Name) { |
||||
return assembly; |
||||
} |
||||
} catch (NotSupportedException) { |
||||
// assembly.Location throws NotSupportedException for assemblies emitted using
|
||||
// Reflection.Emit by custom controls used in the forms designer
|
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -1,102 +0,0 @@
@@ -1,102 +0,0 @@
|
||||
// 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.Windows; |
||||
using System.Windows.Controls.Primitives; |
||||
using System.Windows.Input; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace Debugger.AddIn.Tooltips |
||||
{ |
||||
/// <summary>
|
||||
/// Popup containing <see cref="DebuggerTooltipControl"></see>.
|
||||
/// </summary>
|
||||
public class DebuggerPopup : Popup |
||||
{ |
||||
internal DebuggerTooltipControl innerControl; |
||||
|
||||
public DebuggerPopup(DebuggerTooltipControl parentControl, Location logicalPosition, bool showPins = true) |
||||
{ |
||||
this.innerControl = new DebuggerTooltipControl(parentControl, logicalPosition) { ShowPins = showPins }; |
||||
this.innerControl.containingPopup = this; |
||||
this.Child = this.innerControl; |
||||
this.IsLeaf = false; |
||||
|
||||
//this.KeyDown += new KeyEventHandler(DebuggerPopup_KeyDown);
|
||||
|
||||
//this.innerControl.Focusable = true;
|
||||
//Keyboard.Focus(this.innerControl);
|
||||
//this.AllowsTransparency = true;
|
||||
//this.PopupAnimation = PopupAnimation.Slide;
|
||||
} |
||||
|
||||
// attempt to propagate shortcuts to main windows when Popup is focusable (needed for keyboard scrolling + editing)
|
||||
/*void DebuggerPopup_KeyDown(object sender, KeyEventArgs e) |
||||
{ |
||||
LoggingService.Debug("Unhandled popup key down: " + e.Key); |
||||
RaiseEventPair(WorkbenchSingleton.MainWindow, PreviewKeyDownEvent, KeyDownEvent, |
||||
new KeyEventArgs(e.KeyboardDevice, e.InputSource, e.Timestamp, e.Key)); |
||||
} |
||||
|
||||
// copied from CompletionWindowBase
|
||||
static bool RaiseEventPair(UIElement target, RoutedEvent previewEvent, RoutedEvent @event, RoutedEventArgs args) |
||||
{ |
||||
if (target == null) |
||||
throw new ArgumentNullException("target"); |
||||
if (previewEvent == null) |
||||
throw new ArgumentNullException("previewEvent"); |
||||
if (@event == null) |
||||
throw new ArgumentNullException("event"); |
||||
if (args == null) |
||||
throw new ArgumentNullException("args"); |
||||
args.RoutedEvent = previewEvent; |
||||
target.RaiseEvent(args); |
||||
args.RoutedEvent = @event; |
||||
target.RaiseEvent(args); |
||||
return args.Handled; |
||||
}*/ |
||||
|
||||
public IEnumerable<ITreeNode> ItemsSource |
||||
{ |
||||
get { return this.innerControl.ItemsSource; } |
||||
set { this.innerControl.SetItemsSource(value); } |
||||
} |
||||
|
||||
private bool isLeaf; |
||||
public bool IsLeaf |
||||
{ |
||||
get { return isLeaf; } |
||||
set |
||||
{ |
||||
isLeaf = value; |
||||
// leaf popup closes on lost focus
|
||||
this.StaysOpen = !isLeaf; |
||||
} |
||||
} |
||||
|
||||
protected override void OnClosed(EventArgs e) |
||||
{ |
||||
base.OnClosed(e); |
||||
if (isLeaf) { |
||||
this.innerControl.CloseOnLostFocus(); |
||||
} |
||||
} |
||||
|
||||
public void Open() |
||||
{ |
||||
this.IsOpen = true; |
||||
} |
||||
|
||||
public void CloseSelfAndChildren() |
||||
{ |
||||
this.innerControl.CloseChildPopups(); |
||||
this.IsOpen = false; |
||||
} |
||||
} |
||||
} |
@ -1,113 +0,0 @@
@@ -1,113 +0,0 @@
|
||||
// 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.Windows.Controls; |
||||
|
||||
using ICSharpCode.SharpDevelop; |
||||
|
||||
namespace Debugger.AddIn.Tooltips |
||||
{ |
||||
/// <summary>
|
||||
/// ItemsControl wrapper that takes VirtualizingIEnumerable as source,
|
||||
/// and adds additional items from the source to underlying ItemsControl when scrolled to bottom.
|
||||
/// </summary>
|
||||
public class LazyItemsControl<T> |
||||
{ |
||||
private ItemsControl itemsControl; |
||||
private int initialItemsCount; |
||||
|
||||
/// <summary>
|
||||
/// Creates new instance of LazyItemsControl.
|
||||
/// </summary>
|
||||
/// <param name="wrappedItemsControl">ItemsControl to wrap and add items to it when scrolled to bottom.</param>
|
||||
/// <param name="initialItemsCount">Number of items to be initially displayed in wrapped ItemsControl.</param>
|
||||
public LazyItemsControl(ItemsControl wrappedItemsControl, int initialItemsCount) |
||||
{ |
||||
if (wrappedItemsControl == null) |
||||
throw new ArgumentNullException("wrappedItemsControl"); |
||||
|
||||
this.initialItemsCount = initialItemsCount; |
||||
this.itemsControl = wrappedItemsControl; |
||||
this.itemsControl.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll)); |
||||
} |
||||
|
||||
private ScrollViewer scrollViewerCached; |
||||
public ScrollViewer ScrollViewer |
||||
{ |
||||
get |
||||
{ |
||||
if (this.scrollViewerCached == null) |
||||
this.scrollViewerCached = this.itemsControl.GetScrollViewer(); |
||||
return this.scrollViewerCached; |
||||
} |
||||
} |
||||
|
||||
public bool IsScrolledToStart |
||||
{ |
||||
get |
||||
{ |
||||
if (ScrollViewer == null) // Visual tree not initialized yet
|
||||
return false; |
||||
return ScrollViewer.VerticalOffset == 0; |
||||
} |
||||
} |
||||
|
||||
public bool IsScrolledToEnd |
||||
{ |
||||
get |
||||
{ |
||||
if (itemsSourceTotalCount == null) { |
||||
// not scrolled to end of IEnumerable yet
|
||||
return false; |
||||
} |
||||
// already scrolled to end of IEnumerable
|
||||
int totalItems = itemsSourceTotalCount.Value; |
||||
return (ScrollViewer.VerticalOffset >= totalItems - ScrollViewer.ViewportHeight); |
||||
} |
||||
} |
||||
|
||||
private int? itemsSourceTotalCount = null; |
||||
/// <summary> Items count of underlying IEnumerable. Null until scrolled to the end of IEnumerable. </summary>
|
||||
public int? ItemsSourceTotalCount |
||||
{ |
||||
get |
||||
{ |
||||
return this.itemsSourceTotalCount; |
||||
} |
||||
} |
||||
|
||||
private VirtualizingIEnumerable<T> itemsSource; |
||||
/// <summary> The collection that underlying ItemsControl sees. </summary>
|
||||
public VirtualizingIEnumerable<T> ItemsSource |
||||
{ |
||||
get { return itemsSource; } |
||||
set |
||||
{ |
||||
this.itemsSource = value; |
||||
addNextItems(this.itemsSource, initialItemsCount); |
||||
this.itemsControl.ItemsSource = value; |
||||
} |
||||
} |
||||
|
||||
private void addNextItems(VirtualizingIEnumerable<T> sourceToAdd, int nItems) |
||||
{ |
||||
sourceToAdd.AddNextItems(nItems); |
||||
if (!sourceToAdd.HasNext) { |
||||
// all items from IEnumerable have been added
|
||||
this.itemsSourceTotalCount = sourceToAdd.Count; |
||||
} |
||||
} |
||||
|
||||
private void handleScroll(object sender, ScrollChangedEventArgs e) |
||||
{ |
||||
if (e.VerticalChange > 0) { |
||||
// scrolled to bottom
|
||||
if (e.VerticalOffset >= this.itemsSource.Count - e.ViewportHeight) { |
||||
addNextItems(this.itemsSource, (int)e.VerticalChange); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,29 +0,0 @@
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<UserControl |
||||
Background="Transparent" |
||||
x:Class="Debugger.AddIn.Tooltips.PinCloseControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
<UserControl.Resources> |
||||
<ResourceDictionary> |
||||
<ResourceDictionary.MergedDictionaries> |
||||
<ResourceDictionary |
||||
Source="PinControlsDictionary.xaml" /> |
||||
</ResourceDictionary.MergedDictionaries> |
||||
</ResourceDictionary> |
||||
</UserControl.Resources> |
||||
<StackPanel> |
||||
<Button |
||||
Name="CloseButton" |
||||
Click="CloseButton_Click" |
||||
Template="{StaticResource CloseButtonTemplate}" /> |
||||
<ToggleButton |
||||
Name="UnpinButton" |
||||
Checked="UnpinButton_Checked" |
||||
Unchecked="UnpinButton_Unchecked" |
||||
Template="{StaticResource PinButtonTemplate}" /> |
||||
<ToggleButton |
||||
Name="CommentButton" |
||||
Checked="CommentButton_Checked" |
||||
Unchecked="CommentButton_Unchecked" |
||||
Template="{StaticResource CommentButtonTemplate}" /> |
||||
</StackPanel> |
||||
</UserControl> |
@ -1,74 +0,0 @@
@@ -1,74 +0,0 @@
|
||||
// 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; |
||||
|
||||
namespace Debugger.AddIn.Tooltips |
||||
{ |
||||
public class ShowingCommentEventArgs : EventArgs |
||||
{ |
||||
public bool ShowComment { get; private set; } |
||||
|
||||
public ShowingCommentEventArgs(bool showComment) |
||||
{ |
||||
ShowComment = showComment; |
||||
} |
||||
} |
||||
|
||||
public partial class PinCloseControl : UserControl |
||||
{ |
||||
public event EventHandler Closed; |
||||
|
||||
public event EventHandler PinningChanged; |
||||
|
||||
public event EventHandler<ShowingCommentEventArgs> ShowingComment; |
||||
|
||||
public PinCloseControl() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
public bool IsChecked { |
||||
get { |
||||
return UnpinButton.IsChecked.GetValueOrDefault(false); |
||||
} |
||||
} |
||||
|
||||
void CloseButton_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
var handler = Closed; |
||||
if (handler != null) |
||||
handler(this, EventArgs.Empty); |
||||
} |
||||
|
||||
void CommentButton_Checked(object sender, RoutedEventArgs e) |
||||
{ |
||||
var handler = ShowingComment; |
||||
if (handler != null) |
||||
handler(this, new ShowingCommentEventArgs(true)); |
||||
} |
||||
|
||||
void CommentButton_Unchecked(object sender, RoutedEventArgs e) |
||||
{ |
||||
var handler = ShowingComment; |
||||
if (handler != null) |
||||
handler(this, new ShowingCommentEventArgs(false)); |
||||
} |
||||
|
||||
void UnpinButton_Checked(object sender, RoutedEventArgs e) |
||||
{ |
||||
var handler = PinningChanged; |
||||
if (handler != null) |
||||
handler(this, EventArgs.Empty); |
||||
} |
||||
|
||||
void UnpinButton_Unchecked(object sender, RoutedEventArgs e) |
||||
{ |
||||
var handler = PinningChanged; |
||||
if (handler != null) |
||||
handler(this, EventArgs.Empty); |
||||
} |
||||
} |
||||
} |
@ -1,363 +0,0 @@
@@ -1,363 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:local="clr-namespace:Debugger.AddIn.Tooltips" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
> |
||||
<LinearGradientBrush x:Key="OrangeBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||
<LinearGradientBrush.GradientStops> |
||||
<GradientStop Offset="0" Color="White" /> |
||||
<GradientStop Offset="0.5" Color="Orange" /> |
||||
<GradientStop Offset="1" Color="Orange" /> |
||||
</LinearGradientBrush.GradientStops> |
||||
</LinearGradientBrush> |
||||
|
||||
<LinearGradientBrush x:Key="OrangePressedBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||
<LinearGradientBrush.GradientStops> |
||||
<GradientStop Offset="1" Color="White" /> |
||||
<GradientStop Offset="0.5" Color="Orange" /> |
||||
<GradientStop Offset="0" Color="Orange" /> |
||||
</LinearGradientBrush.GradientStops> |
||||
</LinearGradientBrush> |
||||
|
||||
<LinearGradientBrush x:Key="SilverBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||
<LinearGradientBrush.GradientStops> |
||||
<GradientStop Offset="0" Color="White" /> |
||||
<GradientStop Offset="0.5" Color="LightGray" /> |
||||
<GradientStop Offset="1" Color="LightGray" /> |
||||
</LinearGradientBrush.GradientStops> |
||||
</LinearGradientBrush> |
||||
|
||||
<LinearGradientBrush x:Key="SilverPressedBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||
<LinearGradientBrush.GradientStops> |
||||
<GradientStop Offset="1" Color="White" /> |
||||
<GradientStop Offset="0.5" Color="LightGray" /> |
||||
<GradientStop Offset="0" Color="LightGray" /> |
||||
</LinearGradientBrush.GradientStops> |
||||
</LinearGradientBrush> |
||||
|
||||
<ControlTemplate x:Key="CloseButtonTemplate" TargetType="Button"> |
||||
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="2,2,0,0" BorderThickness="1" BorderBrush="Black" Background="{StaticResource SilverPressedBrushKey}"> |
||||
<Canvas> |
||||
<Line X1="3.5" X2="10.5" Y1="3.5" Y2="10.5" Stroke="Black" StrokeThickness="2"/> |
||||
<Line X1="3.5" X2="10.5" Y1="10.5" Y2="3.5" Stroke="Black" StrokeThickness="2"/> |
||||
</Canvas> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="UIElement.IsMouseOver" Value="true"> |
||||
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangeBrushKey}"/> |
||||
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||
</Trigger> |
||||
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangePressedBrushKey}"/> |
||||
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
|
||||
<TransformGroup x:Key="Rotate"> |
||||
<RotateTransform Angle="270" CenterX="7" CenterY="7"/> |
||||
</TransformGroup> |
||||
|
||||
<TransformGroup x:Key="RotateUnpin"> |
||||
<RotateTransform Angle="270" CenterX="7" CenterY="7"/> |
||||
<RotateTransform Angle="-90" CenterX="7" CenterY="7"/> |
||||
<ScaleTransform ScaleY="-1" CenterX="7" CenterY="7"/> |
||||
</TransformGroup> |
||||
|
||||
<TransformGroup x:Key="RotatePin"> |
||||
<RotateTransform Angle="-90" CenterX="7" CenterY="7"/> |
||||
</TransformGroup> |
||||
|
||||
<TransformGroup x:Key="FlipComment"> |
||||
<ScaleTransform CenterX="7" CenterY="7" ScaleY="-1"/> |
||||
</TransformGroup> |
||||
|
||||
<ControlTemplate x:Key="PinButtonTemplate" TargetType="ToggleButton"> |
||||
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="0" BorderThickness="1" BorderBrush="Black" Background="{StaticResource SilverPressedBrushKey}"> |
||||
<Canvas Name="TheCanvas"> |
||||
<Line X1="4" X2="10" Y1="2" Y2="2" Stroke="Black" StrokeThickness="1"/> |
||||
<Line X1="9" X2="9" Y1="2" Y2="8" Stroke="Black" StrokeThickness="1"/> |
||||
<Line X1="2" X2="12" Y1="8" Y2="8" Stroke="Black" StrokeThickness="1"/> |
||||
<Rectangle Fill="Black" Width="2" Height="5" Canvas.Left="4" Canvas.Top="3"/> |
||||
<Line X1="7" X2="7" Y1="9" Y2="12" Stroke="Black" StrokeThickness="1"/> |
||||
</Canvas> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="UIElement.IsMouseOver" Value="true"> |
||||
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangeBrushKey}"/> |
||||
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||
</Trigger> |
||||
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotatePin}"/> |
||||
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangePressedBrushKey}"/> |
||||
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||
</Trigger> |
||||
<Trigger Property="IsChecked" Value="true"> |
||||
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotatePin}"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
|
||||
<ControlTemplate x:Key="CommentButtonTemplate" TargetType="ToggleButton"> |
||||
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="0,0,2,2" BorderThickness="1" BorderBrush="Black" Background="{StaticResource SilverPressedBrushKey}"> |
||||
<Canvas Name="TheCanvas"> |
||||
<Line X1="3" Y1="3" X2="7" Y2="7.5" Stroke="Black" StrokeThickness="1"/> |
||||
<Line X1="7" Y1="7.4" X2="11" Y2="3" Stroke="Black" StrokeThickness="1"/> |
||||
<Line X1="3" Y1="7.5" X2="7" Y2="12" Stroke="Black" StrokeThickness="1"/> |
||||
<Line X1="7" Y1="12" X2="11" Y2="7.5" Stroke="Black" StrokeThickness="1"/> |
||||
</Canvas> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="UIElement.IsMouseOver" Value="true"> |
||||
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangeBrushKey}"/> |
||||
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||
</Trigger> |
||||
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangePressedBrushKey}"/> |
||||
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||
</Trigger> |
||||
<Trigger Property="IsChecked" Value="True"> |
||||
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource FlipComment}"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
|
||||
<SolidColorBrush x:Key="MouseOverPinBrush" Color="Black" /> |
||||
|
||||
<ControlTemplate x:Key="PinTooltipButtonTemplate" TargetType="ToggleButton"> |
||||
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="2" BorderBrush="Transparent" BorderThickness="1" Background="Transparent"> |
||||
<Canvas RenderTransform="{StaticResource Rotate}" Name="TheCanvas"> |
||||
<Line X1="4" X2="10" Y1="2" Y2="2" Stroke="Silver" StrokeThickness="1" Name="Line1"/> |
||||
<Line X1="9" X2="9" Y1="2" Y2="8" Stroke="Silver" StrokeThickness="1" Name="Line2"/> |
||||
<Line X1="2" X2="12" Y1="8" Y2="8" Stroke="Silver" StrokeThickness="1" Name="Line3"/> |
||||
<Rectangle Fill="Silver" Width="2" Height="7" Canvas.Left="4" Canvas.Top="2" Name="Rectangle"/> |
||||
<Line X1="7" X2="7" Y1="9" Y2="12" Stroke="Silver" StrokeThickness="1" Name="Line4"/> |
||||
</Canvas> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotateUnpin}"/> |
||||
</Trigger> |
||||
<Trigger Property="ButtonBase.IsMouseOver" Value="True"> |
||||
<Setter TargetName="Line1" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||
<Setter TargetName="Line2" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||
<Setter TargetName="Line3" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||
<Setter TargetName="Line4" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||
<Setter TargetName="Rectangle" Property="Fill" Value="{StaticResource MouseOverPinBrush}"/> |
||||
</Trigger> |
||||
<Trigger Property="IsChecked" Value="True"> |
||||
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotateUnpin}"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
|
||||
<Style |
||||
TargetType="{x:Type TextBox}" |
||||
x:Key="TextStyle"> |
||||
<Setter |
||||
Property="OverridesDefaultStyle" |
||||
Value="True" /> |
||||
<Setter |
||||
Property="VerticalAlignment" |
||||
Value="Center" /> |
||||
<Setter |
||||
Property="FontFamily" Value="Khmer UI" /> |
||||
<Setter Property="FontSize" Value="12" /> |
||||
<Setter |
||||
Property="KeyboardNavigation.TabNavigation" |
||||
Value="None" /> |
||||
<Setter |
||||
Property="FocusVisualStyle" |
||||
Value="{x:Null}" /> |
||||
<Setter |
||||
Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate |
||||
TargetType="{x:Type TextBoxBase}"> |
||||
<Border |
||||
Name="Border" |
||||
Background="Transparent" |
||||
BorderBrush="Transparent" |
||||
BorderThickness="0"> |
||||
<ScrollViewer |
||||
Margin="0" |
||||
Name="PART_ContentHost" /> |
||||
</Border> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
<Style TargetType="TextBlock" x:Key="TextBlockStyle"> |
||||
<Setter Property="Margin" Value="4 0" /> |
||||
<Setter |
||||
Property="FontFamily" Value="Khmer UI" /> |
||||
<Setter Property="FontSize" Value="12" /> |
||||
</Style> |
||||
|
||||
<Style x:Key="PinThumbStyle" TargetType="Thumb"> |
||||
<Setter Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate TargetType="Thumb"> |
||||
<StackPanel x:Name="Container"/> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
<Style |
||||
x:Key="ExpandCollapseToggleStyle" |
||||
TargetType="{x:Type ToggleButton}"> |
||||
<Setter |
||||
Property="Focusable" |
||||
Value="False" /> |
||||
<Setter |
||||
Property="Width" |
||||
Value="19" /> |
||||
<Setter |
||||
Property="Height" |
||||
Value="13" /> |
||||
<Setter |
||||
Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate |
||||
TargetType="{x:Type ToggleButton}"> |
||||
<Border |
||||
Width="19" |
||||
Height="13" |
||||
Background="Transparent"> |
||||
<Border |
||||
Width="9" |
||||
Height="9" |
||||
BorderThickness="1" |
||||
BorderBrush="#FF7898B5" |
||||
CornerRadius="1" |
||||
SnapsToDevicePixels="true"> |
||||
<Border.Background> |
||||
<LinearGradientBrush |
||||
StartPoint="0,0" |
||||
EndPoint="1,1"> |
||||
<LinearGradientBrush.GradientStops> |
||||
<GradientStop |
||||
Color="White" |
||||
Offset=".2" /> |
||||
<GradientStop |
||||
Color="#FFC0B7A6" |
||||
Offset="1" /> |
||||
</LinearGradientBrush.GradientStops> |
||||
</LinearGradientBrush> |
||||
</Border.Background> |
||||
<Path |
||||
x:Name="ExpandPath" |
||||
Margin="1,1,1,1" |
||||
Fill="Black" |
||||
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z" /> |
||||
</Border> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger |
||||
Property="IsChecked" |
||||
Value="True"> |
||||
<Setter |
||||
Property="Data" |
||||
TargetName="ExpandPath" |
||||
Value="M 0 2 L 0 3 L 5 3 L 5 2 Z" /> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
<Style |
||||
x:Key="upDownBorderStyle" |
||||
TargetType="{x:Type Border}"> |
||||
<Setter |
||||
Property="BorderBrush" |
||||
Value="Gray" /> |
||||
<Setter |
||||
Property="HorizontalAlignment" |
||||
Value="Stretch" /> |
||||
<Setter |
||||
Property="Margin" |
||||
Value="0" /> |
||||
<Setter |
||||
Property="Padding" |
||||
Value="0" /> |
||||
<Setter |
||||
Property="Background" |
||||
Value="#FFECF7FC" /> |
||||
<Setter |
||||
Property="Height" |
||||
Value="14" /> |
||||
<Style.Triggers> |
||||
<DataTrigger |
||||
Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" |
||||
Value="False"> |
||||
<Setter |
||||
Property="Background" |
||||
Value="#FFE0E0E0"></Setter> |
||||
</DataTrigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
<Style |
||||
x:Key="upButtonStyle" |
||||
TargetType="{x:Type RepeatButton}"> |
||||
<Setter |
||||
Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate |
||||
TargetType="{x:Type RepeatButton}"> |
||||
<Border |
||||
Style="{StaticResource upDownBorderStyle}" |
||||
BorderThickness="1 1 1 0"> |
||||
<ContentPresenter |
||||
HorizontalAlignment="Center"></ContentPresenter> |
||||
</Border> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
<Style |
||||
x:Key="downButtonStyle" |
||||
TargetType="{x:Type RepeatButton}"> |
||||
<Setter |
||||
Property="Template"> |
||||
<Setter.Value> |
||||
<ControlTemplate |
||||
TargetType="{x:Type RepeatButton}"> |
||||
<Border |
||||
Style="{StaticResource upDownBorderStyle}" |
||||
BorderThickness="1 0 1 1"> |
||||
<ContentPresenter |
||||
HorizontalAlignment="Center"></ContentPresenter> |
||||
</Border> |
||||
</ControlTemplate> |
||||
</Setter.Value> |
||||
</Setter> |
||||
</Style> |
||||
|
||||
<ControlTemplate x:Key="RefreshButton" TargetType="Button"> |
||||
<Border |
||||
Name="ImageBorder" |
||||
CornerRadius="7" |
||||
BorderBrush="Transparent" |
||||
BorderThickness="1" |
||||
Height="14" |
||||
Width="14"> |
||||
<Image Width="9" Height="9" Margin="2 2" |
||||
x:Name="RefreshContentImage" |
||||
Tag="{Binding}" |
||||
Source="{core:GetBitmap Icons.16x16.Refresh}"/> |
||||
</Border> |
||||
<ControlTemplate.Triggers> |
||||
<Trigger Property="UIElement.IsMouseOver" Value="true"> |
||||
<Setter TargetName="ImageBorder" Property="Background" Value="{StaticResource SilverBrushKey}"/> |
||||
<Setter TargetName="ImageBorder" Property="BorderBrush" Value="Gray"/> |
||||
</Trigger> |
||||
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||
<Setter TargetName="ImageBorder" Property="Background" Value="{StaticResource SilverPressedBrushKey}"/> |
||||
<Setter TargetName="ImageBorder" Property="BorderBrush" Value="Gray"/> |
||||
</Trigger> |
||||
</ControlTemplate.Triggers> |
||||
</ControlTemplate> |
||||
</ResourceDictionary> |
@ -1,240 +0,0 @@
@@ -1,240 +0,0 @@
|
||||
<UserControl x:Class="Debugger.AddIn.Tooltips.PinDebuggerControl" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:local="clr-namespace:Debugger.AddIn.Tooltips" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
<UserControl.Resources> |
||||
<ResourceDictionary> |
||||
<ResourceDictionary.MergedDictionaries> |
||||
<ResourceDictionary |
||||
Source="PinControlsDictionary.xaml" /> |
||||
</ResourceDictionary.MergedDictionaries> |
||||
</ResourceDictionary> |
||||
</UserControl.Resources> |
||||
<Grid> |
||||
<Grid.Resources> |
||||
<LinearGradientBrush x:Key="DataGridBackground" |
||||
StartPoint="0,-0.03" |
||||
EndPoint="0,1"> |
||||
<GradientStop |
||||
Color="White" /> |
||||
<GradientStop |
||||
Color="#FFFAFCFE" |
||||
Offset="0.983" /> |
||||
<GradientStop |
||||
Color="#FFECF7FC" |
||||
Offset="0.07" /> |
||||
<GradientStop |
||||
Color="#FFEEF7FA" |
||||
Offset="0.436" /> |
||||
</LinearGradientBrush> |
||||
|
||||
<Style x:Key="CellStyle" |
||||
TargetType="{x:Type DataGridCell}"> |
||||
<Setter |
||||
Property="Focusable" |
||||
Value="false" /> |
||||
<!-- Focusable=true blocks shortcuts if cell is focused --> |
||||
<Setter |
||||
Property="BorderThickness" |
||||
Value="0" /> |
||||
<Setter Property="Width" Value="Auto" /> |
||||
<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> |
||||
|
||||
<Style x:Key="RowStyle" |
||||
TargetType="{x:Type DataGridRow}"> |
||||
<Setter |
||||
Property="Background" |
||||
Value="Transparent"></Setter> |
||||
</Style> |
||||
|
||||
<Style x:Key="DataGridStyle" TargetType="DataGrid"> |
||||
<Setter Property="VerticalScrollBarVisibility" Value="Disabled"/> |
||||
<Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/> |
||||
<Setter Property="GridLinesVisibility" Value="None"/> |
||||
<Setter Property="RowHeight" Value="18"/> |
||||
<Setter Property="MaxHeight" Value="202"/> |
||||
<Setter Property="MinHeight" Value="20" /> |
||||
<Setter Property="SelectionMode" Value="Single"/> |
||||
<Setter Property="SelectionUnit" Value="FullRow"/> |
||||
<Setter Property="AutoGenerateColumns" Value="False"/> |
||||
<Setter Property="CanUserAddRows" Value="False"/> |
||||
<Setter Property="HeadersVisibility" Value="None"/> |
||||
<Setter Property="BorderBrush" Value="Gray"/> |
||||
<Setter Property="Background" Value="{StaticResource DataGridBackground}"/> |
||||
<Setter Property="CellStyle" Value="{StaticResource CellStyle}"/> |
||||
<Setter Property="RowStyle" Value="{StaticResource RowStyle}"/> |
||||
<Style.Triggers> |
||||
<Trigger Property="IsMouseOver" Value="True"> |
||||
<Setter Property="Cursor" Value="Arrow"/> |
||||
</Trigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
</Grid.Resources> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto"/> |
||||
<ColumnDefinition Width="Auto"/> |
||||
</Grid.ColumnDefinitions> |
||||
<StackPanel VerticalAlignment="Center"> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto"/> |
||||
<ColumnDefinition Width="Auto"/> |
||||
<ColumnDefinition Width="Auto"/> |
||||
</Grid.ColumnDefinitions> |
||||
<DataGrid |
||||
Width="21" |
||||
BorderThickness="1,1,0,1" |
||||
Background="White" |
||||
x:Name="ExpandersGrid" |
||||
Style="{StaticResource DataGridStyle}" |
||||
ItemsSource="{Binding}"> |
||||
<DataGrid.Columns> |
||||
<DataGridTemplateColumn> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<Grid |
||||
Background="White"> |
||||
<StackPanel |
||||
VerticalAlignment="Center"> |
||||
<ToggleButton |
||||
x:Name="btnExpander" |
||||
Style="{StaticResource ExpandCollapseToggleStyle}" |
||||
Checked="BtnExpander_Checked" |
||||
Unchecked="BtnExpander_Unchecked" |
||||
Padding="0" |
||||
Margin="0" /> |
||||
</StackPanel> |
||||
</Grid> |
||||
<DataTemplate.Triggers> |
||||
<DataTrigger |
||||
Binding="{Binding Path=HasChildNodes}" |
||||
Value="False"> |
||||
<Setter |
||||
TargetName="btnExpander" |
||||
Property="Visibility" |
||||
Value="Collapsed" /> |
||||
</DataTrigger> |
||||
</DataTemplate.Triggers> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> |
||||
</DataGrid.Columns> |
||||
</DataGrid> |
||||
|
||||
<DataGrid |
||||
BorderThickness="0,1,0,1" |
||||
Grid.Column="1" |
||||
IsEnabled="False" |
||||
ColumnWidth="SizeToCells" |
||||
Style="{StaticResource DataGridStyle}" |
||||
ItemsSource="{Binding}" |
||||
Foreground="Black" |
||||
Name="dataGrid"> |
||||
<DataGrid.Columns> |
||||
<DataGridTemplateColumn> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<Image |
||||
Source="{Binding ImageSource}"></Image> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> |
||||
<DataGridTemplateColumn |
||||
MinWidth="20" |
||||
Header="Name"> |
||||
<!-- Name --> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<Border |
||||
BorderBrush="#FFDDDDDD" |
||||
BorderThickness="0 0 1 0"> |
||||
<TextBlock |
||||
Style="{StaticResource TextBlockStyle}" |
||||
Text="{Binding Path=FullName, Mode=OneWay}" |
||||
VerticalAlignment="Center"></TextBlock> |
||||
</Border> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> |
||||
<DataGridTemplateColumn IsReadOnly="True" |
||||
Width="SizeToCells" |
||||
Header="Text"> |
||||
<!-- Text (value) --> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<TextBox |
||||
Style="{StaticResource TextStyle}" |
||||
IsEnabled="false" |
||||
Text="{Binding Path=Text}" /> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> |
||||
</DataGrid.Columns> |
||||
</DataGrid> |
||||
|
||||
<DataGrid |
||||
MaxWidth="20" |
||||
BorderThickness="1" |
||||
Grid.Column="2" |
||||
x:Name="ImagesGrid" |
||||
Style="{StaticResource DataGridStyle}" |
||||
ItemsSource="{Binding}"> |
||||
<DataGrid.Columns> |
||||
<DataGridTemplateColumn> |
||||
<DataGridTemplateColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<Button Click="Button_Click" Template="{StaticResource RefreshButton}"/> |
||||
</DataTemplate> |
||||
</DataGridTemplateColumn.CellTemplate> |
||||
</DataGridTemplateColumn> |
||||
</DataGrid.Columns> |
||||
</DataGrid> |
||||
</Grid> |
||||
<!-- comment textbox --> |
||||
<Border |
||||
Name="BorderComment" |
||||
Background="White" |
||||
BorderThickness="1,0,1,1" |
||||
BorderBrush="Gray" |
||||
Height="0" |
||||
MaxHeight="50"> |
||||
<TextBox |
||||
FontFamily="Khmer UI" |
||||
BorderBrush="Gray" |
||||
BorderThickness="1" |
||||
FontSize="12" |
||||
Name="CommentTextBox" |
||||
TextChanged="CommentTextBox_TextChanged" |
||||
Margin="3"/> |
||||
</Border> |
||||
</StackPanel> |
||||
|
||||
<local:PinCloseControl |
||||
VerticalAlignment="Center" |
||||
Background="Transparent" |
||||
Grid.Column="1" |
||||
Margin="5,0,0,0" |
||||
x:Name="PinCloseControl"> |
||||
<local:PinCloseControl.Effect> |
||||
<DropShadowEffect |
||||
ShadowDepth="5" |
||||
Direction="330" |
||||
Color="Black" |
||||
Opacity="0.5"/> |
||||
</local:PinCloseControl.Effect> |
||||
</local:PinCloseControl> |
||||
</Grid> |
||||
</UserControl> |
@ -1,384 +0,0 @@
@@ -1,384 +0,0 @@
|
||||
// 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.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Controls.Primitives; |
||||
using System.Windows.Input; |
||||
using System.Windows.Media.Animation; |
||||
using System.Windows.Shapes; |
||||
|
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Bookmarks; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.Tooltips |
||||
{ |
||||
public partial class PinDebuggerControl : UserControl, IPinDebuggerControl |
||||
{ |
||||
private const double ChildPopupOpenXOffet = 16; |
||||
private const double ChildPopupOpenYOffet = 15; |
||||
private const int InitialItemsCount = 12; |
||||
private const double MINIMUM_OPACITY = .3d; |
||||
|
||||
private WindowsDebugger currentDebugger; |
||||
private DebuggerPopup childPopup; |
||||
private LazyItemsControl<ITreeNode> lazyExpandersGrid; |
||||
private LazyItemsControl<ITreeNode> lazyGrid; |
||||
private LazyItemsControl<ITreeNode> lazyImagesGrid; |
||||
private IEnumerable<ITreeNode> itemsSource; |
||||
|
||||
public PinDebuggerControl() |
||||
{ |
||||
InitializeComponent(); |
||||
|
||||
if (!DebuggerService.IsDebuggerStarted) |
||||
Opacity = MINIMUM_OPACITY; |
||||
this.PinCloseControl.Opacity = 0; |
||||
|
||||
Loaded += OnLoaded; |
||||
this.PinCloseControl.Closed += PinCloseControl_Closed; |
||||
this.PinCloseControl.ShowingComment += PinCloseControl_ShowingComment; |
||||
this.PinCloseControl.PinningChanged += PinCloseControl_PinningChanged; |
||||
|
||||
BookmarkManager.Removed += OnBookmarkRemoved; |
||||
|
||||
currentDebugger = (WindowsDebugger)DebuggerService.CurrentDebugger; |
||||
|
||||
currentDebugger.DebugStopped += OnDebugStopped; |
||||
currentDebugger.ProcessSelected += OnProcessSelected; |
||||
|
||||
if (currentDebugger.DebuggedProcess != null) |
||||
currentDebugger.DebuggedProcess.Paused += OnDebuggedProcessPaused; |
||||
} |
||||
|
||||
#region Properties
|
||||
|
||||
public PinBookmark Mark { get; set; } |
||||
|
||||
public IEnumerable<ITreeNode> ItemsSource |
||||
{ |
||||
get { return this.itemsSource; } |
||||
set { |
||||
itemsSource = value; |
||||
var items = new VirtualizingIEnumerable<ITreeNode>(value); |
||||
lazyExpandersGrid = new LazyItemsControl<ITreeNode>(this.ExpandersGrid, InitialItemsCount); |
||||
lazyExpandersGrid.ItemsSource = items; |
||||
|
||||
lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount); |
||||
lazyGrid.ItemsSource = items; |
||||
|
||||
lazyImagesGrid = new LazyItemsControl<ITreeNode>(this.ImagesGrid, InitialItemsCount); |
||||
lazyImagesGrid.ItemsSource = items; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Relative position of the pin with respect to the screen.
|
||||
/// </summary>
|
||||
public Point Location { get; set; } |
||||
|
||||
#endregion
|
||||
|
||||
#region Main operations
|
||||
|
||||
public void Open() |
||||
{ |
||||
Pin(); |
||||
} |
||||
|
||||
public void Close() |
||||
{ |
||||
CloseChildPopups(); |
||||
Unpin(); |
||||
|
||||
BookmarkManager.Removed -= OnBookmarkRemoved; |
||||
if (currentDebugger != null) { |
||||
currentDebugger.DebugStopped -= OnDebugStopped; |
||||
currentDebugger.ProcessSelected -= OnProcessSelected; |
||||
currentDebugger = null; |
||||
} |
||||
} |
||||
|
||||
void Pin() |
||||
{ |
||||
var provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider; |
||||
if(provider != null) { |
||||
var pinLayer = PinningBinding.GetPinlayer(provider.TextEditor); |
||||
if (pinLayer != null) |
||||
pinLayer.Pin(this); |
||||
} |
||||
} |
||||
|
||||
void Unpin() |
||||
{ |
||||
var provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider; |
||||
if(provider != null) { |
||||
var pinLayer = PinningBinding.GetPinlayer(provider.TextEditor); |
||||
if (pinLayer != null) |
||||
pinLayer.Unpin(this); |
||||
} |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Debugger events
|
||||
|
||||
void OnDebugStopped(object sender, EventArgs e) |
||||
{ |
||||
if (currentDebugger.DebuggedProcess != null) |
||||
currentDebugger.DebuggedProcess.Paused -= OnDebuggedProcessPaused; |
||||
} |
||||
|
||||
void OnProcessSelected(object sender, ProcessEventArgs e) |
||||
{ |
||||
Opacity = 1d; |
||||
if (currentDebugger.DebuggedProcess != null) |
||||
currentDebugger.DebuggedProcess.Paused += OnDebuggedProcessPaused; |
||||
} |
||||
|
||||
void OnDebuggedProcessPaused(object sender, ProcessEventArgs e) |
||||
{ |
||||
//var nodes = new StackFrameNode(e.Process.SelectedStackFrame).ChildNodes;
|
||||
|
||||
// if (!lazyGrid.ItemsSource.ContainsNode(node))
|
||||
// return;
|
||||
// TODO : find the current expression so we don't update every pin
|
||||
// var observable = new List<ITreeNode>();
|
||||
//
|
||||
// foreach (var node in lazyGrid.ItemsSource) {
|
||||
// var resultNode = currentDebugger.GetNode(node.FullName);
|
||||
// // HACK for updating the pins in tooltip
|
||||
// observable.Add(resultNode);
|
||||
// }
|
||||
//
|
||||
// // update UI
|
||||
// var newSource = new VirtualizingIEnumerable<ITreeNode>(observable);
|
||||
// lazyGrid.ItemsSource = newSource;
|
||||
// lazyExpandersGrid.ItemsSource = newSource;
|
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Expand button
|
||||
|
||||
private ToggleButton expandedButton; |
||||
|
||||
/// <summary>
|
||||
/// Closes the child popup of this control, if it exists.
|
||||
/// </summary>
|
||||
void CloseChildPopups() |
||||
{ |
||||
if (this.expandedButton != null) { |
||||
this.expandedButton = null; |
||||
// nice simple example of indirect recursion
|
||||
this.childPopup.CloseSelfAndChildren(); |
||||
} |
||||
} |
||||
|
||||
void BtnExpander_Checked(object sender, RoutedEventArgs e) |
||||
{ |
||||
if (!DebuggerService.IsDebuggerStarted) |
||||
return; |
||||
|
||||
var clickedButton = (ToggleButton)e.OriginalSource; |
||||
var clickedNode = (ITreeNode)clickedButton.DataContext; |
||||
// use device independent units, because child popup Left/Top are in independent units
|
||||
Point buttonPos = clickedButton.PointToScreen(new Point(0, 0)).TransformFromDevice(clickedButton); |
||||
|
||||
if (clickedButton.IsChecked.GetValueOrDefault(false)) { |
||||
|
||||
this.expandedButton = clickedButton; |
||||
|
||||
// open child Popup
|
||||
if (this.childPopup == null) { |
||||
this.childPopup = new DebuggerPopup(null, ICSharpCode.NRefactory.Location.Empty, false); |
||||
this.childPopup.PlacementTarget = this; |
||||
this.childPopup.Closed += new EventHandler(PinDebuggerControl_Closed); |
||||
this.childPopup.Placement = PlacementMode.Absolute; |
||||
} |
||||
|
||||
this.childPopup.IsLeaf = true; |
||||
this.childPopup.HorizontalOffset = buttonPos.X + ChildPopupOpenXOffet; |
||||
this.childPopup.VerticalOffset = buttonPos.Y + ChildPopupOpenYOffet; |
||||
if (clickedNode.ChildNodes != null) { |
||||
this.childPopup.ItemsSource = clickedNode.ChildNodes; |
||||
this.childPopup.Open(); |
||||
} |
||||
} else { |
||||
|
||||
} |
||||
} |
||||
|
||||
void PinDebuggerControl_Closed(object sender, EventArgs e) |
||||
{ |
||||
if (expandedButton != null && expandedButton.IsChecked.GetValueOrDefault(false)) |
||||
expandedButton.IsChecked = false; |
||||
} |
||||
|
||||
void BtnExpander_Unchecked(object sender, RoutedEventArgs e) |
||||
{ |
||||
CloseChildPopups(); |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region PinCloseControl
|
||||
|
||||
void PinCloseControl_Closed(object sender, EventArgs e) |
||||
{ |
||||
BookmarkManager.RemoveMark(Mark); |
||||
Close(); |
||||
} |
||||
|
||||
void PinCloseControl_PinningChanged(object sender, EventArgs e) |
||||
{ |
||||
if (this.PinCloseControl.IsChecked) { |
||||
BookmarkManager.RemoveMark(Mark); |
||||
} |
||||
else { |
||||
if(BookmarkManager.Bookmarks.Contains(Mark)) |
||||
BookmarkManager.RemoveMark(Mark); |
||||
|
||||
BookmarkManager.AddMark(Mark); |
||||
} |
||||
} |
||||
|
||||
void PinCloseControl_ShowingComment(object sender, ShowingCommentEventArgs e) |
||||
{ |
||||
ShowComment(e.ShowComment); |
||||
} |
||||
|
||||
void AnimateCloseControl(bool show) |
||||
{ |
||||
DoubleAnimation animation = new DoubleAnimation(); |
||||
animation.From = show ? 0 : 1; |
||||
animation.To = show ? 1 : 0; |
||||
animation.BeginTime = new TimeSpan(0, 0, show ? 0 : 1); |
||||
animation.Duration = new Duration(TimeSpan.FromMilliseconds(500)); |
||||
animation.SetValue(Storyboard.TargetProperty, this.PinCloseControl); |
||||
animation.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath(Rectangle.OpacityProperty)); |
||||
|
||||
Storyboard board = new Storyboard(); |
||||
board.Children.Add(animation); |
||||
|
||||
board.Begin(this); |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
void OnBookmarkRemoved(object sender, BookmarkEventArgs e) |
||||
{ |
||||
// if the bookmark was removed from pressing the button, return
|
||||
if (this.PinCloseControl.IsChecked) |
||||
return; |
||||
|
||||
if (e.Bookmark is PinBookmark) { |
||||
var pin = (PinBookmark)e.Bookmark; |
||||
if (pin.Location == Mark.Location && pin.FileName == Mark.FileName) { |
||||
Close(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e) |
||||
{ |
||||
this.CommentTextBox.Text = Mark.Comment; |
||||
} |
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e) |
||||
{ |
||||
if (!DebuggerService.IsDebuggerStarted) |
||||
return; |
||||
|
||||
// refresh content
|
||||
ITreeNode node = ((FrameworkElement)e.OriginalSource).DataContext as ITreeNode; |
||||
|
||||
var resultNode = currentDebugger.GetNode(node.FullName, node.ImageName); |
||||
if (resultNode == null) |
||||
return; |
||||
// HACK for updating the pins in tooltip
|
||||
var observable = new ObservableCollection<ITreeNode>(); |
||||
var source = lazyGrid.ItemsSource; |
||||
source.ForEach(item => { |
||||
if (item.CompareTo(node) == 0) |
||||
observable.Add(resultNode); |
||||
else |
||||
observable.Add(item); |
||||
}); |
||||
|
||||
Mark.Nodes = observable; |
||||
// update UI
|
||||
var newSource = new VirtualizingIEnumerable<ITreeNode>(observable); |
||||
lazyGrid.ItemsSource = newSource; |
||||
lazyExpandersGrid.ItemsSource = newSource; |
||||
} |
||||
|
||||
#region Comment
|
||||
|
||||
void ShowComment(bool show) |
||||
{ |
||||
if(show && BorderComment.Height != 0) |
||||
return; |
||||
if(!show && BorderComment.Height != 40) |
||||
return; |
||||
|
||||
DoubleAnimation animation = new DoubleAnimation(); |
||||
animation.From = show ? 0 : 40; |
||||
animation.To = show ? 40 : 0; |
||||
|
||||
animation.Duration = new Duration(TimeSpan.FromMilliseconds(300)); |
||||
animation.SetValue(Storyboard.TargetProperty, BorderComment); |
||||
animation.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath(Border.HeightProperty)); |
||||
|
||||
Storyboard board = new Storyboard(); |
||||
board.Children.Add(animation); |
||||
board.Begin(this); |
||||
} |
||||
|
||||
void CommentTextBox_TextChanged(object sender, TextChangedEventArgs e) |
||||
{ |
||||
Mark.Comment = this.CommentTextBox.Text; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides
|
||||
|
||||
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e) |
||||
{ |
||||
AnimateCloseControl(true); |
||||
Opacity = 1d; |
||||
Cursor = Cursors.Arrow; |
||||
base.OnMouseEnter(e); |
||||
} |
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e) |
||||
{ |
||||
Opacity = 1d; |
||||
Cursor = Cursors.Arrow; |
||||
base.OnMouseMove(e); |
||||
} |
||||
|
||||
protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) |
||||
{ |
||||
if (DebuggerService.IsDebuggerStarted) |
||||
Opacity = 1; |
||||
else |
||||
Opacity = MINIMUM_OPACITY; |
||||
|
||||
AnimateCloseControl(false); |
||||
|
||||
Cursor = Cursors.IBeam; |
||||
base.OnMouseLeave(e); |
||||
} |
||||
|
||||
#endregion
|
||||
} |
||||
} |
@ -1,184 +0,0 @@
@@ -1,184 +0,0 @@
|
||||
// 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.Controls.Primitives; |
||||
using System.Windows.Input; |
||||
using System.Windows.Media; |
||||
|
||||
using ICSharpCode.AvalonEdit.Editing; |
||||
using ICSharpCode.AvalonEdit.Rendering; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.SharpDevelop.Refactoring; |
||||
|
||||
namespace Debugger.AddIn.Tooltips |
||||
{ |
||||
/// <summary>
|
||||
/// Pin layer class. This class handles the pinning and unpinning operations.
|
||||
/// </summary>
|
||||
public class PinLayer : Canvas |
||||
{ |
||||
private double verticalOffset = 0; |
||||
private double horizontalOffset = 0; |
||||
|
||||
private TextView textView; |
||||
|
||||
/// <summary>
|
||||
/// PinLayer constructor.
|
||||
/// </summary>
|
||||
/// <param name="textArea">Text area for this layer.</param>
|
||||
public PinLayer(TextArea textArea) |
||||
{ |
||||
textView = textArea.TextView; |
||||
textView.VisualLinesChanged += textView_VisualLinesChanged; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Pins an element;
|
||||
/// </summary>
|
||||
/// <param name="element">Element to pin.</param>
|
||||
public void Pin(PinDebuggerControl element) |
||||
{ |
||||
if (element == null) |
||||
throw new NullReferenceException("Element is null!"); |
||||
|
||||
Thumb currentThumb = new Thumb(); |
||||
// check for saved position
|
||||
if (!element.Mark.PinPosition.HasValue) { |
||||
// this is satisfied when pinning the first time
|
||||
element.Mark.PinPosition = new Point { |
||||
X = element.Location.X + textView.HorizontalOffset, |
||||
Y = element.Location.Y + textView.VerticalOffset |
||||
}; |
||||
|
||||
Canvas.SetTop(currentThumb, element.Location.Y); |
||||
Canvas.SetLeft(currentThumb, element.Location.X); |
||||
} |
||||
else { |
||||
// this is satisfied when loading the pins - so we might have hidden pins
|
||||
element.Location = new Point { |
||||
X = element.Mark.PinPosition.Value.X - textView.HorizontalOffset, |
||||
Y = element.Mark.PinPosition.Value.Y - textView.VerticalOffset |
||||
}; |
||||
|
||||
Canvas.SetTop(currentThumb, element.Mark.PinPosition.Value.Y); |
||||
Canvas.SetLeft(currentThumb, element.Mark.PinPosition.Value.X); |
||||
} |
||||
|
||||
currentThumb.Style = element.TryFindResource("PinThumbStyle") as Style; |
||||
currentThumb.ApplyTemplate(); |
||||
currentThumb.DragDelta += onDragDelta; |
||||
currentThumb.DragStarted += currentThumb_DragStarted; |
||||
currentThumb.DragCompleted += currentThumb_DragCompleted; |
||||
|
||||
var container = TryFindChild<StackPanel>(currentThumb); |
||||
container.Children.Add(element); |
||||
this.Children.Add(currentThumb); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Unpins an element.
|
||||
/// </summary>
|
||||
/// <param name="element">Element to unpin.</param>
|
||||
public void Unpin(PinDebuggerControl element) |
||||
{ |
||||
if (element == null) |
||||
throw new NullReferenceException("Element is null!"); |
||||
|
||||
foreach (var thumb in this.Children) { |
||||
PinDebuggerControl pinControl = TryFindChild<PinDebuggerControl>((DependencyObject)thumb); |
||||
if (pinControl != null && pinControl == element) |
||||
{ |
||||
this.Children.Remove((UIElement)thumb); |
||||
element.Close(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void textView_VisualLinesChanged(object sender, EventArgs e) |
||||
{ |
||||
foreach (var ctrl in this.Children) { |
||||
var currentThumb = ctrl as Thumb; |
||||
PinDebuggerControl pinControl = TryFindChild<PinDebuggerControl>(currentThumb); |
||||
if (pinControl != null) |
||||
{ |
||||
// update relative location
|
||||
Point location = pinControl.Location; |
||||
location.X += horizontalOffset - textView.HorizontalOffset; |
||||
location.Y += verticalOffset - textView.VerticalOffset; |
||||
|
||||
Canvas.SetLeft(currentThumb, location.X); |
||||
Canvas.SetTop(currentThumb, location.Y); |
||||
|
||||
pinControl.Location = location; |
||||
pinControl.Mark.PinPosition = new Point { |
||||
X = location.X + textView.HorizontalOffset, |
||||
Y = location.Y + textView.VerticalOffset, |
||||
}; |
||||
} |
||||
} |
||||
|
||||
verticalOffset = textView.VerticalOffset; |
||||
horizontalOffset = textView.HorizontalOffset; |
||||
} |
||||
|
||||
#region Mouse move
|
||||
|
||||
void onDragDelta(object sender, DragDeltaEventArgs e) |
||||
{ |
||||
Thumb currnetThumb = (Thumb)sender; |
||||
currnetThumb.Cursor = Cursors.Arrow; |
||||
double left = Canvas.GetLeft(currnetThumb) + e.HorizontalChange; |
||||
double top = Canvas.GetTop(currnetThumb) + e.VerticalChange; |
||||
|
||||
Canvas.SetLeft(currnetThumb, left); |
||||
Canvas.SetTop(currnetThumb, top); |
||||
} |
||||
|
||||
void currentThumb_DragCompleted(object sender, DragCompletedEventArgs e) |
||||
{ |
||||
Thumb currnetThumb = (Thumb)sender; |
||||
currnetThumb.Cursor = Cursors.Arrow; |
||||
|
||||
var pinControl = TryFindChild<PinDebuggerControl>(currnetThumb); |
||||
if (pinControl != null) { |
||||
double left = Canvas.GetLeft(currnetThumb); |
||||
double top = Canvas.GetTop(currnetThumb); |
||||
pinControl.Opacity = 1d; |
||||
pinControl.Location = new Point { X = left, Y = top }; |
||||
|
||||
// pin's position is with respect to the layer.
|
||||
pinControl.Mark.PinPosition = |
||||
new Point |
||||
{ |
||||
X = textView.HorizontalOffset + left, |
||||
Y = textView.VerticalOffset + top |
||||
}; |
||||
} |
||||
} |
||||
|
||||
void currentThumb_DragStarted(object sender, DragStartedEventArgs e) |
||||
{ |
||||
Thumb currnetThumb = (Thumb)sender; |
||||
currnetThumb.Cursor = Cursors.Arrow; |
||||
|
||||
var pinControl = TryFindChild<PinDebuggerControl>(currnetThumb); |
||||
if (pinControl != null) |
||||
pinControl.Opacity = 1d; |
||||
} |
||||
|
||||
#endregion
|
||||
|
||||
#region Static helpers
|
||||
|
||||
static T TryFindChild<T>(DependencyObject root) where T : DependencyObject |
||||
{ |
||||
return WpfTreeNavigation.TryFindChild<T>(root); |
||||
} |
||||
|
||||
#endregion
|
||||
} |
||||
} |
@ -1,117 +0,0 @@
@@ -1,117 +0,0 @@
|
||||
// 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.ObjectModel; |
||||
using ICSharpCode.AvalonEdit; |
||||
using ICSharpCode.AvalonEdit.Rendering; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Bookmarks; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace Debugger.AddIn.Tooltips |
||||
{ |
||||
public class PinningBinding : DefaultLanguageBinding |
||||
{ |
||||
ITextEditor _editor; |
||||
PinLayer pinLayer; |
||||
|
||||
public PinningBinding() |
||||
{} |
||||
|
||||
public override void Attach(ITextEditor editor) |
||||
{ |
||||
if (editor == null) |
||||
return; |
||||
|
||||
var textEditor = editor.GetService(typeof(TextEditor)) as TextEditor; |
||||
if (textEditor != null) { |
||||
pinLayer = new PinLayer(textEditor.TextArea); |
||||
textEditor.TextArea.TextView.InsertLayer( |
||||
pinLayer, |
||||
KnownLayer.Caret, |
||||
LayerInsertionPosition.Above); |
||||
} |
||||
|
||||
_editor = editor; |
||||
CreatePins(_editor); |
||||
|
||||
base.Attach(editor); |
||||
} |
||||
|
||||
public override void Detach() |
||||
{ |
||||
ClosePins(_editor); |
||||
pinLayer = null; |
||||
base.Detach(); |
||||
} |
||||
|
||||
public void CreatePins(ITextEditor editor) |
||||
{ |
||||
// load pins
|
||||
var pins = BookmarkManager.Bookmarks.FindAll( |
||||
b => b is PinBookmark && b.FileName == editor.FileName); |
||||
|
||||
foreach (var bookmark in pins) { |
||||
var pin = (PinBookmark)bookmark; |
||||
pin.Popup = new PinDebuggerControl(); |
||||
pin.Popup.Mark = pin; |
||||
|
||||
var nodes = new ObservableCollection<ITreeNode>(); |
||||
foreach (var tuple in pin.SavedNodes) { |
||||
string imageName = !string.IsNullOrEmpty(tuple.Item1) ? tuple.Item1 : "Icons.16x16.Field"; |
||||
var node = new Debugger.AddIn.TreeModel.SavedTreeNode( |
||||
new ResourceServiceImage(imageName), |
||||
tuple.Item2, |
||||
tuple.Item3); |
||||
node.ImageName = imageName; |
||||
nodes.Add(node); |
||||
} |
||||
|
||||
pin.SavedNodes.Clear(); |
||||
pin.Popup.ItemsSource = nodes; |
||||
pin.Nodes = nodes; |
||||
|
||||
pinLayer.Pin((PinDebuggerControl)pin.Popup); |
||||
} |
||||
} |
||||
|
||||
public void ClosePins(ITextEditor editor) |
||||
{ |
||||
// save pins
|
||||
var pins = BookmarkManager.Bookmarks.FindAll( |
||||
b => b is PinBookmark && b.FileName == editor.FileName); |
||||
|
||||
foreach (var bookmark in pins) { |
||||
var pin = (PinBookmark)bookmark; |
||||
if (!pin.PinPosition.HasValue) |
||||
pin.PinPosition = pin.Popup.Location; |
||||
|
||||
// nodes
|
||||
if (pin.SavedNodes == null) |
||||
pin.SavedNodes = new System.Collections.Generic.List<Tuple<string, string, string>>(); |
||||
|
||||
foreach (var node in pin.Nodes) { |
||||
pin.SavedNodes.Add( |
||||
new Tuple<string, string, string>( |
||||
"Icons.16x16.Field", |
||||
node.FullName, |
||||
node.Text)); |
||||
} |
||||
|
||||
pinLayer.Unpin((PinDebuggerControl)pin.Popup); |
||||
pin.Popup = null; |
||||
} |
||||
} |
||||
|
||||
public static PinLayer GetPinlayer(ITextEditor editor) { |
||||
var textEditor = editor.GetService(typeof(TextEditor)) as TextEditor; |
||||
if (textEditor != null) { |
||||
return textEditor.TextArea.TextView.Layers[3] as PinLayer; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -1,53 +0,0 @@
@@ -1,53 +0,0 @@
|
||||
// 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; |
||||
|
||||
namespace Debugger.AddIn.Tooltips |
||||
{ |
||||
/// <summary>
|
||||
/// A wrapper around IEnumerable<T> with AddNextItems method for pulling additional items
|
||||
/// from underlying IEnumerable<T>.
|
||||
/// Can be used as source for <see cref="LazyItemsControl" />.
|
||||
/// </summary>
|
||||
public class VirtualizingIEnumerable<T> : ObservableCollection<T> |
||||
{ |
||||
private IEnumerator<T> originalSourceEnumerator; |
||||
|
||||
public VirtualizingIEnumerable(IEnumerable<T> originalSource) |
||||
{ |
||||
if (originalSource == null) |
||||
throw new ArgumentNullException("originalSource"); |
||||
|
||||
this.originalSourceEnumerator = originalSource.GetEnumerator(); |
||||
} |
||||
|
||||
private bool hasNext = true; |
||||
/// <summary>
|
||||
/// False if all items from underlying IEnumerable have already been added.
|
||||
/// </summary>
|
||||
public bool HasNext |
||||
{ |
||||
get |
||||
{ |
||||
return this.hasNext; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Requests next <paramref name="count"/> items from underlying IEnumerable source and adds them to the collection.
|
||||
/// </summary>
|
||||
public void AddNextItems(int count) |
||||
{ |
||||
for (int i = 0; i < count; i++) { |
||||
if (!originalSourceEnumerator.MoveNext()) { |
||||
this.hasNext = false; |
||||
break; |
||||
} |
||||
this.Add(originalSourceEnumerator.Current); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,125 +0,0 @@
@@ -1,125 +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.Generic; |
||||
using System.Text; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public partial class Utils |
||||
{ |
||||
public static IEnumerable<TreeNode> LazyGetChildNodesOfArray(TreeNode parent, Expression expression, ArrayDimensions dimensions) |
||||
{ |
||||
if (dimensions.TotalElementCount == 0) |
||||
return new TreeNode[] { new TreeNode(null, "(empty)", null, null, parent, _ => null) }; |
||||
|
||||
return new ArrayRangeNode(parent, expression, dimensions, dimensions).ChildNodes; |
||||
} |
||||
} |
||||
|
||||
/// <summary> This is a partent node for all elements within a given bounds </summary>
|
||||
public class ArrayRangeNode: TreeNode |
||||
{ |
||||
const int MaxElementCount = 100; |
||||
|
||||
Expression arrayTarget; |
||||
ArrayDimensions bounds; |
||||
ArrayDimensions originalBounds; |
||||
|
||||
public ArrayRangeNode(TreeNode parent, Expression arrayTarget, ArrayDimensions bounds, ArrayDimensions originalBounds) |
||||
: base(parent) |
||||
{ |
||||
this.arrayTarget = arrayTarget; |
||||
this.bounds = bounds; |
||||
this.originalBounds = originalBounds; |
||||
|
||||
this.Name = GetName(); |
||||
this.childNodes = LazyGetChildren(); |
||||
} |
||||
|
||||
public override IEnumerable<TreeNode> ChildNodes { |
||||
get { return base.ChildNodes; } |
||||
} |
||||
|
||||
string GetName() |
||||
{ |
||||
StringBuilder name = new StringBuilder(); |
||||
bool isFirst = true; |
||||
name.Append("["); |
||||
for(int i = 0; i < bounds.Count; i++) { |
||||
if (!isFirst) name.Append(", "); |
||||
isFirst = false; |
||||
ArrayDimension dim = bounds[i]; |
||||
ArrayDimension originalDim = originalBounds[i]; |
||||
|
||||
if (dim.Count == 0) { |
||||
throw new DebuggerException("Empty dimension"); |
||||
} else if (dim.Count == 1) { |
||||
name.Append(dim.LowerBound.ToString()); |
||||
} else if (dim.Equals(originalDim)) { |
||||
name.Append("*"); |
||||
} else { |
||||
name.Append(dim.LowerBound); |
||||
name.Append(".."); |
||||
name.Append(dim.UpperBound); |
||||
} |
||||
} |
||||
name.Append("]"); |
||||
return name.ToString(); |
||||
} |
||||
|
||||
static string GetName(int[] indices) |
||||
{ |
||||
StringBuilder sb = new StringBuilder(indices.Length * 4); |
||||
sb.Append("["); |
||||
bool isFirst = true; |
||||
foreach(int index in indices) { |
||||
if (!isFirst) sb.Append(", "); |
||||
sb.Append(index.ToString()); |
||||
isFirst = false; |
||||
} |
||||
sb.Append("]"); |
||||
return sb.ToString(); |
||||
} |
||||
|
||||
IEnumerable<TreeNode> LazyGetChildren() |
||||
{ |
||||
// The whole array is small - just add all elements as childs
|
||||
if (bounds.TotalElementCount <= MaxElementCount) { |
||||
foreach(int[] indices in bounds.Indices) { |
||||
string imageName; |
||||
var image = ExpressionNode.GetImageForArrayIndexer(out imageName); |
||||
var expression = new ExpressionNode(this, image, GetName(indices), arrayTarget.AppendIndexer(indices)); |
||||
expression.ImageName = imageName; |
||||
yield return expression; |
||||
} |
||||
yield break; |
||||
} |
||||
|
||||
// Find a dimension of size at least 2
|
||||
int splitDimensionIndex = bounds.Count - 1; |
||||
for(int i = 0; i < bounds.Count; i++) { |
||||
if (bounds[i].Count > 1) { |
||||
splitDimensionIndex = i; |
||||
break; |
||||
} |
||||
} |
||||
ArrayDimension splitDim = bounds[splitDimensionIndex]; |
||||
|
||||
// Split the dimension
|
||||
int elementsPerSegment = 1; |
||||
while (splitDim.Count > elementsPerSegment * MaxElementCount) { |
||||
elementsPerSegment *= MaxElementCount; |
||||
} |
||||
for(int i = splitDim.LowerBound; i <= splitDim.UpperBound; i += elementsPerSegment) { |
||||
List<ArrayDimension> newDims = new List<ArrayDimension>(bounds); |
||||
newDims[splitDimensionIndex] = new ArrayDimension(i, Math.Min(i + elementsPerSegment - 1, splitDim.UpperBound)); |
||||
yield return new ArrayRangeNode(this, arrayTarget, new ArrayDimensions(newDims), originalBounds); |
||||
} |
||||
yield break; |
||||
} |
||||
} |
||||
} |
@ -1,144 +0,0 @@
@@ -1,144 +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.Collections.Generic; |
||||
using System.Reflection; |
||||
|
||||
using Debugger.AddIn.Visualizers.Utils; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public partial class Utils |
||||
{ |
||||
public static IEnumerable<TreeNode> LazyGetChildNodesOfObject(TreeNode current, Expression targetObject, DebugType shownType) |
||||
{ |
||||
MemberInfo[] publicStatic = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); |
||||
MemberInfo[] publicInstance = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); |
||||
MemberInfo[] nonPublicStatic = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly); |
||||
MemberInfo[] nonPublicInstance = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); |
||||
|
||||
DebugType baseType = (DebugType)shownType.BaseType; |
||||
if (baseType != null) { |
||||
yield return new TreeNode( |
||||
DebuggerResourceService.GetImage("Icons.16x16.Class"), |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}"), |
||||
baseType.Name, |
||||
baseType.FullName, |
||||
current, |
||||
newNode => baseType.FullName == "System.Object" ? null : Utils.LazyGetChildNodesOfObject(newNode, targetObject, baseType) |
||||
); |
||||
} |
||||
|
||||
if (nonPublicInstance.Length > 0) { |
||||
yield return new TreeNode( |
||||
null, |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicMembers}"), |
||||
string.Empty, |
||||
string.Empty, |
||||
current, |
||||
newNode => Utils.LazyGetMembersOfObject(newNode, targetObject, nonPublicInstance) |
||||
); |
||||
} |
||||
|
||||
if (publicStatic.Length > 0 || nonPublicStatic.Length > 0) { |
||||
yield return new TreeNode( |
||||
null, |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.StaticMembers}"), |
||||
string.Empty, |
||||
string.Empty, |
||||
current, |
||||
p => { |
||||
var children = Utils.LazyGetMembersOfObject(p, targetObject, publicStatic); |
||||
if (nonPublicStatic.Length > 0) { |
||||
TreeNode nonPublicStaticNode = new TreeNode( |
||||
null, |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicStaticMembers}"), |
||||
string.Empty, |
||||
string.Empty, |
||||
p, |
||||
newNode => Utils.LazyGetMembersOfObject(newNode, targetObject, nonPublicStatic) |
||||
); |
||||
children = Utils.PrependNode(nonPublicStaticNode, children); |
||||
} |
||||
return children; |
||||
} |
||||
); |
||||
} |
||||
|
||||
DebugType iListType = (DebugType)shownType.GetInterface(typeof(IList).FullName); |
||||
if (iListType != null) { |
||||
yield return new IListNode(current, targetObject); |
||||
} else { |
||||
DebugType iEnumerableType, itemType; |
||||
if (shownType.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { |
||||
yield return new IEnumerableNode(current, targetObject, itemType); |
||||
} |
||||
} |
||||
|
||||
foreach(TreeNode node in LazyGetMembersOfObject(current, targetObject, publicInstance)) { |
||||
yield return node; |
||||
} |
||||
} |
||||
|
||||
public static IEnumerable<TreeNode> LazyGetMembersOfObject(TreeNode parent, Expression expression, MemberInfo[] members) |
||||
{ |
||||
List<TreeNode> nodes = new List<TreeNode>(); |
||||
foreach(MemberInfo memberInfo in members) { |
||||
string imageName; |
||||
var image = ExpressionNode.GetImageForMember((IDebugMemberInfo)memberInfo, out imageName); |
||||
var exp = new ExpressionNode(parent, image, memberInfo.Name, expression.AppendMemberReference((IDebugMemberInfo)memberInfo)); |
||||
exp.ImageName = imageName; |
||||
nodes.Add(exp); |
||||
} |
||||
nodes.Sort(); |
||||
return nodes; |
||||
} |
||||
|
||||
|
||||
public static IEnumerable<TreeNode> LazyGetItemsOfIList(TreeNode parent, Expression targetObject) |
||||
{ |
||||
// Add a cast, so that we are sure the expression has an indexer.
|
||||
// (The expression can be e.g. of type 'object' but its value is a List.
|
||||
// Without the cast, evaluating "expr[i]" would fail, because object does not have an indexer).
|
||||
targetObject = targetObject.CastToIList(); |
||||
int count = 0; |
||||
GetValueException error = null; |
||||
try { |
||||
count = targetObject.GetIListCount(); |
||||
} catch (GetValueException e) { |
||||
// Cannot yield a value in the body of a catch clause (CS1631)
|
||||
error = e; |
||||
} |
||||
if (error != null) { |
||||
yield return new TreeNode(null, "(error)", error.Message, null, null, _ => null); |
||||
} else if (count == 0) { |
||||
yield return new TreeNode(null, "(empty)", null, null, null, _ => null); |
||||
} else { |
||||
for(int i = 0; i < count; i++) { |
||||
string imageName; |
||||
var image = ExpressionNode.GetImageForArrayIndexer(out imageName); |
||||
var itemNode = new ExpressionNode(parent, image, "[" + i + "]", targetObject.AppendIndexer(i)); |
||||
itemNode.ImageName = imageName; |
||||
yield return itemNode; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static IEnumerable<TreeNode> PrependNode(TreeNode node, IEnumerable<TreeNode> rest) |
||||
{ |
||||
yield return node; |
||||
if (rest != null) { |
||||
foreach(TreeNode absNode in rest) { |
||||
yield return absNode; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,25 +0,0 @@
@@ -1,25 +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 ICSharpCode.SharpDevelop; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
/// <summary>
|
||||
/// Gets resources the way suitable for Debugger.AddIn.
|
||||
/// </summary>
|
||||
public static class DebuggerResourceService |
||||
{ |
||||
/// <summary>
|
||||
/// Gets image with given name from resources.
|
||||
/// </summary>
|
||||
/// <param name="resourceName">Resource name of the image.</param>
|
||||
public static IImage GetImage(string resourceName) |
||||
{ |
||||
return new ResourceServiceImage(resourceName); |
||||
} |
||||
} |
||||
} |
@ -1,462 +0,0 @@
@@ -1,462 +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.Generic; |
||||
using System.ComponentModel; |
||||
using System.Globalization; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Runtime.InteropServices; |
||||
using System.Text; |
||||
using System.Windows.Forms; |
||||
|
||||
using Debugger.AddIn.Visualizers; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
using TreeNode = Debugger.AddIn.TreeModel.TreeNode; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
/// <summary>
|
||||
/// Node in the tree which can be defined by a debugger expression.
|
||||
/// The expression will be lazily evaluated when needed.
|
||||
/// </summary>
|
||||
public class ExpressionNode: TreeNode, ISetText, INotifyPropertyChanged |
||||
{ |
||||
bool evaluated; |
||||
|
||||
Expression expression; |
||||
bool canSetText; |
||||
GetValueException error; |
||||
string fullText; |
||||
|
||||
public bool Evaluated { |
||||
get { return evaluated; } |
||||
set { evaluated = value; } |
||||
} |
||||
|
||||
public Expression Expression { |
||||
get { return expression; } |
||||
} |
||||
|
||||
public override bool CanSetText { |
||||
get { |
||||
if (!evaluated) EvaluateExpression(); |
||||
return canSetText; |
||||
} |
||||
} |
||||
|
||||
public GetValueException Error { |
||||
get { |
||||
if (!evaluated) EvaluateExpression(); |
||||
return error; |
||||
} |
||||
} |
||||
|
||||
public string FullText { |
||||
get { return fullText; } |
||||
} |
||||
|
||||
public override string Text { |
||||
get { |
||||
if (!evaluated) EvaluateExpression(); |
||||
return base.Text; |
||||
} |
||||
set { |
||||
if (value != base.Text) { |
||||
base.Text = value; |
||||
NotifyPropertyChanged("Text"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public override string FullName { |
||||
get { |
||||
return this.expression.PrettyPrint() ?? Name.Trim(); |
||||
} |
||||
} |
||||
|
||||
public override string Type { |
||||
get { |
||||
if (!evaluated) EvaluateExpression(); |
||||
return base.Type; |
||||
} |
||||
} |
||||
|
||||
public override IEnumerable<TreeNode> ChildNodes { |
||||
get { |
||||
if (!evaluated) EvaluateExpression(); |
||||
return base.ChildNodes; |
||||
} |
||||
} |
||||
|
||||
public override bool HasChildNodes { |
||||
get { |
||||
if (!evaluated) EvaluateExpression(); |
||||
return base.HasChildNodes; |
||||
} |
||||
} |
||||
|
||||
/// <summary> Used to determine available VisualizerCommands </summary>
|
||||
private DebugType expressionType; |
||||
/// <summary> Used to determine available VisualizerCommands </summary>
|
||||
private bool valueIsNull = true; |
||||
|
||||
private IEnumerable<IVisualizerCommand> visualizerCommands; |
||||
public override IEnumerable<IVisualizerCommand> VisualizerCommands { |
||||
get { |
||||
if (visualizerCommands == null) { |
||||
visualizerCommands = getAvailableVisualizerCommands(); |
||||
} |
||||
return visualizerCommands; |
||||
} |
||||
} |
||||
|
||||
private IEnumerable<IVisualizerCommand> getAvailableVisualizerCommands() |
||||
{ |
||||
if (!evaluated) EvaluateExpression(); |
||||
|
||||
if (this.expressionType == null) { |
||||
// no visualizers if EvaluateExpression failed
|
||||
yield break; |
||||
} |
||||
if (this.valueIsNull) { |
||||
// no visualizers if evaluated value is null
|
||||
yield break; |
||||
} |
||||
/*if (this.expressionType.IsPrimitive || this.expressionType.IsSystemDotObject() || this.expressionType.IsEnum()) { |
||||
// no visualizers for primitive types
|
||||
yield break; |
||||
}*/ |
||||
|
||||
foreach (var descriptor in VisualizerDescriptors.GetAllDescriptors()) { |
||||
if (descriptor.IsVisualizerAvailable(this.expressionType)) { |
||||
yield return descriptor.CreateVisualizerCommand(this.Expression); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public ExpressionNode(TreeNode parent, IImage image, string name, Expression expression) |
||||
: base(parent) |
||||
{ |
||||
this.IconImage = image; |
||||
this.Name = name; |
||||
this.expression = expression; |
||||
} |
||||
|
||||
void EvaluateExpression() |
||||
{ |
||||
evaluated = true; |
||||
|
||||
Value val; |
||||
try { |
||||
var process = WindowsDebugger.DebuggedProcess; |
||||
if (process == null) return; |
||||
StackFrame frame = process.GetCurrentExecutingFrame(); |
||||
if (frame == null) return; |
||||
var debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; |
||||
object data = debugger.debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken, |
||||
frame.MethodInfo.MetadataToken, |
||||
Name); |
||||
|
||||
if (expression is MemberReferenceExpression) { |
||||
var memberExpression = (MemberReferenceExpression)expression; |
||||
memberExpression.TargetObject.UserData = data; |
||||
} else { |
||||
expression.UserData = data; |
||||
} |
||||
// evaluate expression
|
||||
val = expression.Evaluate(process); |
||||
} catch (GetValueException e) { |
||||
error = e; |
||||
this.Text = e.Message; |
||||
return; |
||||
} |
||||
|
||||
this.canSetText = val.Type.IsPrimitive; |
||||
|
||||
this.expressionType = val.Type; |
||||
this.Type = val.Type.Name; |
||||
this.valueIsNull = val.IsNull; |
||||
|
||||
// Note that these return enumerators so they are lazy-evaluated
|
||||
if (val.IsNull) { |
||||
} else if (val.Type.IsPrimitive || val.Type.FullName == typeof(string).FullName) { // Must be before IsClass
|
||||
} else if (val.Type.IsArray) { // Must be before IsClass
|
||||
if (val.ArrayLength > 0) |
||||
this.childNodes = Utils.LazyGetChildNodesOfArray(this, this.Expression, val.ArrayDimensions); |
||||
} else if (val.Type.IsClass || val.Type.IsValueType) { |
||||
if (val.Type.FullNameWithoutGenericArguments == typeof(List<>).FullName) { |
||||
if ((int)val.GetMemberValue("_size").PrimitiveValue > 0) |
||||
this.childNodes = Utils.LazyGetItemsOfIList(this, this.expression); |
||||
} else { |
||||
this.childNodes = Utils.LazyGetChildNodesOfObject(this, this.Expression, val.Type); |
||||
} |
||||
} else if (val.Type.IsPointer) { |
||||
Value deRef = val.Dereference(); |
||||
if (deRef != null) { |
||||
this.childNodes = new ExpressionNode [] { new ExpressionNode(this, this.IconImage, "*" + this.Name, this.Expression.AppendDereference()) }; |
||||
} |
||||
} |
||||
|
||||
if (DebuggingOptions.Instance.ICorDebugVisualizerEnabled) { |
||||
TreeNode info = ICorDebug.GetDebugInfoRoot(val.AppDomain, val.CorValue); |
||||
this.childNodes = Utils.PrependNode(info, this.ChildNodes); |
||||
} |
||||
|
||||
// Do last since it may expire the object
|
||||
if (val.Type.IsInteger) { |
||||
fullText = FormatInteger(val.PrimitiveValue); |
||||
} else if (val.Type.IsPointer) { |
||||
fullText = String.Format("0x{0:X}", val.PointerAddress); |
||||
} else if ((val.Type.FullName == typeof(string).FullName || |
||||
val.Type.FullName == typeof(char).FullName) && !val.IsNull) { |
||||
try { |
||||
fullText = '"' + Escape(val.InvokeToString()) + '"'; |
||||
} catch (GetValueException e) { |
||||
error = e; |
||||
fullText = e.Message; |
||||
return; |
||||
} |
||||
} else if ((val.Type.IsClass || val.Type.IsValueType) && !val.IsNull) { |
||||
try { |
||||
fullText = val.InvokeToString(); |
||||
} catch (GetValueException e) { |
||||
error = e; |
||||
fullText = e.Message; |
||||
return; |
||||
} |
||||
} else { |
||||
fullText = val.AsString(); |
||||
} |
||||
|
||||
this.Text = (fullText.Length > 256) ? fullText.Substring(0, 256) + "..." : fullText; |
||||
} |
||||
|
||||
string Escape(string source) |
||||
{ |
||||
return source.Replace("\n", "\\n") |
||||
.Replace("\t", "\\t") |
||||
.Replace("\r", "\\r") |
||||
.Replace("\0", "\\0") |
||||
.Replace("\b", "\\b") |
||||
.Replace("\a", "\\a") |
||||
.Replace("\f", "\\f") |
||||
.Replace("\v", "\\v") |
||||
.Replace("\"", "\\\""); |
||||
} |
||||
|
||||
string FormatInteger(object i) |
||||
{ |
||||
if (DebuggingOptions.Instance.ShowIntegersAs == ShowIntegersAs.Decimal) |
||||
return i.ToString(); |
||||
|
||||
string hex = null; |
||||
for(int len = 1;; len *= 2) { |
||||
hex = string.Format("{0:X" + len + "}", i); |
||||
if (hex.Length == len) |
||||
break; |
||||
} |
||||
|
||||
if (DebuggingOptions.Instance.ShowIntegersAs == ShowIntegersAs.Hexadecimal) { |
||||
return "0x" + hex; |
||||
} else { |
||||
if (ShowAsHex(i)) { |
||||
return String.Format("{0} (0x{1})", i, hex); |
||||
} else { |
||||
return i.ToString(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
bool ShowAsHex(object i) |
||||
{ |
||||
ulong val; |
||||
if (i is sbyte || i is short || i is int || i is long) { |
||||
unchecked { val = (ulong)Convert.ToInt64(i); } |
||||
if (val > (ulong)long.MaxValue) |
||||
val = ~val + 1; |
||||
} else { |
||||
val = Convert.ToUInt64(i); |
||||
} |
||||
if (val >= 0x10000) |
||||
return true; |
||||
|
||||
int ones = 0; // How many 1s there is
|
||||
int runs = 0; // How many runs of 1s there is
|
||||
int size = 0; // Size of the integer in bits
|
||||
while(val != 0) { // There is at least one 1
|
||||
while((val & 1) == 0) { // Skip 0s
|
||||
val = val >> 1; |
||||
size++; |
||||
} |
||||
while((val & 1) == 1) { // Skip 1s
|
||||
val = val >> 1; |
||||
size++; |
||||
ones++; |
||||
} |
||||
runs++; |
||||
} |
||||
|
||||
return size >= 7 && runs <= (size + 7) / 8; |
||||
} |
||||
|
||||
public override bool SetText(string newText) |
||||
{ |
||||
string fullName = FullName; |
||||
|
||||
Value val = null; |
||||
try { |
||||
val = this.Expression.Evaluate(WindowsDebugger.DebuggedProcess); |
||||
if (val.Type.IsInteger && newText.StartsWith("0x")) { |
||||
try { |
||||
val.PrimitiveValue = long.Parse(newText.Substring(2), NumberStyles.HexNumber); |
||||
} catch (FormatException) { |
||||
throw new NotSupportedException(); |
||||
} catch (OverflowException) { |
||||
throw new NotSupportedException(); |
||||
} |
||||
} else { |
||||
val.PrimitiveValue = newText; |
||||
} |
||||
this.Text = newText; |
||||
return true; |
||||
} catch (NotSupportedException) { |
||||
string format = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CannotSetValue.BadFormat"); |
||||
string msg = string.Format(format, newText, val.Type.PrimitiveType); |
||||
MessageService.ShowMessage(msg ,"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}"); |
||||
} catch (COMException) { |
||||
// COMException (0x80131330): Cannot perfrom SetValue on non-leaf frames.
|
||||
// Happens if trying to set value after exception is breaked
|
||||
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.UnknownError}", |
||||
"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}"); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public static IImage GetImageForThis(out string imageName) |
||||
{ |
||||
imageName = "Icons.16x16.Parameter"; |
||||
return DebuggerResourceService.GetImage(imageName); |
||||
} |
||||
|
||||
public static IImage GetImageForParameter(out string imageName) |
||||
{ |
||||
imageName = "Icons.16x16.Parameter"; |
||||
return DebuggerResourceService.GetImage(imageName); |
||||
} |
||||
|
||||
public static IImage GetImageForLocalVariable(out string imageName) |
||||
{ |
||||
imageName = "Icons.16x16.Local"; |
||||
return DebuggerResourceService.GetImage(imageName); |
||||
} |
||||
|
||||
public static IImage GetImageForArrayIndexer(out string imageName) |
||||
{ |
||||
imageName = "Icons.16x16.Field"; |
||||
return DebuggerResourceService.GetImage(imageName); |
||||
} |
||||
|
||||
public static IImage GetImageForMember(IDebugMemberInfo memberInfo, out string imageName) |
||||
{ |
||||
string name = string.Empty; |
||||
if (memberInfo.IsPublic) { |
||||
} else if (memberInfo.IsAssembly) { |
||||
name += "Internal"; |
||||
} else if (memberInfo.IsFamily) { |
||||
name += "Protected"; |
||||
} else if (memberInfo.IsPrivate) { |
||||
name += "Private"; |
||||
} |
||||
if (memberInfo is FieldInfo) { |
||||
name += "Field"; |
||||
} else if (memberInfo is PropertyInfo) { |
||||
name += "Property"; |
||||
} else if (memberInfo is MethodInfo) { |
||||
name += "Method"; |
||||
} else { |
||||
throw new DebuggerException("Unknown member type " + memberInfo.GetType().FullName); |
||||
} |
||||
|
||||
imageName = "Icons.16x16." + name; |
||||
return DebuggerResourceService.GetImage(imageName); |
||||
} |
||||
|
||||
// public ContextMenuStrip GetContextMenu()
|
||||
// {
|
||||
// if (this.Error != null) return GetErrorContextMenu();
|
||||
//
|
||||
// ContextMenuStrip menu = new ContextMenuStrip();
|
||||
//
|
||||
// ToolStripMenuItem copyItem;
|
||||
// copyItem = new ToolStripMenuItem();
|
||||
// copyItem.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CopyToClipboard");
|
||||
// copyItem.Checked = false;
|
||||
// copyItem.Click += delegate {
|
||||
// ClipboardWrapper.SetText(fullText);
|
||||
// };
|
||||
|
||||
// ToolStripMenuItem hexView;
|
||||
// hexView = new ToolStripMenuItem();
|
||||
// hexView.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.ShowInHexadecimal");
|
||||
// hexView.Checked = DebuggingOptions.Instance.ShowValuesInHexadecimal;
|
||||
// hexView.Click += delegate {
|
||||
// // refresh all pads that use ValueNode for display
|
||||
// DebuggingOptions.Instance.ShowValuesInHexadecimal = !DebuggingOptions.Instance.ShowValuesInHexadecimal;
|
||||
// // always check if instance is null, might be null if pad is not opened
|
||||
// if (LocalVarPad.Instance != null)
|
||||
// LocalVarPad.Instance.RefreshPad();
|
||||
// if (WatchPad.Instance != null)
|
||||
// WatchPad.Instance.RefreshPad();
|
||||
// };
|
||||
|
||||
// menu.Items.AddRange(new ToolStripItem[] {
|
||||
// copyItem,
|
||||
// //hexView
|
||||
// });
|
||||
//
|
||||
// return menu;
|
||||
// }
|
||||
|
||||
public ContextMenuStrip GetErrorContextMenu() |
||||
{ |
||||
ContextMenuStrip menu = new ContextMenuStrip(); |
||||
|
||||
ToolStripMenuItem showError; |
||||
showError = new ToolStripMenuItem(); |
||||
showError.Text = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.ShowFullError}"); |
||||
showError.Checked = false; |
||||
showError.Click += delegate { |
||||
MessageService.ShowException(error, null); |
||||
}; |
||||
|
||||
menu.Items.AddRange(new ToolStripItem[] { |
||||
showError |
||||
}); |
||||
|
||||
return menu; |
||||
} |
||||
|
||||
public static WindowsDebugger WindowsDebugger { |
||||
get { |
||||
return (WindowsDebugger)DebuggerService.CurrentDebugger; |
||||
} |
||||
} |
||||
|
||||
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
private void NotifyPropertyChanged(string info) |
||||
{ |
||||
if (PropertyChanged != null) |
||||
{ |
||||
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(info)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,12 +0,0 @@
@@ -1,12 +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.Windows.Forms; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public interface IContextMenu |
||||
{ |
||||
ContextMenuStrip GetContextMenu(); |
||||
} |
||||
} |
@ -1,158 +0,0 @@
@@ -1,158 +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 Debugger.Interop.CorDebug; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public class ICorDebug |
||||
{ |
||||
public class InfoNode: TreeNode |
||||
{ |
||||
List<TreeNode> children; |
||||
|
||||
public InfoNode(TreeNode parent, string name, string text) |
||||
: this(parent, name, text, _ => null) |
||||
{ |
||||
|
||||
} |
||||
|
||||
public InfoNode(TreeNode parent, string name, string text, Func<TreeNode, List<TreeNode>> children) |
||||
: base(parent) |
||||
{ |
||||
this.Name = name; |
||||
this.Text = text; |
||||
this.children = children(this); |
||||
} |
||||
|
||||
public override IEnumerable<TreeNode> ChildNodes { |
||||
get { return children; } |
||||
} |
||||
|
||||
public void AddChild(string name, string text) |
||||
{ |
||||
if (children == null) { |
||||
children = new List<TreeNode>(); |
||||
} |
||||
children.Add(new InfoNode(this, name, text)); |
||||
} |
||||
|
||||
public void AddChild(string name, string text, Func<TreeNode, List<TreeNode>> subChildren) |
||||
{ |
||||
if (children == null) { |
||||
children = new List<TreeNode>(); |
||||
} |
||||
children.Add(new InfoNode(this, name, text, p => subChildren(p))); |
||||
} |
||||
} |
||||
|
||||
public static InfoNode GetDebugInfoRoot(AppDomain appDomain, ICorDebugValue corValue) |
||||
{ |
||||
return new InfoNode(null, "ICorDebug", "", p => GetDebugInfo(p, appDomain, corValue)); |
||||
} |
||||
|
||||
public static List<TreeNode> GetDebugInfo(TreeNode parent, AppDomain appDomain, ICorDebugValue corValue) |
||||
{ |
||||
List<TreeNode> items = new List<TreeNode>(); |
||||
|
||||
if (corValue is ICorDebugValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugValue", ""); |
||||
info.AddChild("Address", corValue.GetAddress().ToString("X8")); |
||||
info.AddChild("Type", ((CorElementType)corValue.GetTheType()).ToString()); |
||||
info.AddChild("Size", corValue.GetSize().ToString()); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugValue2) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugValue2", ""); |
||||
ICorDebugValue2 corValue2 = (ICorDebugValue2)corValue; |
||||
string fullname; |
||||
try { |
||||
fullname = DebugType.CreateFromCorType(appDomain, corValue2.GetExactType()).FullName; |
||||
} catch (DebuggerException e) { |
||||
fullname = e.Message; |
||||
} |
||||
info.AddChild("ExactType", fullname); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugGenericValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugGenericValue", ""); |
||||
try { |
||||
byte[] bytes = ((ICorDebugGenericValue)corValue).GetRawValue(); |
||||
for(int i = 0; i < bytes.Length; i += 8) { |
||||
string val = ""; |
||||
for(int j = i; j < bytes.Length && j < i + 8; j++) { |
||||
val += bytes[j].ToString("X2") + " "; |
||||
} |
||||
info.AddChild("Value" + i.ToString("X2"), val); |
||||
} |
||||
} catch (ArgumentException) { |
||||
info.AddChild("Value", "N/A"); |
||||
} |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugReferenceValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugReferenceValue", ""); |
||||
ICorDebugReferenceValue refValue = (ICorDebugReferenceValue)corValue; |
||||
info.AddChild("IsNull", (refValue.IsNull() != 0).ToString()); |
||||
if (refValue.IsNull() == 0) { |
||||
info.AddChild("Value", refValue.GetValue().ToString("X8")); |
||||
if (refValue.Dereference() != null) { |
||||
info.AddChild("Dereference", "", p => GetDebugInfo(p, appDomain, refValue.Dereference())); |
||||
} else { |
||||
info.AddChild("Dereference", "N/A"); |
||||
} |
||||
} |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugHeapValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugHeapValue", ""); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugHeapValue2) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugHeapValue2", ""); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugObjectValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugObjectValue", ""); |
||||
ICorDebugObjectValue objValue = (ICorDebugObjectValue)corValue; |
||||
info.AddChild("Class", objValue.GetClass().GetToken().ToString("X8")); |
||||
info.AddChild("IsValueClass", (objValue.IsValueClass() != 0).ToString()); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugObjectValue2) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugObjectValue2", ""); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugBoxValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugBoxValue", ""); |
||||
ICorDebugBoxValue boxValue = (ICorDebugBoxValue)corValue; |
||||
info.AddChild("Object", "", p => GetDebugInfo(p, appDomain, boxValue.GetObject())); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugStringValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugStringValue", ""); |
||||
ICorDebugStringValue stringValue = (ICorDebugStringValue)corValue; |
||||
info.AddChild("Length", stringValue.GetLength().ToString()); |
||||
info.AddChild("String", stringValue.GetString()); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugArrayValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugArrayValue", ""); |
||||
info.AddChild("...", "..."); |
||||
items.Add(info); |
||||
} |
||||
if (corValue is ICorDebugHandleValue) { |
||||
InfoNode info = new InfoNode(parent, "ICorDebugHandleValue", ""); |
||||
ICorDebugHandleValue handleValue = (ICorDebugHandleValue)corValue; |
||||
info.AddChild("HandleType", handleValue.GetHandleType().ToString()); |
||||
items.Add(info); |
||||
} |
||||
|
||||
return items; |
||||
} |
||||
} |
||||
} |
@ -1,32 +0,0 @@
@@ -1,32 +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 Debugger.AddIn.Visualizers.Utils; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
/// <summary>
|
||||
/// IEnumerable node in the variable tree.
|
||||
/// </summary>
|
||||
public class IEnumerableNode : TreeNode |
||||
{ |
||||
Expression targetObject; |
||||
Expression debugListExpression; |
||||
|
||||
public IEnumerableNode(TreeNode parent, Expression targetObject, DebugType itemType) |
||||
: base(parent) |
||||
{ |
||||
this.targetObject = targetObject; |
||||
|
||||
this.Name = "IEnumerable"; |
||||
this.Text = "Expanding will enumerate the IEnumerable"; |
||||
DebugType debugListType; |
||||
this.debugListExpression = DebuggerHelpers.CreateDebugListExpression(targetObject, itemType, out debugListType); |
||||
this.childNodes = Utils.LazyGetItemsOfIList(this, this.debugListExpression); |
||||
} |
||||
} |
||||
} |
@ -1,33 +0,0 @@
@@ -1,33 +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 Debugger.AddIn.Visualizers.Utils; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using System.Collections; |
||||
using System.Collections.Generic; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public class IListNode : TreeNode |
||||
{ |
||||
Expression targetList; |
||||
int listCount; |
||||
|
||||
public IListNode(TreeNode parent, Expression targetListObject) |
||||
: base(parent) |
||||
{ |
||||
this.targetList = targetListObject; |
||||
|
||||
this.Name = "IList"; |
||||
this.listCount = this.targetList.GetIListCount(); |
||||
this.childNodes = Utils.LazyGetItemsOfIList(this, this.targetList); |
||||
} |
||||
|
||||
public override bool HasChildNodes { |
||||
get { return this.listCount > 0; } |
||||
} |
||||
} |
||||
} |
@ -1,12 +0,0 @@
@@ -1,12 +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)
|
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public interface ISetText |
||||
{ |
||||
bool CanSetText { get; } |
||||
|
||||
bool SetText(string text); |
||||
} |
||||
} |
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
// 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 ICSharpCode.SharpDevelop; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
/// <summary>
|
||||
/// Description of SavedTreeNode.
|
||||
/// </summary>
|
||||
public class SavedTreeNode : TreeNode |
||||
{ |
||||
public override bool CanSetText { |
||||
get { return true; } |
||||
} |
||||
|
||||
public SavedTreeNode(IImage image, string fullname, string text) |
||||
: base(null) |
||||
{ |
||||
base.IconImage = image; |
||||
FullName = fullname; |
||||
Text = text; |
||||
} |
||||
|
||||
public override bool SetText(string newValue) { |
||||
Text = newValue; |
||||
return false; |
||||
} |
||||
} |
||||
} |
@ -1,67 +0,0 @@
@@ -1,67 +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.Generic; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.NRefactory.Visitors; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public class StackFrameNode: TreeNode |
||||
{ |
||||
StackFrame stackFrame; |
||||
|
||||
public StackFrame StackFrame { |
||||
get { return stackFrame; } |
||||
} |
||||
|
||||
public StackFrameNode(StackFrame stackFrame) |
||||
: base(null) |
||||
{ |
||||
this.stackFrame = stackFrame; |
||||
|
||||
this.Name = stackFrame.MethodInfo.Name; |
||||
this.childNodes = LazyGetChildNodes(); |
||||
} |
||||
|
||||
IEnumerable<TreeNode> LazyGetChildNodes() |
||||
{ |
||||
foreach(DebugParameterInfo par in stackFrame.MethodInfo.GetParameters()) { |
||||
string imageName; |
||||
var image = ExpressionNode.GetImageForParameter(out imageName); |
||||
var expression = new ExpressionNode(this, image, par.Name, par.GetExpression()); |
||||
expression.ImageName = imageName; |
||||
yield return expression; |
||||
} |
||||
if (this.stackFrame.HasSymbols) { |
||||
foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(this.StackFrame.IP)) { |
||||
string imageName; |
||||
var image = ExpressionNode.GetImageForLocalVariable(out imageName); |
||||
var expression = new ExpressionNode(this, image, locVar.Name, locVar.GetExpression()); |
||||
expression.ImageName = imageName; |
||||
yield return expression; |
||||
} |
||||
} else { |
||||
WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; |
||||
if (debugger.debuggerDecompilerService != null) { |
||||
int typeToken = this.stackFrame.MethodInfo.DeclaringType.MetadataToken; |
||||
int methodToken = this.stackFrame.MethodInfo.MetadataToken; |
||||
foreach (var localVar in debugger.debuggerDecompilerService.GetLocalVariables(typeToken, methodToken)) { |
||||
string imageName; |
||||
var image = ExpressionNode.GetImageForLocalVariable(out imageName); |
||||
var expression = new ExpressionNode(this, image, localVar, ExpressionEvaluator.ParseExpression(localVar, SupportedLanguage.CSharp)); |
||||
expression.ImageName = imageName; |
||||
yield return expression; |
||||
} |
||||
} |
||||
} |
||||
if (stackFrame.Thread.CurrentException != null) { |
||||
yield return new ExpressionNode(this, null, "__exception", new IdentifierExpression("__exception")); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,478 @@
@@ -0,0 +1,478 @@
|
||||
// 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; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using System.Diagnostics; |
||||
using System.Globalization; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Runtime.InteropServices; |
||||
using System.Text; |
||||
using System.Windows.Forms; |
||||
using Debugger.AddIn.Visualizers; |
||||
using Debugger.AddIn.Visualizers.Utils; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Gui.Pads; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
/// <summary>
|
||||
/// Tree node which represents debuggee's <see cref="Value"/>.
|
||||
/// The node stores a lambda which can be used to reobtain the value
|
||||
/// at any time (possibly even after some stepping).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The general rule is that getting a value or getting children will
|
||||
/// either succeed or result in <see cref="GetValueException"/>.
|
||||
/// </remarks>
|
||||
public class ValueNode: TreeNode |
||||
{ |
||||
Func<Value> getValue; |
||||
Action<Value> setValue; |
||||
|
||||
Value cachedValue; |
||||
Debugger.Process cachedValueProcess; |
||||
long cachedValueDebuggeeState; |
||||
|
||||
string fullValue; |
||||
GetValueException error; |
||||
|
||||
public string FullText { |
||||
get { return this.Value; } |
||||
} |
||||
|
||||
public ValueNode(string imageName, string name, Func<Value> getValue, Action<Value> setValue = null) |
||||
: base(imageName, name, string.Empty, string.Empty, null) |
||||
{ |
||||
if (getValue == null) |
||||
throw new ArgumentNullException("getValue"); |
||||
|
||||
this.getValue = getValue; |
||||
this.setValue = setValue; |
||||
|
||||
GetValueAndUpdateUI(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Get the value of the node and cache it as long-lived reference.
|
||||
/// We assume that the user will need this value a lot.
|
||||
/// </summary>
|
||||
public Value GetValue() |
||||
{ |
||||
// The value still survives across debuggee state, but we want a fresh one for the UI
|
||||
if (cachedValue == null || cachedValueProcess.DebuggeeState != cachedValueDebuggeeState) |
||||
{ |
||||
Stopwatch watch = new Stopwatch(); |
||||
watch.Start(); |
||||
cachedValue = this.getValue().GetPermanentReference(WindowsDebugger.EvalThread); |
||||
cachedValueProcess = cachedValue.Process; |
||||
cachedValueDebuggeeState = cachedValue.Process.DebuggeeState; |
||||
LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms (result cached for future use)", this.Name, watch.ElapsedMilliseconds); |
||||
} |
||||
return cachedValue; |
||||
} |
||||
|
||||
public void SetValue(Value value) |
||||
{ |
||||
if (setValue == null) |
||||
throw new DebuggerException("Setting of value is not supported for this node"); |
||||
|
||||
try |
||||
{ |
||||
this.setValue(value); |
||||
} |
||||
catch(GetValueException e) |
||||
{ |
||||
MessageService.ShowMessage(e.Message, "${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}"); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Get the value of the node and update the UI text fields.
|
||||
/// </summary>
|
||||
void GetValueAndUpdateUI() |
||||
{ |
||||
try { |
||||
Stopwatch watch = new Stopwatch(); |
||||
watch.Start(); |
||||
|
||||
// Do not keep permanent reference
|
||||
Value val = this.getValue(); |
||||
|
||||
// Note that the child collections are lazy-evaluated
|
||||
if (val.IsNull) { |
||||
this.GetChildren = null; |
||||
} else if (val.Type.IsPrimitive || val.Type.FullName == typeof(string).FullName) { // Must be before IsClass
|
||||
this.GetChildren = null; |
||||
} else if (val.Type.IsArray) { // Must be before IsClass
|
||||
var dims = val.ArrayDimensions; // Eval now
|
||||
if (dims.TotalElementCount > 0) { |
||||
this.GetChildren = () => GetArrayChildren(dims, dims); |
||||
} |
||||
} else if (val.Type.IsClass || val.Type.IsValueType) { |
||||
if (val.Type.FullNameWithoutGenericArguments == typeof(List<>).FullName) { |
||||
if ((int)val.GetFieldValue("_size").PrimitiveValue > 0) |
||||
this.GetChildren = () => GetIListChildren(this.GetValue); |
||||
} else { |
||||
this.GetChildren = () => GetObjectChildren(val.Type); |
||||
} |
||||
} else if (val.Type.IsPointer) { |
||||
if (val.Dereference() != null) { |
||||
this.GetChildren = () => new[] { new ValueNode("Icons.16x16.Local", "*" + this.Name, () => GetValue().Dereference()) }; |
||||
} |
||||
} |
||||
|
||||
// Do last since it may expire the object
|
||||
if (val.IsNull) { |
||||
fullValue = "null"; |
||||
} else if (val.Type.IsInteger) { |
||||
var i = val.PrimitiveValue; |
||||
if (DebuggingOptions.Instance.ShowIntegersAs == ShowIntegersAs.Decimal) { |
||||
fullValue = i.ToString(); |
||||
} else { |
||||
string hex = string.Format("0x{0:X4}", i); |
||||
if (hex.Length > 6 ) hex = string.Format("0x{0:X8}", i); |
||||
if (hex.Length > 10) hex = string.Format("0x{0:X16}", i); |
||||
if (DebuggingOptions.Instance.ShowIntegersAs == ShowIntegersAs.Hexadecimal) { |
||||
fullValue = hex; |
||||
} else { |
||||
fullValue = string.Format("{0} ({1})", i, hex); |
||||
} |
||||
} |
||||
} else if (val.Type.IsPointer) { |
||||
fullValue = String.Format("0x{0:X}", val.PointerAddress); |
||||
} else if (val.Type.FullName == typeof(string).FullName) { |
||||
fullValue = '"' + val.InvokeToString(WindowsDebugger.EvalThread).Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + '"'; |
||||
} else if (val.Type.FullName == typeof(char).FullName) { |
||||
fullValue = "'" + val.InvokeToString(WindowsDebugger.EvalThread).Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + "'"; |
||||
} else if ((val.Type.IsClass || val.Type.IsValueType)) { |
||||
fullValue = val.InvokeToString(WindowsDebugger.EvalThread); |
||||
} else { |
||||
fullValue = val.AsString(); |
||||
} |
||||
|
||||
this.error = null; |
||||
this.Value = (fullValue.Length > 256) ? fullValue.Substring(0, 256) + "..." : fullValue; |
||||
this.Type = val.Type.Name; |
||||
|
||||
if (!val.IsNull) { |
||||
this.VisualizerCommands = VisualizerDescriptors.GetAllDescriptors() |
||||
.Where(descriptor => descriptor.IsVisualizerAvailable(val.Type)) |
||||
.Select(descriptor => descriptor.CreateVisualizerCommand(this.Name, this.GetValue)) |
||||
.ToList(); |
||||
} |
||||
|
||||
LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms", this.Name, watch.ElapsedMilliseconds); |
||||
|
||||
} catch (GetValueException e) { |
||||
error = e; |
||||
this.Value = e.Message; |
||||
this.Type = string.Empty; |
||||
this.GetChildren = null; |
||||
this.VisualizerCommands = null; |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// public ContextMenuStrip GetContextMenu()
|
||||
// {
|
||||
// if (this.Error != null) return GetErrorContextMenu();
|
||||
//
|
||||
// ContextMenuStrip menu = new ContextMenuStrip();
|
||||
//
|
||||
// ToolStripMenuItem copyItem;
|
||||
// copyItem = new ToolStripMenuItem();
|
||||
// copyItem.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CopyToClipboard");
|
||||
// copyItem.Checked = false;
|
||||
// copyItem.Click += delegate {
|
||||
// ClipboardWrapper.SetText(fullText);
|
||||
// };
|
||||
|
||||
// ToolStripMenuItem hexView;
|
||||
// hexView = new ToolStripMenuItem();
|
||||
// hexView.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.ShowInHexadecimal");
|
||||
// hexView.Checked = DebuggingOptions.Instance.ShowValuesInHexadecimal;
|
||||
// hexView.Click += delegate {
|
||||
// // refresh all pads that use ValueNode for display
|
||||
// DebuggingOptions.Instance.ShowValuesInHexadecimal = !DebuggingOptions.Instance.ShowValuesInHexadecimal;
|
||||
// // always check if instance is null, might be null if pad is not opened
|
||||
// if (LocalVarPad.Instance != null)
|
||||
// LocalVarPad.Instance.RefreshPad();
|
||||
// if (WatchPad.Instance != null)
|
||||
// WatchPad.Instance.RefreshPad();
|
||||
// };
|
||||
|
||||
// menu.Items.AddRange(new ToolStripItem[] {
|
||||
// copyItem,
|
||||
// //hexView
|
||||
// });
|
||||
//
|
||||
// return menu;
|
||||
// }
|
||||
|
||||
ContextMenuStrip GetErrorContextMenu() |
||||
{ |
||||
ContextMenuStrip menu = new ContextMenuStrip(); |
||||
|
||||
ToolStripMenuItem showError = new ToolStripMenuItem(); |
||||
showError.Text = StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.ShowFullError}"); |
||||
showError.Click += delegate { MessageService.ShowException(error, null); }; |
||||
menu.Items.Add(showError); |
||||
|
||||
return menu; |
||||
} |
||||
|
||||
public static string GetImageForMember(IDebugMemberInfo memberInfo) |
||||
{ |
||||
string name = string.Empty; |
||||
|
||||
if (memberInfo.IsPublic) { |
||||
} else if (memberInfo.IsAssembly) { |
||||
name += "Internal"; |
||||
} else if (memberInfo.IsFamily) { |
||||
name += "Protected"; |
||||
} else if (memberInfo.IsPrivate) { |
||||
name += "Private"; |
||||
} |
||||
|
||||
if (memberInfo is FieldInfo) { |
||||
name += "Field"; |
||||
} else if (memberInfo is PropertyInfo) { |
||||
name += "Property"; |
||||
} else if (memberInfo is MethodInfo) { |
||||
name += "Method"; |
||||
} else { |
||||
throw new DebuggerException("Unknown member type " + memberInfo.GetType().FullName); |
||||
} |
||||
|
||||
return "Icons.16x16." + name; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// The root of any node evaluation is valid stack frame.
|
||||
/// </summary>
|
||||
static StackFrame GetCurrentStackFrame() |
||||
{ |
||||
if (WindowsDebugger.CurrentProcess == null) |
||||
throw new GetValueException("Debugger is not running"); |
||||
if (WindowsDebugger.CurrentProcess.IsRunning) |
||||
throw new GetValueException("Process is not paused"); |
||||
if (WindowsDebugger.CurrentStackFrame == null) |
||||
throw new GetValueException("No stack frame selected"); |
||||
|
||||
return WindowsDebugger.CurrentStackFrame; |
||||
} |
||||
|
||||
public static IEnumerable<TreeNode> GetLocalVariables() |
||||
{ |
||||
var stackFrame = GetCurrentStackFrame(); |
||||
foreach(DebugParameterInfo par in stackFrame.MethodInfo.GetParameters()) { |
||||
var parCopy = par; |
||||
yield return new ValueNode("Icons.16x16.Parameter", par.Name, () => parCopy.GetValue(GetCurrentStackFrame())); |
||||
} |
||||
if (stackFrame.HasSymbols) { |
||||
foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(stackFrame.IP)) { |
||||
var locVarCopy = locVar; |
||||
yield return new ValueNode("Icons.16x16.Local", locVar.Name, () => locVarCopy.GetValue(GetCurrentStackFrame())); |
||||
} |
||||
} else { |
||||
WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; |
||||
if (debugger.debuggerDecompilerService != null) { |
||||
int typeToken = stackFrame.MethodInfo.DeclaringType.MetadataToken; |
||||
int methodToken = stackFrame.MethodInfo.MetadataToken; |
||||
foreach (var localVar in debugger.debuggerDecompilerService.GetLocalVariables(typeToken, methodToken)) { |
||||
int index = ((int[])debugger.debuggerDecompilerService.GetLocalVariableIndex(typeToken, methodToken, localVar))[0]; |
||||
yield return new ValueNode("Icons.16x16.Local", localVar, () => { |
||||
var newStackFrame = GetCurrentStackFrame(); |
||||
if (newStackFrame.MethodInfo != stackFrame.MethodInfo) |
||||
throw new GetValueException("Expected stack frame: " + stackFrame.MethodInfo.ToString()); |
||||
|
||||
return newStackFrame.GetLocalVariableValue((uint)index); |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
IEnumerable<TreeNode> GetObjectChildren(DebugType shownType) |
||||
{ |
||||
MemberInfo[] publicStatic = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); |
||||
MemberInfo[] publicInstance = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); |
||||
MemberInfo[] nonPublicStatic = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly); |
||||
MemberInfo[] nonPublicInstance = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); |
||||
|
||||
DebugType baseType = (DebugType)shownType.BaseType; |
||||
if (baseType != null) { |
||||
yield return new TreeNode( |
||||
"Icons.16x16.Class", |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}"), |
||||
baseType.Name, |
||||
baseType.FullName, |
||||
baseType.FullName == "System.Object" ? (Func<IEnumerable<TreeNode>>) null : () => GetObjectChildren(baseType) |
||||
); |
||||
} |
||||
|
||||
if (nonPublicInstance.Length > 0) { |
||||
yield return new TreeNode( |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicMembers}"), |
||||
() => GetMembers(nonPublicInstance) |
||||
); |
||||
} |
||||
|
||||
if (publicStatic.Length > 0 || nonPublicStatic.Length > 0) { |
||||
yield return new TreeNode( |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.StaticMembers}"), |
||||
() => { |
||||
var children = GetMembers(publicStatic).ToList(); |
||||
if (nonPublicStatic.Length > 0) { |
||||
children.Insert(0, new TreeNode( |
||||
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicStaticMembers}"), |
||||
() => GetMembers(nonPublicStatic) |
||||
)); |
||||
} |
||||
return children; |
||||
} |
||||
); |
||||
} |
||||
|
||||
if (shownType.GetInterface(typeof(IList).FullName) != null) { |
||||
yield return new TreeNode( |
||||
"IList", |
||||
() => GetIListChildren(GetValue) |
||||
); |
||||
} else { |
||||
DebugType iEnumerableType, itemType; |
||||
if (shownType.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { |
||||
yield return new TreeNode( |
||||
null, |
||||
"IEnumerable", |
||||
"Expanding will enumerate the IEnumerable", |
||||
string.Empty, |
||||
() => GetIListChildren(() => DebuggerHelpers.CreateListFromIEnumerable(GetValue())) |
||||
); |
||||
} |
||||
} |
||||
|
||||
foreach(TreeNode node in GetMembers(publicInstance)) { |
||||
yield return node; |
||||
} |
||||
} |
||||
|
||||
IEnumerable<TreeNode> GetMembers(MemberInfo[] members) |
||||
{ |
||||
foreach(MemberInfo memberInfo in members.OrderBy(m => m.Name)) { |
||||
var memberInfoCopy = memberInfo; |
||||
string imageName = GetImageForMember((IDebugMemberInfo)memberInfo); |
||||
yield return new ValueNode(imageName, memberInfo.Name, () => GetValue().GetMemberValue(WindowsDebugger.EvalThread, memberInfoCopy)); |
||||
} |
||||
} |
||||
|
||||
static IEnumerable<TreeNode> GetIListChildren(Func<Value> getValue) |
||||
{ |
||||
Value list; |
||||
PropertyInfo itemProp; |
||||
int count = 0; |
||||
try { |
||||
// TODO: We want new list on reeval
|
||||
// We need the list to survive generation of index via Eval
|
||||
list = getValue().GetPermanentReference(WindowsDebugger.EvalThread); |
||||
DebugType iListType = (DebugType)list.Type.GetInterface(typeof(IList).FullName); |
||||
itemProp = iListType.GetProperty("Item"); |
||||
// Do not get string representation since it can be printed in hex
|
||||
count = (int)list.GetPropertyValue(WindowsDebugger.EvalThread, iListType.GetProperty("Count")).PrimitiveValue; |
||||
} catch (GetValueException e) { |
||||
return new [] { new TreeNode(null, "(error)", e.Message, string.Empty, null) }; |
||||
} |
||||
if (count == 0) { |
||||
return new [] { new TreeNode("(empty)", null) }; |
||||
} else { |
||||
return Enumerable.Range(0, count).Select(i => new ValueNode("Icons.16x16.Field", "[" + i + "]", () => list.GetPropertyValue(WindowsDebugger.EvalThread, itemProp, Eval.CreateValue(WindowsDebugger.EvalThread, i)))); |
||||
} |
||||
} |
||||
|
||||
TreeNode GetArraySubsetNode(ArrayDimensions bounds, ArrayDimensions originalBounds) |
||||
{ |
||||
StringBuilder name = new StringBuilder(); |
||||
bool isFirst = true; |
||||
name.Append("["); |
||||
for(int i = 0; i < bounds.Count; i++) { |
||||
if (!isFirst) name.Append(", "); |
||||
isFirst = false; |
||||
ArrayDimension dim = bounds[i]; |
||||
ArrayDimension originalDim = originalBounds[i]; |
||||
|
||||
if (dim.Count == 0) { |
||||
name.Append("-"); |
||||
} else if (dim.Count == 1) { |
||||
name.Append(dim.LowerBound.ToString()); |
||||
} else if (dim.Equals(originalDim)) { |
||||
name.Append("*"); |
||||
} else { |
||||
name.Append(dim.LowerBound); |
||||
name.Append(".."); |
||||
name.Append(dim.UpperBound); |
||||
} |
||||
} |
||||
name.Append("]"); |
||||
|
||||
return new TreeNode(name.ToString(), () => GetArrayChildren(bounds, originalBounds)); |
||||
} |
||||
|
||||
IEnumerable<TreeNode> GetArrayChildren(ArrayDimensions bounds, ArrayDimensions originalBounds) |
||||
{ |
||||
const int MaxElementCount = 1000; |
||||
|
||||
if (bounds.TotalElementCount == 0) |
||||
{ |
||||
yield return new TreeNode("(empty)", null); |
||||
yield break; |
||||
} |
||||
|
||||
// The whole array is small - just add all elements as childs
|
||||
if (bounds.TotalElementCount <= MaxElementCount * 2) { |
||||
foreach(int[] indices in bounds.Indices) { |
||||
StringBuilder sb = new StringBuilder(indices.Length * 4); |
||||
sb.Append("["); |
||||
bool isFirst = true; |
||||
foreach(int index in indices) { |
||||
if (!isFirst) sb.Append(", "); |
||||
sb.Append(index.ToString()); |
||||
isFirst = false; |
||||
} |
||||
sb.Append("]"); |
||||
int[] indicesCopy = indices; |
||||
yield return new ValueNode("Icons.16x16.Field", sb.ToString(), () => GetValue().GetArrayElement(indicesCopy)); |
||||
} |
||||
yield break; |
||||
} |
||||
|
||||
// Find a dimension of size at least 2
|
||||
int splitDimensionIndex = bounds.Count - 1; |
||||
for(int i = 0; i < bounds.Count; i++) { |
||||
if (bounds[i].Count > 1) { |
||||
splitDimensionIndex = i; |
||||
break; |
||||
} |
||||
} |
||||
ArrayDimension splitDim = bounds[splitDimensionIndex]; |
||||
|
||||
// Split the dimension
|
||||
int elementsPerSegment = 1; |
||||
while (splitDim.Count > elementsPerSegment * MaxElementCount) { |
||||
elementsPerSegment *= MaxElementCount; |
||||
} |
||||
for(int i = splitDim.LowerBound; i <= splitDim.UpperBound; i += elementsPerSegment) { |
||||
List<ArrayDimension> newDims = new List<ArrayDimension>(bounds); |
||||
newDims[splitDimensionIndex] = new ArrayDimension(i, Math.Min(i + elementsPerSegment - 1, splitDim.UpperBound)); |
||||
yield return GetArraySubsetNode(new ArrayDimensions(newDims), originalBounds); |
||||
} |
||||
yield break; |
||||
} |
||||
} |
||||
} |
@ -1,16 +0,0 @@
@@ -1,16 +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; |
||||
|
||||
namespace Debugger.AddIn.Visualizers |
||||
{ |
||||
/// <summary>
|
||||
/// Can provide individial items for a lazy collection, as well as total count of items.
|
||||
/// </summary>
|
||||
public interface IListValuesProvider<T> |
||||
{ |
||||
int GetCount(); |
||||
T GetItemAt(int index); |
||||
} |
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
// 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.Linq; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
|
||||
namespace Debugger.AddIn.Visualizers.Graph |
||||
{ |
||||
/// <summary>
|
||||
/// NRefactory Expression plus a method that can evaluate it,
|
||||
/// as the Debugger does not support evaluating NRefactory expressions directly.
|
||||
/// </summary>
|
||||
public class GraphExpression |
||||
{ |
||||
public Expression Expr { get; set; } |
||||
public Func<Value> GetValue { get; set; } |
||||
|
||||
public GraphExpression(Expression expr, Func<Value> getValue) |
||||
{ |
||||
if (expr == null) throw new ArgumentNullException("expr"); |
||||
if (getValue == null) throw new ArgumentNullException("getValue"); |
||||
this.Expr = expr; |
||||
this.GetValue = getValue; |
||||
} |
||||
} |
||||
} |
@ -1,85 +0,0 @@
@@ -1,85 +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.Generic; |
||||
using Debugger.AddIn.Visualizers.Utils; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
using System.Reflection; |
||||
|
||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
||||
{ |
||||
/// <summary>
|
||||
/// Item of a collection in the debugee, with lazy evaluated properties.
|
||||
/// </summary>
|
||||
public class ObjectValue |
||||
{ |
||||
/// <summary> Index of this item in the collection. </summary>
|
||||
public int Index { get; private set; } |
||||
|
||||
// PermanentReference for one row.
|
||||
public Value PermanentReference { get; private set; } |
||||
|
||||
private Dictionary<string, ObjectProperty> properties = new Dictionary<string, ObjectProperty>(); |
||||
|
||||
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
|
||||
private Dictionary<string, MemberInfo> memberForNameMap; |
||||
|
||||
internal ObjectValue(int index, Dictionary<string, MemberInfo> memberFromNameMap) |
||||
{ |
||||
this.Index = index; |
||||
this.memberForNameMap = memberFromNameMap; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns property with given name.
|
||||
/// </summary>
|
||||
public ObjectProperty this[string propertyName] |
||||
{ |
||||
get |
||||
{ |
||||
ObjectProperty property; |
||||
// has property with name 'propertyName' already been evaluated?
|
||||
if(!this.properties.TryGetValue(propertyName, out property)) |
||||
{ |
||||
if (this.PermanentReference == null) { |
||||
throw new DebuggerVisualizerException("Cannot get member of this ObjectValue - ObjectValue.PermanentReference is null"); |
||||
} |
||||
MemberInfo memberInfo = this.memberForNameMap.GetValue(propertyName); |
||||
if (memberInfo == null) { |
||||
throw new DebuggerVisualizerException("Cannot get member value - no member found with name " + propertyName); |
||||
} |
||||
property = CreatePropertyFromValue(propertyName, this.PermanentReference.GetMemberValue(memberInfo)); |
||||
this.properties.Add(propertyName, property); |
||||
} |
||||
return property; |
||||
} |
||||
} |
||||
|
||||
public static ObjectValue Create(Debugger.Value value, int index, Dictionary<string, MemberInfo> memberFromName) |
||||
{ |
||||
ObjectValue result = new ObjectValue(index, memberFromName); |
||||
|
||||
// remember PermanentReference for expanding IEnumerable
|
||||
Value permanentReference = value.GetPermanentReference(); |
||||
result.PermanentReference = permanentReference; |
||||
|
||||
return result; |
||||
} |
||||
|
||||
private static ObjectProperty CreatePropertyFromValue(string propertyName, Value value) |
||||
{ |
||||
ObjectProperty property = new ObjectProperty(); |
||||
property.Name = propertyName; |
||||
// property.Expression = ?.Age
|
||||
// - cannot use expression,
|
||||
// if the value is returned from an enumerator, it has no meaningful expression
|
||||
property.IsAtomic = value.Type.IsPrimitive; |
||||
property.IsNull = value.IsNull; |
||||
property.Value = value.IsNull ? "" : value.InvokeToString(); |
||||
return property; |
||||
} |
||||
} |
||||
} |
@ -1,50 +0,0 @@
@@ -1,50 +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; |
||||
using System.Collections.Generic; |
||||
|
||||
using Debugger.AddIn.Visualizers.Utils; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
using System.Reflection; |
||||
|
||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
||||
{ |
||||
/// <summary>
|
||||
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IEnumerable.
|
||||
/// </summary>
|
||||
/*public class EnumerableValuesProvider : GridValuesProvider |
||||
{ |
||||
public EnumerableValuesProvider(Expression targetObject, DebugType iEnumerableType, DebugType itemType) |
||||
:base(targetObject, iEnumerableType, itemType) |
||||
{ |
||||
this.itemsSource = enumerateItems(); |
||||
} |
||||
|
||||
private IEnumerable<ObjectValue> itemsSource; |
||||
public IEnumerable<ObjectValue> ItemsSource |
||||
{ |
||||
get { return this.itemsSource; } |
||||
} |
||||
|
||||
private IEnumerable<ObjectValue> enumerateItems() |
||||
{ |
||||
MethodInfo enumeratorMethod = collectionType.GetMethod("GetEnumerator"); |
||||
Value enumerator = targetObject.Evaluate(WindowsDebugger.CurrentProcess).InvokeMethod(enumeratorMethod, null).GetPermanentReference(); |
||||
|
||||
MethodInfo moveNextMethod = enumerator.Type.GetMethod("MoveNext"); |
||||
PropertyInfo currentproperty = enumerator.Type.GetInterface(typeof(IEnumerator).FullName).GetProperty("Current"); |
||||
|
||||
int index = 0; |
||||
while ((bool)enumerator.InvokeMethod(moveNextMethod, null).PrimitiveValue) |
||||
{ |
||||
Value currentValue = enumerator.GetPropertyValue(currentproperty); |
||||
yield return ObjectValue.Create(currentValue, index++, this.memberFromNameMap); |
||||
} |
||||
} |
||||
}*/ |
||||
} |
@ -1,42 +0,0 @@
@@ -1,42 +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.Generic; |
||||
using Debugger.AddIn.Visualizers.Utils; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using System.Reflection; |
||||
|
||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
||||
{ |
||||
/// <summary>
|
||||
/// Provides <see cref="ObjectValue"/>s to be displayed in Grid visualizer.
|
||||
/// Descandants implement getting values for IList and IEnumerable.
|
||||
/// </summary>
|
||||
public class GridValuesProvider |
||||
{ |
||||
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
|
||||
protected Dictionary<string, MemberInfo> memberFromNameMap; |
||||
|
||||
protected Expression targetObject; |
||||
protected DebugType itemType; |
||||
|
||||
public GridValuesProvider(Expression targetObject, DebugType itemType) |
||||
{ |
||||
this.targetObject = targetObject; |
||||
this.itemType = itemType; |
||||
|
||||
this.memberFromNameMap = this.GetItemTypeMembers().MakeDictionary(memberInfo => memberInfo.Name); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets members that will be displayed as columns.
|
||||
/// </summary>
|
||||
public IList<MemberInfo> GetItemTypeMembers() |
||||
{ |
||||
var publicPropetiesAndFields = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); |
||||
return publicPropetiesAndFields; |
||||
} |
||||
} |
||||
} |
@ -1,59 +0,0 @@
@@ -1,59 +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.Generic; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using Debugger.AddIn.Visualizers.Utils; |
||||
using Debugger.MetaData; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.SharpDevelop.Services; |
||||
|
||||
namespace Debugger.AddIn.Visualizers.GridVisualizer |
||||
{ |
||||
/// <summary>
|
||||
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IList.
|
||||
/// </summary>
|
||||
public class ListValuesProvider : GridValuesProvider, IListValuesProvider<ObjectValue> |
||||
{ |
||||
int? listCount = null; |
||||
/// <summary>
|
||||
/// After evaluating how many items to clear debugger Expression cache,
|
||||
/// so that the cache does not keep too many PermanentReferences.
|
||||
/// </summary>
|
||||
static readonly int ClearCacheThreshold = 50; |
||||
|
||||
public ListValuesProvider(Expression targetObject, DebugType listItemType) |
||||
:base(targetObject, listItemType) |
||||
{ |
||||
} |
||||
|
||||
public int GetCount() |
||||
{ |
||||
if (this.listCount == null) { |
||||
this.listCount = this.targetObject.GetIListCount(); |
||||
} |
||||
return this.listCount.Value; |
||||
} |
||||
|
||||
/// <summary>When this reaches ClearCacheThreshold, the debugger Expression cache is cleared.</summary>
|
||||
int itemClearCacheCounter = 0; |
||||
|
||||
public ObjectValue GetItemAt(int index) |
||||
{ |
||||
if (itemClearCacheCounter++ > ClearCacheThreshold) { |
||||
// clear debugger Expression cache to avoid holding too many PermanentReferences
|
||||
WindowsDebugger.CurrentProcess.ClearExpressionCache(); |
||||
LoggingService.Info("Cleared debugger Expression cache."); |
||||
itemClearCacheCounter = 0; |
||||
} |
||||
return ObjectValue.Create( |
||||
targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess), |
||||
//targetObject.AppendIndexer(index), // use Expression instead of value - possible only for IList though
|
||||
index, |
||||
this.memberFromNameMap); |
||||
} |
||||
} |
||||
} |
@ -1,12 +0,0 @@
@@ -1,12 +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.Generic; |
||||
using System.Linq; |
||||
using System; |
||||
|
||||
public enum TextVisualizerMode |
||||
{ |
||||
PlainText, |
||||
Xml |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue