diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
index 79c009707e..a17ec6120e 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
+++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
@@ -15,13 +15,6 @@
-
-
-
-
EditBreakpointScriptWindow.xaml
Code
-
DebuggerTooltipControl.xaml
-
-
- PinCloseControl.xaml
-
-
- PinDebuggerControl.xaml
-
-
-
-
VisualizerPicker.xaml
@@ -205,6 +194,7 @@
+
@@ -267,7 +257,6 @@
DebuggeeExceptionForm.cs
-
@@ -372,9 +361,6 @@
-
-
-
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs
index 17ab1144f6..d8de070030 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs
@@ -10,7 +10,7 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Services
{
- public enum ShowIntegersAs { Auto, Decimal, Hexadecimal };
+ public enum ShowIntegersAs { Decimal, Hexadecimal, Both, Auto };
[Serializable]
public class DebuggingOptions: Options
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs
index b391df174f..ccc20a9464 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs
@@ -94,8 +94,8 @@ namespace Debugger.AddIn
if (this.Owner is WatchPad) {
WatchPad pad = (WatchPad)this.Owner;
var node = pad.WatchList.SelectedNode;
- if (node != null && node.Node is ExpressionNode) {
- string text = ((ExpressionNode)node.Node).FullText;
+ if (node != null && node.Node is ValueNode) {
+ string text = ((ValueNode)node.Node).FullText;
ClipboardWrapper.SetText(text);
}
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs
index 3bd353e36c..3b624fe16b 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs
@@ -32,7 +32,7 @@ namespace Debugger.AddIn.Pads.Controls
}
public override object Icon {
- get { return this.Node.ImageSource; }
+ get { return this.Node.Image.ImageSource; }
}
public override bool ShowExpander {
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml
index f31b220086..d88e84eef2 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml
@@ -21,7 +21,7 @@
-
+
@@ -32,7 +32,7 @@
-
+
@@ -41,8 +41,8 @@
-
-
+
+
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
index 07ad0ec678..f382c435f9 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
@@ -53,9 +53,9 @@ namespace Debugger.AddIn.Pads.Controls
}
if (e.Key == Key.Enter) {
- if(SelectedNode.Node is ExpressionNode) {
- var node = (ExpressionNode)SelectedNode.Node;
- node.SetText(((TextBox)sender).Text);
+ if(SelectedNode.Node is ValueNode) {
+ var node = (ValueNode)SelectedNode.Node;
+ node.Value = ((TextBox)sender).Text;
}
}
if (e.Key == Key.Enter || e.Key == Key.Escape) {
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
index d1fb38c508..7d3987e18e 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
@@ -71,7 +71,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
debuggedProcess.EnqueueForEach(
Dispatcher.CurrentDispatcher,
- Utils.GetLocalVariableNodes(frame).ToList(),
+ ValueNode.GetLocalVariables().ToList(),
n => localVarList.WatchItems.Add(n.ToSharpTreeNode())
);
} catch (Exception ex) {
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
index 99b236f3b1..5669593f99 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
@@ -192,7 +192,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
LoggingService.Info("Evaluating: " + (string.IsNullOrEmpty(node.Node.Name) ? "is null or empty!" : node.Node.Name));
//Value val = ExpressionEvaluator.Evaluate(nod.Name, nod.Language, debuggedProcess.SelectedStackFrame);
- ExpressionNode valNode = new ExpressionNode(null, node.Node.Name, () => debugger.GetExpression(node.Node.Name).Evaluate(debuggedProcess));
+ ValueNode valNode = new ValueNode(null, node.Node.Name, () => debugger.GetExpression(node.Node.Name).Evaluate(debuggedProcess));
return valNode.ToSharpTreeNode();
} catch (GetValueException) {
string error = String.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.InvalidExpression}"), node.Node.Name);
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/RemotingConfigurationHelpper.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/RemotingConfigurationHelpper.cs
deleted file mode 100644
index b77f20be6b..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Service/RemotingConfigurationHelpper.cs
+++ /dev/null
@@ -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;
- }
- }
-}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
index acf29b606b..f8bfe43bcc 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
@@ -28,6 +28,7 @@ using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Project;
using Mono.Cecil;
using Process = Debugger.Process;
+using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
namespace ICSharpCode.SharpDevelop.Services
{
@@ -39,7 +40,6 @@ namespace ICSharpCode.SharpDevelop.Services
Cancel = 2
}
- bool useRemotingForThreadInterop = false;
bool attached;
NDebugger debugger;
@@ -491,18 +491,18 @@ namespace ICSharpCode.SharpDevelop.Services
{
try {
var tooltipExpression = GetExpression(variableName);
- ExpressionNode expressionNode = new ExpressionNode("Icons.16x16.Local", variableName, () => tooltipExpression.Evaluate(this.DebuggedProcess));
- return new DebuggerTooltipControl(logicalPosition, expressionNode) { ShowPins = debuggedProcess.GetCurrentExecutingFrame().HasSymbols };
+ var valueNode = new ValueNode("Icons.16x16.Local", variableName, () => tooltipExpression.Evaluate(this.DebuggedProcess));
+ return new DebuggerTooltipControl(new TreeNode[] { valueNode });
} catch (System.Exception ex) {
LoggingService.Error("Error on GetTooltipControl: " + ex.Message);
return null;
}
}
- public ITreeNode GetNode(string variable, string currentImageName = null)
+ public Debugger.AddIn.TreeModel.TreeNode GetNode(string variable, string currentImageName = null)
{
try {
- return new ExpressionNode(currentImageName ?? "Icons.16x16.Local", variable, () => GetExpression(variable).Evaluate(this.DebuggedProcess));
+ return new ValueNode(currentImageName ?? "Icons.16x16.Local", variable, () => GetExpression(variable).Evaluate(this.DebuggedProcess));
} catch (GetValueException) {
return null;
}
@@ -539,12 +539,6 @@ namespace ICSharpCode.SharpDevelop.Services
public void InitializeService()
{
- if (useRemotingForThreadInterop) {
- // This needs to be called before instance of NDebugger is created
- string path = RemotingConfigurationHelpper.GetLoadedAssemblyPath("Debugger.Core.dll");
- new RemotingConfigurationHelpper(path).Configure();
- }
-
// get decompiler service
var items = AddInTree.BuildItems("/SharpDevelop/Services/DebuggerDecompilerService", null, false);
if (items.Count > 0)
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs
deleted file mode 100644
index acf3663258..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs
+++ /dev/null
@@ -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
-{
- ///
- /// Popup containing .
- ///
- 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 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;
- }
- }
-}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml
index b28e746732..1ad63cf46b 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml
@@ -1,29 +1,123 @@
-
-
-
+ xmlns:debugging="clr-namespace:Debugger.AddIn.Tooltips"
+ AllowsTransparency="True"
+>
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
+
-
-
-
+
+
+ Margin="0"
+ Focusable="False"
+ Width="19"
+ Height="13"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -133,24 +225,16 @@
-
+
-
-
+
+
-
-
+
+
@@ -159,82 +243,48 @@
-
+
-
-
+
+
-
-
+
+
+ Text="{Binding Value}"
+ >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
index 62f76b5141..9785ef6763 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
@@ -3,426 +3,117 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
-using System.Windows.Documents;
+using System.Windows.Data;
using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Animation;
-using System.Windows.Shapes;
+
using Debugger.AddIn.TreeModel;
-using ICSharpCode.Core;
-using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Bookmarks;
-using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
-using ICSharpCode.SharpDevelop.Gui;
namespace Debugger.AddIn.Tooltips
{
- ///
- /// Default Control used as content of SharpDevelop debugger tooltips.
- ///
- public partial class DebuggerTooltipControl : UserControl, ITooltip
+ public partial class DebuggerTooltipControl : Popup, ITooltip
{
- private const double ChildPopupOpenXOffet = 16;
- private const double ChildPopupOpenYOffet = 15;
- private const int InitialItemsCount = 12;
- private const int VisibleItemsCount = 11;
+ static Point ChildPopupOffset = new Point(16, 15);
- private bool showPins = true;
- private LazyItemsControl lazyGrid;
- private IEnumerable itemsSource;
- readonly Location logicalPosition;
+ public DebuggerTooltipControl ChildTooltip { get; private set; }
+ public IEnumerable TreeNodes { get; set; }
- public DebuggerTooltipControl(Location logicalPosition)
+ public DebuggerTooltipControl(IEnumerable treeNodes)
{
- this.logicalPosition = logicalPosition;
InitializeComponent();
- Loaded += new RoutedEventHandler(OnLoaded);
- }
-
- public DebuggerTooltipControl(Location logicalPosition, ITreeNode node)
- : this(logicalPosition, new ITreeNode[] { node })
- {
+ this.TreeNodes = treeNodes;
+ this.dataGrid.ItemsSource = treeNodes;
- }
-
- public DebuggerTooltipControl(Location logicalPosition, IEnumerable nodes)
- : this(logicalPosition)
- {
- this.itemsSource = nodes;
- }
-
- public DebuggerTooltipControl(DebuggerTooltipControl parentControl, Location logicalPosition)
- : this(logicalPosition)
- {
- this.parentControl = parentControl;
+ // Only the leaf of the tooltip has this set to false
+ // Therefore it will automatically close if something else gets focus
+ this.StaysOpen = false;
+ this.Placement = PlacementMode.Absolute;
}
- private void OnLoaded(object sender, RoutedEventArgs e)
- {
- if (!showPins) {
- dataGrid.Columns[5].Visibility = Visibility.Collapsed;
- }
-
- SetItemsSource(this.itemsSource);
- }
-
- public event RoutedEventHandler Closed;
- protected void OnClosed()
+ private void Expand_Click(object sender, RoutedEventArgs e)
{
- if (this.Closed != null) {
- this.Closed(this, new RoutedEventArgs());
- }
- }
-
- public bool ShowPins {
- get { return showPins; }
- set { showPins = value; }
- }
-
- public IEnumerable ItemsSource {
- get { return this.itemsSource; }
- }
-
- public void SetItemsSource(IEnumerable value) {
- this.itemsSource = value;
- this.lazyGrid = new LazyItemsControl(this.dataGrid, InitialItemsCount);
-
- // HACK for updating the pins in tooltip
- var observable = new List();
- this.itemsSource.ForEach(item => observable.Add(item));
-
- // verify if at the line of the root there's a pin bookmark
- ITextEditor editor;
- var viewContent = WorkbenchSingleton.Workbench.ActiveViewContent;
- ITextEditorProvider provider = viewContent as ITextEditorProvider;
- if (provider != null) {
- editor = provider.TextEditor;
- } else {
- editor = viewContent.GetService(typeof(ITextEditor)) as ITextEditor;
- }
+ var clickedButton = (ToggleButton)e.OriginalSource;
+ var clickedNode = (TreeNode)clickedButton.DataContext;
- if (editor != null) {
- var pin = BookmarkManager.Bookmarks.Find(
- b => b is PinBookmark &&
- b.Location.Line == logicalPosition.Line &&
- b.FileName == editor.FileName) as PinBookmark;
+ if (clickedButton.IsChecked == true && clickedNode.GetChildren != null) {
+ Point popupPos = clickedButton.PointToScreen(ChildPopupOffset).TransformFromDevice(clickedButton);
+ this.ChildTooltip = new DebuggerTooltipControl(clickedNode.GetChildren().ToList()) {
+ // We can not use placement target otherwise we would get too deep logical tree
+ Placement = PlacementMode.Absolute,
+ HorizontalOffset = popupPos.X,
+ VerticalOffset = popupPos.Y,
+ };
- if (pin != null) {
- observable.ForEach(item => { // TODO: find a way not to use "observable"
- if (pin.ContainsNode(item))
- item.IsPinned = true;
- });
- }
- }
-
- var source = new VirtualizingIEnumerable(observable);
- lazyGrid.ItemsSource = source;
- this.dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll));
-
- if (this.lazyGrid.ItemsSourceTotalCount != null) {
- // hide up/down buttons if too few items
- btnUp.Visibility = btnDown.Visibility =
- this.lazyGrid.ItemsSourceTotalCount.Value <= VisibleItemsCount ? Visibility.Collapsed : Visibility.Visible;
+ // The child is now tracking the focus
+ this.StaysOpen = true;
+ this.ChildTooltip.StaysOpen = false;
+
+ this.ChildTooltip.Closed += delegate {
+ // The null will have the effect of ignoring the next click
+ clickedButton.IsChecked = clickedButton.IsMouseOver ? (bool?)null : false;
+ // Either keep closing or make us the new leaf
+ if (this.IsMouseOver) {
+ this.StaysOpen = false;
+ } else {
+ this.IsOpen = false;
+ }
+ };
+ this.ChildTooltip.IsOpen = true;
}
}
- //public Location LogicalPosition { get; set; }
-
- ///
- public bool ShowAsPopup
- {
- get
- {
- return true;
- }
- }
-
- ///
- public bool Close(bool mouseClick)
- {
- if (mouseClick || (!mouseClick && !isChildExpanded)) {
- CloseChildPopups();
- return true;
- } else {
- return false;
- }
- }
-
- private DebuggerPopup childPopup { get; set; }
- private DebuggerTooltipControl parentControl { get; set; }
- internal DebuggerPopup containingPopup { get; set; }
-
- bool isChildExpanded
- {
- get
- {
- return this.childPopup != null && this.childPopup.IsOpen;
- }
- }
-
- private ToggleButton expandedButton;
-
- ///
- /// Closes the child popup of this control, if it exists.
- ///
- public void CloseChildPopups()
- {
- if (this.expandedButton != null) {
- this.expandedButton.IsChecked = false;
- this.expandedButton = null;
- // nice simple example of indirect recursion
- this.childPopup.CloseSelfAndChildren();
- }
- }
-
- public void CloseOnLostFocus()
- {
- // when we close, parent becomes leaf
- if (this.containingPopup != null) {
- this.containingPopup.IsLeaf = true;
- }
- if (!this.IsMouseOver) {
- if (this.containingPopup != null) {
- this.containingPopup.IsOpen = false;
- this.containingPopup.IsLeaf = false;
- }
- if (this.parentControl != null) {
- this.parentControl.CloseOnLostFocus();
- }
- OnClosed();
- } else {
- // leaf closed because of click inside this control - stop the closing chain
- if (this.expandedButton != null && !this.expandedButton.IsMouseOver) {
- this.expandedButton.IsChecked = false;
- this.expandedButton = null;
- }
+ bool ITooltip.CloseOnHoverEnd {
+ get {
+ return this.ChildTooltip == null;
}
}
- private void btnExpander_Click(object sender, RoutedEventArgs e)
+ protected override void OnClosed(EventArgs e)
{
- 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)) {
- CloseChildPopups();
- this.expandedButton = clickedButton;
-
- // open child Popup
- if (this.childPopup == null) {
- this.childPopup = new DebuggerPopup(this, logicalPosition, showPins);
- this.childPopup.Placement = PlacementMode.Absolute;
- }
- if (this.containingPopup != null) {
- this.containingPopup.IsLeaf = false;
- }
- this.childPopup.IsLeaf = true;
- this.childPopup.HorizontalOffset = buttonPos.X + ChildPopupOpenXOffet;
- this.childPopup.VerticalOffset = buttonPos.Y + ChildPopupOpenYOffet;
- if (clickedNode.GetChildren != null) {
- this.childPopup.ItemsSource = clickedNode.GetChildren().ToList();
- this.childPopup.Open();
- }
- } else {
- CloseChildPopups();
+ // Closing the popup does not normally cause LostFocus on the textbox so we have to update it manually
+ TextBox textBox = FocusManager.GetFocusedElement(this) as TextBox;
+ if (textBox != null) {
+ BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty);
+ be.UpdateSource();
}
- }
-
- private void handleScroll(object sender, ScrollChangedEventArgs e)
- {
- btnUp.IsEnabled = !this.lazyGrid.IsScrolledToStart;
- btnDown.IsEnabled = !this.lazyGrid.IsScrolledToEnd;
- }
- void BtnUp_Click(object sender, RoutedEventArgs e)
- {
- this.lazyGrid.ScrollViewer.ScrollUp(1);
- }
-
- void BtnDown_Click(object sender, RoutedEventArgs e)
- {
- this.lazyGrid.ScrollViewer.ScrollDown(1);
- }
-
- #region Edit value in tooltip
-
- void TextBox_KeyUp(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Escape) {
- dataGrid.Focus();
- return;
- }
+ base.OnClosed(e);
- if (e.Key == Key.Enter) {
- dataGrid.Focus();
- // set new value
- var textBox = (TextBox)e.OriginalSource;
- var newValue = textBox.Text;
- var node = ((FrameworkElement)sender).DataContext as ITreeNode;
- SaveNewValue(node, textBox.Text);
- }
- }
-
- void TextBox_LostFocus(object sender, RoutedEventArgs e)
- {
- var textBox = (TextBox)e.OriginalSource;
- var newValue = textBox.Text;
- var node = ((FrameworkElement)sender).DataContext as ITreeNode;
- SaveNewValue(node, textBox.Text);
- }
-
- void SaveNewValue(ITreeNode node, string newValue)
- {
- if(node != null && node.SetText(newValue)) {
- // show adorner
- var adornerLayer = AdornerLayer.GetAdornerLayer(dataGrid);
- var adorners = adornerLayer.GetAdorners(dataGrid);
- if (adorners != null && adorners.Length != 0)
- adornerLayer.Remove(adorners[0]);
- SavedAdorner adorner = new SavedAdorner(dataGrid);
- adornerLayer.Add(adorner);
- }
- }
-
- #endregion
-
- #region Pining checked/unchecked
-
- void PinButton_Checked(object sender, RoutedEventArgs e)
- {
- ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider;
- var editor = provider.TextEditor;
- if (editor == null) return;
- var node = (ITreeNode)(((ToggleButton)(e.OriginalSource)).DataContext);
-
- if (!string.IsNullOrEmpty(editor.FileName)) {
-
- // verify if at the line of the root there's a pin bookmark
- var pin = BookmarkManager.Bookmarks.Find(
- b => b is PinBookmark &&
- b.LineNumber == logicalPosition.Line &&
- b.FileName == editor.FileName) as PinBookmark;
-
- if (pin == null) {
- pin = new PinBookmark(editor.FileName, logicalPosition);
- // show pinned DebuggerPopup
- if (pin.Popup == null) {
- pin.Popup = new PinDebuggerControl();
- pin.Popup.Mark = pin;
- Rect rect = new Rect(this.DesiredSize);
- var point = this.PointToScreen(rect.TopRight);
- pin.Popup.Location = new Point { X = 500, Y = point.Y - 150 };
- pin.Nodes.Add(node);
- pin.Popup.ItemsSource = pin.Nodes;
- }
-
- // do actions
- pin.Popup.Open();
- BookmarkManager.AddMark(pin);
- }
- else
- {
- if (!pin.ContainsNode(node)) {
- pin.Nodes.Add(node);
- pin.Popup.ItemsSource = pin.Nodes;
- }
- }
- }
- }
-
- void PinButton_Unchecked(object sender, RoutedEventArgs e)
- {
- ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider;
- var editor = provider.TextEditor;
- if (editor == null) return;
-
- if (!string.IsNullOrEmpty(editor.FileName)) {
- // remove from pinned DebuggerPopup
- var pin = BookmarkManager.Bookmarks.Find(
- b => b is PinBookmark &&
- b.LineNumber == logicalPosition.Line &&
- b.FileName == editor.FileName) as PinBookmark;
- if (pin == null) return;
-
- ToggleButton button = (ToggleButton)e.OriginalSource;
- pin.RemoveNode((ITreeNode)button.DataContext);
- pin.Popup.ItemsSource = pin.Nodes;
- // remove if no more data pins are available
- if (pin.Nodes.Count == 0) {
- pin.Popup.Close();
-
- BookmarkManager.RemoveMark(pin);
- }
+ if (this.ChildTooltip != null) {
+ this.ChildTooltip.IsOpen = false;
}
}
void CopyMenuItemClick(object sender, RoutedEventArgs e)
{
- ExpressionNode node = ((MenuItem)sender).DataContext as ExpressionNode;
+ ValueNode node = ((MenuItem)sender).DataContext as ValueNode;
if (node != null) {
Clipboard.SetText(node.FullText);
}
}
- #endregion
-
- #region Saved Adorner
-
- class SavedAdorner : Adorner
+ /*
+ void AnimateCloseControl(bool show)
{
- public SavedAdorner(UIElement adornedElement) : base(adornedElement)
- {
- Loaded += delegate { 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));
- protected override void OnRender(DrawingContext drawingContext)
- {
- Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
-
- // Some arbitrary drawing implements.
- var formatedText = new FormattedText(StringParser.Parse("${res:ICSharpCode.SharpDevelop.Debugging.SavedString}"),
- CultureInfo.CurrentCulture,
- FlowDirection.LeftToRight,
- new Typeface(new FontFamily("Arial"),
- FontStyles.Normal,
- FontWeights.Black,
- FontStretches.Expanded),
- 8d,
- Brushes.Black);
-
-
- drawingContext.DrawText(formatedText,
- new Point(adornedElementRect.TopRight.X - formatedText.Width - 2,
- adornedElementRect.TopRight.Y));
- }
+ Storyboard board = new Storyboard();
+ board.Children.Add(animation);
- private void Show()
- {
- DoubleAnimation animation = new DoubleAnimation();
- animation.From = 1;
- animation.To = 0;
-
- animation.Duration = new Duration(TimeSpan.FromSeconds(2));
- animation.SetValue(Storyboard.TargetProperty, this);
- animation.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath(Rectangle.OpacityProperty));
-
- Storyboard board = new Storyboard();
- board.Children.Add(animation);
-
- board.Begin(this);
- }
+ board.Begin(this);
}
-
- #endregion
+ */
}
}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/LazyItemsControl.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/LazyItemsControl.cs
deleted file mode 100644
index f4af8a0aa7..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/LazyItemsControl.cs
+++ /dev/null
@@ -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
-{
- ///
- /// ItemsControl wrapper that takes VirtualizingIEnumerable as source,
- /// and adds additional items from the source to underlying ItemsControl when scrolled to bottom.
- ///
- public class LazyItemsControl
- {
- private ItemsControl itemsControl;
- private int initialItemsCount;
-
- ///
- /// Creates new instance of LazyItemsControl.
- ///
- /// ItemsControl to wrap and add items to it when scrolled to bottom.
- /// Number of items to be initially displayed in wrapped ItemsControl.
- 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;
- /// Items count of underlying IEnumerable. Null until scrolled to the end of IEnumerable.
- public int? ItemsSourceTotalCount
- {
- get
- {
- return this.itemsSourceTotalCount;
- }
- }
-
- private VirtualizingIEnumerable itemsSource;
- /// The collection that underlying ItemsControl sees.
- public VirtualizingIEnumerable ItemsSource
- {
- get { return itemsSource; }
- set
- {
- this.itemsSource = value;
- addNextItems(this.itemsSource, initialItemsCount);
- this.itemsControl.ItemsSource = value;
- }
- }
-
- private void addNextItems(VirtualizingIEnumerable 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);
- }
- }
- }
- }
-}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml
deleted file mode 100644
index c2fc077e1e..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml.cs
deleted file mode 100644
index d417c5ba38..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml.cs
+++ /dev/null
@@ -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 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);
- }
- }
-}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinControlsDictionary.xaml b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinControlsDictionary.xaml
deleted file mode 100644
index f06219eeb6..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinControlsDictionary.xaml
+++ /dev/null
@@ -1,363 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml
deleted file mode 100644
index 32218a3b76..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml
+++ /dev/null
@@ -1,240 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs
deleted file mode 100644
index a32e1a5ec9..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs
+++ /dev/null
@@ -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.Linq;
-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 lazyExpandersGrid;
- private LazyItemsControl lazyGrid;
- private LazyItemsControl lazyImagesGrid;
- private IEnumerable 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 ItemsSource
- {
- get { return this.itemsSource; }
- set {
- itemsSource = value;
- var items = new VirtualizingIEnumerable(value);
- lazyExpandersGrid = new LazyItemsControl(this.ExpandersGrid, InitialItemsCount);
- lazyExpandersGrid.ItemsSource = items;
-
- lazyGrid = new LazyItemsControl(this.dataGrid, InitialItemsCount);
- lazyGrid.ItemsSource = items;
-
- lazyImagesGrid = new LazyItemsControl(this.ImagesGrid, InitialItemsCount);
- lazyImagesGrid.ItemsSource = items;
- }
- }
-
- ///
- /// Relative position of the pin with respect to the screen.
- ///
- 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();
-//
-// 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(observable);
-// lazyGrid.ItemsSource = newSource;
-// lazyExpandersGrid.ItemsSource = newSource;
- }
-
- #endregion
-
- #region Expand button
-
- private ToggleButton expandedButton;
-
- ///
- /// Closes the child popup of this control, if it exists.
- ///
- 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.GetChildren != null) {
- this.childPopup.ItemsSource = clickedNode.GetChildren().ToList();
- 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.Name, node.ImageName);
- if (resultNode == null)
- return;
- // HACK for updating the pins in tooltip
- var observable = new ObservableCollection();
- var source = lazyGrid.ItemsSource;
- source.ForEach(item => {
- if (item.Name == node.Name)
- observable.Add(resultNode);
- else
- observable.Add(item);
- });
-
- Mark.Nodes = observable;
- // update UI
- var newSource = new VirtualizingIEnumerable(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
- }
-}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinLayer.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinLayer.cs
deleted file mode 100644
index cfc901f57f..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinLayer.cs
+++ /dev/null
@@ -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
-{
- ///
- /// Pin layer class. This class handles the pinning and unpinning operations.
- ///
- public class PinLayer : Canvas
- {
- private double verticalOffset = 0;
- private double horizontalOffset = 0;
-
- private TextView textView;
-
- ///
- /// PinLayer constructor.
- ///
- /// Text area for this layer.
- public PinLayer(TextArea textArea)
- {
- textView = textArea.TextView;
- textView.VisualLinesChanged += textView_VisualLinesChanged;
- }
-
- ///
- /// Pins an element;
- ///
- /// Element to pin.
- 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(currentThumb);
- container.Children.Add(element);
- this.Children.Add(currentThumb);
- }
-
- ///
- /// Unpins an element.
- ///
- /// Element to unpin.
- public void Unpin(PinDebuggerControl element)
- {
- if (element == null)
- throw new NullReferenceException("Element is null!");
-
- foreach (var thumb in this.Children) {
- PinDebuggerControl pinControl = TryFindChild((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(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(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(currnetThumb);
- if (pinControl != null)
- pinControl.Opacity = 1d;
- }
-
- #endregion
-
- #region Static helpers
-
- static T TryFindChild(DependencyObject root) where T : DependencyObject
- {
- return WpfTreeNavigation.TryFindChild(root);
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs
deleted file mode 100644
index ca3282af2a..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs
+++ /dev/null
@@ -1,118 +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();
- foreach (var tuple in pin.SavedNodes) {
- var node = new Debugger.AddIn.TreeModel.TreeNode(
- !string.IsNullOrEmpty(tuple.Item1) ? tuple.Item1 : "Icons.16x16.Field",
- tuple.Item2,
- tuple.Item3,
- string.Empty,
- null
- );
- 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>();
-
- foreach (var node in pin.Nodes) {
- pin.SavedNodes.Add(
- new Tuple(
- "Icons.16x16.Field",
- node.Name,
- 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;
- }
- }
-}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VirtualizingIEnumerable.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VirtualizingIEnumerable.cs
deleted file mode 100644
index ca51500f2e..0000000000
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VirtualizingIEnumerable.cs
+++ /dev/null
@@ -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
-{
- ///
- /// A wrapper around IEnumerable<T> with AddNextItems method for pulling additional items
- /// from underlying IEnumerable<T>.
- /// Can be used as source for .
- ///
- public class VirtualizingIEnumerable : ObservableCollection
- {
- private IEnumerator originalSourceEnumerator;
-
- public VirtualizingIEnumerable(IEnumerable originalSource)
- {
- if (originalSource == null)
- throw new ArgumentNullException("originalSource");
-
- this.originalSourceEnumerator = originalSource.GetEnumerator();
- }
-
- private bool hasNext = true;
- ///
- /// False if all items from underlying IEnumerable have already been added.
- ///
- public bool HasNext
- {
- get
- {
- return this.hasNext;
- }
- }
-
- ///
- /// Requests next items from underlying IEnumerable source and adds them to the collection.
- ///
- public void AddNextItems(int count)
- {
- for (int i = 0; i < count; i++) {
- if (!originalSourceEnumerator.MoveNext()) {
- this.hasNext = false;
- break;
- }
- this.Add(originalSourceEnumerator.Current);
- }
- }
- }
-}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs
index 4bdabbdb65..b90a7745ec 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs
@@ -16,62 +16,81 @@ namespace Debugger.AddIn.TreeModel
///
/// A node in the variable tree.
///
- public class TreeNode : ITreeNode
+ public class TreeNode : INotifyPropertyChanged
{
- public IImage IconImage { get; protected set; }
- public string ImageName { get; set; }
- public string Name { get; set; }
- public virtual string Text { get; set; }
- public virtual string Type { get; protected set; }
- public virtual Func> GetChildren { get; protected set; }
+ public event EventHandler PropertyRead;
+ public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
- ///
- /// System.Windows.Media.ImageSource version of .
- ///
- public ImageSource ImageSource {
- get {
- return this.IconImage == null ? null : this.IconImage.ImageSource;
+ IImage image;
+ string name;
+ string value;
+ string type;
+
+ public IImage Image {
+ get {
+ OnPropertyRead("Image");
+ return this.image;
+ }
+ set {
+ if (this.image != value) {
+ this.image = value;
+ OnPropertyChanged("Image");
+ }
}
}
- ///
- /// System.Drawing.Image version of .
- ///
- public Image Image {
- get {
- return this.IconImage == null ? null : this.IconImage.Bitmap;
+ public string Name {
+ get {
+ OnPropertyRead("Name");
+ return this.name;
+ }
+ set {
+ if (this.name != value) {
+ this.name = value;
+ OnPropertyChanged("Name");
+ }
}
}
- public virtual bool CanSetText {
- get { return false; }
- }
+ public bool CanSetName { get; protected set; }
- Func> ITreeNode.GetChildren {
+ public string Value {
get {
- if (this.GetChildren == null)
- return null;
- return () => this.GetChildren();
+ OnPropertyRead("Value");
+ return this.value;
+ }
+ set {
+ if (this.value != value) {
+ this.value = value;
+ OnPropertyChanged("Value");
+ }
}
}
- public virtual bool HasChildNodes {
- get { return this.GetChildren != null; }
- }
-
- public virtual IEnumerable VisualizerCommands {
+ public bool CanSetValue { get; protected set; }
+
+ public string Type {
get {
- return null;
+ OnPropertyRead("Type");
+ return this.type;
+ }
+ set {
+ if (this.type != value) {
+ this.type = value;
+ OnPropertyChanged("Type");
+ }
}
}
- public virtual bool HasVisualizerCommands {
- get {
- return (VisualizerCommands != null) && (VisualizerCommands.Count() > 0);
- }
+ public Func> GetChildren { get; protected set; }
+
+ public bool HasChildren {
+ get { return GetChildren != null; }
}
- public bool IsPinned { get; set; }
+ public IEnumerable VisualizerCommands { get; protected set; }
+
+ public bool HasVisualizerCommands { get; protected set; }
public TreeNode(string name, Func> getChildren)
{
@@ -79,19 +98,32 @@ namespace Debugger.AddIn.TreeModel
this.GetChildren = getChildren;
}
- public TreeNode(string imageName, string name, string text, string type, Func> getChildren)
+ public TreeNode(string imageName, string name, string value, string type, Func> getChildren)
{
- this.ImageName = imageName;
- if (imageName != null)
- this.IconImage = new ResourceServiceImage(imageName);
+ this.Image = string.IsNullOrEmpty(imageName) ? null : new ResourceServiceImage(imageName);
this.Name = name;
- this.Text = text;
+ this.Value = value;
this.Type = type;
this.GetChildren = getChildren;
}
- public virtual bool SetText(string newValue) {
- return false;
+ protected virtual void OnPropertyRead(string name)
+ {
+ if (PropertyRead != null) {
+ PropertyRead(this, new PropertyEventArgs() { Name = name});
+ }
+ }
+
+ protected virtual void OnPropertyChanged(string name)
+ {
+ if (PropertyChanged != null) {
+ PropertyChanged(this, new PropertyChangedEventArgs(name));
+ }
}
}
+
+ public class PropertyEventArgs: EventArgs
+ {
+ public string Name { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
index aec8c66701..7814d2f628 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
@@ -12,346 +12,172 @@ 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
{
///
- /// Node in the tree which can be defined by a debugger expression.
- /// The expression will be lazily evaluated when needed.
+ /// Tree node which represents debuggee's .
+ /// The node stores a lambda which can be used to reobtain the value
+ /// at any time (possibly even after some stepping).
///
- public class ExpressionNode: TreeNode, INotifyPropertyChanged
+ ///
+ /// The general rule is that getting a value or getting children will
+ /// either succeed or result in .
+ ///
+ public class ValueNode: TreeNode
{
- bool evaluated;
-
- Func valueGetter;
- Value permanentValue;
- bool canSetText;
- GetValueException error;
- string fullText;
+ Func getValue;
+ Action setValue;
- public bool Evaluated {
- get { return evaluated; }
- set { evaluated = value; }
- }
-
- public override bool CanSetText {
- get {
- if (!evaluated) EvaluateExpression();
- return canSetText;
- }
- }
+ Value cachedValue;
+ Debugger.Process cachedValueProcess;
+ object cachedValueDebuggeeState;
- public GetValueException Error {
- get {
- if (!evaluated) EvaluateExpression();
- return error;
- }
- }
+ string fullValue;
+ GetValueException error;
public string FullText {
- get { return fullText; }
+ get { return this.Value; }
}
- public override string Text {
- get {
- if (!evaluated) EvaluateExpression();
- return base.Text;
- }
- set {
- if (value != base.Text) {
- base.Text = value;
- NotifyPropertyChanged("Text");
- }
- }
- }
-
- public override string Type {
- get {
- if (!evaluated) EvaluateExpression();
- return base.Type;
- }
- }
-
- public override Func> GetChildren {
- get {
- if (!evaluated) EvaluateExpression();
- return base.GetChildren;
- }
- protected set {
- base.GetChildren = value;
- }
- }
-
- /// Used to determine available VisualizerCommands
- private DebugType expressionType;
- /// Used to determine available VisualizerCommands
- private bool valueIsNull = true;
-
- private IEnumerable visualizerCommands;
- public override IEnumerable VisualizerCommands {
- get {
- if (visualizerCommands == null) {
- visualizerCommands = getAvailableVisualizerCommands();
- }
- return visualizerCommands;
- }
- }
-
- private IEnumerable getAvailableVisualizerCommands()
+ public ValueNode(string imageName, string name, Func getValue, Action setValue = null)
+ : base(imageName, name, string.Empty, string.Empty, null)
{
- if (!evaluated) EvaluateExpression();
+ if (getValue == null)
+ throw new ArgumentNullException("getValue");
- 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;
- }*/
+ this.getValue = getValue;
+ this.setValue = setValue;
- foreach (var descriptor in VisualizerDescriptors.GetAllDescriptors()) {
- if (descriptor.IsVisualizerAvailable(this.expressionType)) {
- yield return descriptor.CreateVisualizerCommand(this.Name, () => this.Evaluate());
- }
- }
- }
-
- public ExpressionNode(string imageName, string name, Func valueGetter)
- : base(imageName, name, string.Empty, string.Empty, null)
- {
- this.valueGetter = valueGetter;
+ GetValueAndUpdateUI();
}
///
/// Get the value of the node and cache it as long-lived reference.
/// We assume that the user will need this value a lot.
///
- public Value Evaluate()
+ public Value GetValue()
{
- if (permanentValue == null)
+ // 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();
- permanentValue = valueGetter().GetPermanentReference();
+ cachedValue = this.getValue().GetPermanentReference();
+ 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 permanentValue;
- }
-
- ///
- /// Get the value of the node and update the UI text fields.
- ///
- void EvaluateExpression()
- {
- evaluated = true;
-
- Stopwatch watch = new Stopwatch();
- watch.Start();
-
- Value val;
- try {
- // Do not keep permanent reference
- val = valueGetter();
- } 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) {
- var dims = val.ArrayDimensions; // Eval now
- this.GetChildren = () => Utils.GetChildNodesOfArray(this, dims, dims);
- }
- } else if (val.Type.IsClass || val.Type.IsValueType) {
- if (val.Type.FullNameWithoutGenericArguments == typeof(List<>).FullName) {
- if ((int)val.GetMemberValue("_size").PrimitiveValue > 0)
- this.GetChildren = () => Utils.GetItemsOfIList(() => this.Evaluate());
- } else {
- this.GetChildren = () => Utils.GetChildNodesOfObject(this, val.Type);
- }
- } else if (val.Type.IsPointer) {
- Value deRef = val.Dereference();
- if (deRef != null) {
- this.GetChildren = () => new ExpressionNode [] { new ExpressionNode(this.ImageName, "*" + this.Name, () => this.Evaluate().Dereference()) };
- }
- }
-
- // 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;
-
- LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms", this.Name, watch.ElapsedMilliseconds);
- }
-
- 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("\"", "\\\"");
+ return cachedValue;
}
- string FormatInteger(object i)
+ public void SetValue(Value value)
{
- if (DebuggingOptions.Instance.ShowIntegersAs == ShowIntegersAs.Decimal)
- return i.ToString();
+ if (setValue == null)
+ throw new DebuggerException("Setting of value is not supported for this node");
- 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);
+ try
+ {
+ this.setValue(value);
}
- 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++;
+ catch(GetValueException e)
+ {
+ MessageService.ShowMessage(e.Message, "${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}");
}
-
- return size >= 7 && runs <= (size + 7) / 8;
}
- public override bool SetText(string newText)
- {
- Value val = null;
+ ///
+ /// Get the value of the node and update the UI text fields.
+ ///
+ void GetValueAndUpdateUI()
+ {
try {
- val = this.Evaluate();
- 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();
+ 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.GetMemberValue("_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().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().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();
} else {
- val.PrimitiveValue = newText;
+ fullValue = val.AsString();
}
- 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 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";
- }
+
+ 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);
- 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);
+ } catch (GetValueException e) {
+ error = e;
+ this.Value = e.Message;
+ this.Type = string.Empty;
+ this.GetChildren = null;
+ this.VisualizerCommands = null;
+ return;
}
-
- return "Icons.16x16." + name;
}
// public ContextMenuStrip GetContextMenu()
@@ -390,54 +216,72 @@ namespace Debugger.AddIn.TreeModel
// return menu;
// }
- public ContextMenuStrip GetErrorContextMenu()
+ ContextMenuStrip GetErrorContextMenu()
{
ContextMenuStrip menu = new ContextMenuStrip();
- ToolStripMenuItem showError;
- showError = new ToolStripMenuItem();
+ ToolStripMenuItem 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
- });
+ showError.Click += delegate { MessageService.ShowException(error, null); };
+ menu.Items.Add(showError);
return menu;
}
- public static WindowsDebugger WindowsDebugger {
- get {
- return (WindowsDebugger)DebuggerService.CurrentDebugger;
+ 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;
}
- public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
-
- private void NotifyPropertyChanged(string info)
+ ///
+ /// The root of any node evaluation is valid stack frame.
+ ///
+ static StackFrame GetCurrentStackFrame()
{
- if (PropertyChanged != null)
- {
- PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(info));
- }
+ var debugger = DebuggerService.CurrentDebugger as WindowsDebugger;
+
+ if (debugger == null || debugger.DebuggedProcess == null)
+ throw new GetValueException("Debugger is not running");
+ if (debugger.DebuggedProcess.IsRunning)
+ throw new GetValueException("Process is not paused");
+ if (debugger.DebuggedProcess.SelectedStackFrame == null)
+ throw new GetValueException("No stack frame selected");
+
+ return debugger.DebuggedProcess.SelectedStackFrame;
}
- }
-
- public partial class Utils
- {
- public static IEnumerable GetLocalVariableNodes(StackFrame stackFrame)
+
+ public static IEnumerable GetLocalVariables()
{
+ var stackFrame = GetCurrentStackFrame();
foreach(DebugParameterInfo par in stackFrame.MethodInfo.GetParameters()) {
var parCopy = par;
- yield return new ExpressionNode("Icons.16x16.Parameter", par.Name, () => parCopy.GetValue(stackFrame));
+ 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 ExpressionNode("Icons.16x16.Local", locVar.Name, () => locVarCopy.GetValue(stackFrame));
+ yield return new ValueNode("Icons.16x16.Local", locVar.Name, () => locVarCopy.GetValue(GetCurrentStackFrame()));
}
} else {
WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger;
@@ -446,19 +290,19 @@ namespace Debugger.AddIn.TreeModel
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 ExpressionNode("Icons.16x16.Local", localVar, () => stackFrame.GetLocalVariableValue((uint)index));
+ 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);
+ });
}
}
}
- if (stackFrame.Thread.CurrentException != null) {
- yield return new ExpressionNode(null, "$exception", () => stackFrame.Thread.CurrentException.Value);
- }
}
- }
-
- public partial class Utils
- {
- public static IEnumerable GetChildNodesOfObject(ExpressionNode expr, DebugType shownType)
+
+ IEnumerable GetObjectChildren(DebugType shownType)
{
MemberInfo[] publicStatic = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
MemberInfo[] publicInstance = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
@@ -472,14 +316,14 @@ namespace Debugger.AddIn.TreeModel
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}"),
baseType.Name,
baseType.FullName,
- baseType.FullName == "System.Object" ? (Func>) null : () => Utils.GetChildNodesOfObject(expr, baseType)
+ baseType.FullName == "System.Object" ? (Func>) null : () => GetObjectChildren(baseType)
);
}
if (nonPublicInstance.Length > 0) {
yield return new TreeNode(
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicMembers}"),
- () => GetMembersOfObject(expr, nonPublicInstance)
+ () => GetMembers(nonPublicInstance)
);
}
@@ -487,11 +331,11 @@ namespace Debugger.AddIn.TreeModel
yield return new TreeNode(
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.StaticMembers}"),
() => {
- var children = GetMembersOfObject(expr, publicStatic).ToList();
+ var children = GetMembers(publicStatic).ToList();
if (nonPublicStatic.Length > 0) {
children.Insert(0, new TreeNode(
StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicStaticMembers}"),
- () => GetMembersOfObject(expr, nonPublicStatic)
+ () => GetMembers(nonPublicStatic)
));
}
return children;
@@ -502,70 +346,59 @@ namespace Debugger.AddIn.TreeModel
if (shownType.GetInterface(typeof(IList).FullName) != null) {
yield return new TreeNode(
"IList",
- () => GetItemsOfIList(() => expr.Evaluate())
+ () => GetIListChildren(GetValue)
);
} else {
- DebugType listType, iEnumerableType, itemType;
+ DebugType iEnumerableType, itemType;
if (shownType.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) {
yield return new TreeNode(
null,
"IEnumerable",
"Expanding will enumerate the IEnumerable",
string.Empty,
- () => GetItemsOfIList(() => DebuggerHelpers.CreateListFromIEnumeralbe(expr.Evaluate(), itemType, out listType))
+ () => GetIListChildren(() => DebuggerHelpers.CreateListFromIEnumeralbe(GetValue()))
);
}
}
- foreach(TreeNode node in GetMembersOfObject(expr, publicInstance)) {
+ foreach(TreeNode node in GetMembers(publicInstance)) {
yield return node;
}
}
- public static IEnumerable GetMembersOfObject(ExpressionNode expr, MemberInfo[] members)
+ IEnumerable GetMembers(MemberInfo[] members)
{
foreach(MemberInfo memberInfo in members.OrderBy(m => m.Name)) {
var memberInfoCopy = memberInfo;
- string imageName = ExpressionNode.GetImageForMember((IDebugMemberInfo)memberInfo);
- yield return new ExpressionNode(imageName, memberInfo.Name, () => expr.Evaluate().GetMemberValue(memberInfoCopy));
+ string imageName = GetImageForMember((IDebugMemberInfo)memberInfo);
+ yield return new ValueNode(imageName, memberInfo.Name, () => GetValue().GetMemberValue(memberInfoCopy));
}
}
- public static IEnumerable GetItemsOfIList(Func getValue)
+ static IEnumerable GetIListChildren(Func getValue)
{
- Value list = null;
- DebugType iListType = null;
+ Value list;
+ PropertyInfo itemProp;
int count = 0;
- GetValueException error = null;
try {
- // We use lambda for the value just so that we can get it in this try-catch block
+ // TODO: We want new list on reeval
+ // We need the list to survive generation of index via Eval
list = getValue().GetPermanentReference();
- iListType = (DebugType)list.Type.GetInterface(typeof(IList).FullName);
+ 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(iListType.GetProperty("Count")).PrimitiveValue;
} catch (GetValueException e) {
- // Cannot yield a value in the body of a catch clause (CS1631)
- error = e;
+ return new [] { new TreeNode(null, "(error)", e.Message, string.Empty, null) };
}
- if (error != null) {
- yield return new TreeNode(null, "(error)", error.Message, string.Empty, null);
- } else if (count == 0) {
- yield return new TreeNode("(empty)", null);
+ if (count == 0) {
+ return new [] { new TreeNode("(empty)", null) };
} else {
- PropertyInfo pi = iListType.GetProperty("Item");
- for(int i = 0; i < count; i++) {
- int iCopy = i;
- yield return new ExpressionNode("Icons.16x16.Field", "[" + i + "]", () => list.GetPropertyValue(pi, Eval.CreateValue(list.AppDomain, iCopy)));
- }
+ return Enumerable.Range(0, count).Select(i => new ValueNode("Icons.16x16.Field", "[" + i + "]", () => list.GetPropertyValue(itemProp, Eval.CreateValue(list.AppDomain, i))));
}
}
- }
-
- public partial class Utils
- {
- const int MaxElementCount = 100;
- public static TreeNode GetArrayRangeNode(ExpressionNode expr, ArrayDimensions bounds, ArrayDimensions originalBounds)
+ TreeNode GetArraySubsetNode(ArrayDimensions bounds, ArrayDimensions originalBounds)
{
StringBuilder name = new StringBuilder();
bool isFirst = true;
@@ -590,11 +423,13 @@ namespace Debugger.AddIn.TreeModel
}
name.Append("]");
- return new TreeNode(name.ToString(), () => GetChildNodesOfArray(expr, bounds, originalBounds));
+ return new TreeNode(name.ToString(), () => GetArrayChildren(bounds, originalBounds));
}
- public static IEnumerable GetChildNodesOfArray(ExpressionNode arrayTarget, ArrayDimensions bounds, ArrayDimensions originalBounds)
+ IEnumerable GetArrayChildren(ArrayDimensions bounds, ArrayDimensions originalBounds)
{
+ const int MaxElementCount = 1000;
+
if (bounds.TotalElementCount == 0)
{
yield return new TreeNode("(empty)", null);
@@ -602,7 +437,7 @@ namespace Debugger.AddIn.TreeModel
}
// The whole array is small - just add all elements as childs
- if (bounds.TotalElementCount <= MaxElementCount) {
+ if (bounds.TotalElementCount <= MaxElementCount * 2) {
foreach(int[] indices in bounds.Indices) {
StringBuilder sb = new StringBuilder(indices.Length * 4);
sb.Append("[");
@@ -614,7 +449,7 @@ namespace Debugger.AddIn.TreeModel
}
sb.Append("]");
int[] indicesCopy = indices;
- yield return new ExpressionNode("Icons.16x16.Field", sb.ToString(), () => arrayTarget.Evaluate().GetArrayElement(indicesCopy));
+ yield return new ValueNode("Icons.16x16.Field", sb.ToString(), () => GetValue().GetArrayElement(indicesCopy));
}
yield break;
}
@@ -637,7 +472,7 @@ namespace Debugger.AddIn.TreeModel
for(int i = splitDim.LowerBound; i <= splitDim.UpperBound; i += elementsPerSegment) {
List newDims = new List(bounds);
newDims[splitDimensionIndex] = new ArrayDimension(i, Math.Min(i + elementsPerSegment - 1, splitDim.UpperBound));
- yield return GetArrayRangeNode(arrayTarget, new ArrayDimensions(newDims), originalBounds);
+ yield return GetArraySubsetNode(new ArrayDimensions(newDims), originalBounds);
}
yield break;
}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IVisualizerCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/IVisualizerCommand.cs
similarity index 100%
rename from src/Main/Base/Project/Src/Services/Debugger/Tooltips/IVisualizerCommand.cs
rename to src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/IVisualizerCommand.cs
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs
index 53b7b1c643..a5031cc5b2 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs
@@ -78,7 +78,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout
if ((this.Property != null) && (this.Property.ObjectGraphProperty != null)) {
var memberInfo = (IDebugMemberInfo)this.Property.ObjectGraphProperty.MemberInfo;
if (memberInfo != null) {
- var image = new ResourceServiceImage(ExpressionNode.GetImageForMember(memberInfo));
+ var image = new ResourceServiceImage(ValueNode.GetImageForMember(memberInfo));
this.MemberIcon = image.ImageSource;
}
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs
index d03a78198a..a05d8cb746 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs
@@ -47,7 +47,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
} else {
// Value is IEnumerable
if (shownValue.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) {
- shownValue = DebuggerHelpers.CreateListFromIEnumeralbe(shownValue, itemType, out iListType);
+ shownValue = DebuggerHelpers.CreateListFromIEnumeralbe(shownValue);
+ iListType = DebugType.CreateFromType(shownValue.AppDomain, typeof(System.Collections.Generic.IList<>), itemType);
} else {
// Not IList or IEnumerable - can't be displayed in GridVisualizer
return;
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs
index ba4e3c4136..0c89a25c7e 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs
@@ -34,14 +34,19 @@ namespace Debugger.AddIn.Visualizers.Utils
}
- public static Value CreateListFromIEnumeralbe(Value iEnumerableValue, DebugType itemType, out DebugType listType)
+ public static Value CreateListFromIEnumeralbe(Value iEnumerableValue)
{
- listType = DebugType.CreateFromType(iEnumerableValue.AppDomain, typeof(System.Collections.Generic.List<>), itemType);
- DebugType iEnumerableType = DebugType.CreateFromType(itemType.AppDomain, typeof(IEnumerable<>), itemType);
+ DebugType iEnumerableType, itemType;
+ if (!iEnumerableValue.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType))
+ throw new GetValueException("Value is not IEnumeralbe");
+
+ DebugType listType = DebugType.CreateFromType(iEnumerableValue.AppDomain, typeof(System.Collections.Generic.List<>), itemType);
ConstructorInfo ctor = listType.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, new System.Type[] { iEnumerableType }, null);
if (ctor == null)
throw new DebuggerException("List constructor not found");
- return (Value)ctor.Invoke(new object[] { iEnumerableValue });
+
+ // Keep reference since we do not want to keep reenumerating it
+ return ((Value)ctor.Invoke(new object[] { iEnumerableValue })).GetPermanentReference();
}
///
diff --git a/src/AddIns/Debugger/Debugger.Core/Eval.cs b/src/AddIns/Debugger/Debugger.Core/Eval.cs
index 497d36c378..15edd7d898 100644
--- a/src/AddIns/Debugger/Debugger.Core/Eval.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Eval.cs
@@ -246,7 +246,7 @@ namespace Debugger
Value arg = args[i];
DebugType paramType = (DebugType)method.GetParameters()[i].ParameterType;
if (!arg.Type.CanImplicitelyConvertTo(paramType))
- throw new GetValueException("Inncorrect parameter type");
+ throw new GetValueException("Inncorrect parameter type. Expected " + paramType.ToString());
// Implicitely convert to correct primitve type
if (paramType.IsPrimitive && args[i].Type != paramType) {
object oldPrimVal = arg.PrimitiveValue;
diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs
index 72afa64446..b5b97f7aaa 100644
--- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs
+++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Reflection;
namespace Debugger.MetaData
{
@@ -11,6 +12,8 @@ namespace Debugger.MetaData
int localIndex;
DebugType localType;
+ public DebugMethodInfo Member { get; private set; }
+
///
public override int LocalIndex {
get { return localIndex; }
@@ -34,8 +37,9 @@ namespace Debugger.MetaData
public bool IsThis { get; internal set; }
public bool IsCaptured { get; internal set; }
- public DebugLocalVariableInfo(string name, int localIndex, int startOffset, int endOffset, DebugType localType, ValueGetter getter)
+ public DebugLocalVariableInfo(DebugMethodInfo member, string name, int localIndex, int startOffset, int endOffset, DebugType localType, ValueGetter getter)
{
+ this.Member = member;
this.Name = name;
this.localIndex = localIndex;
this.StartOffset = startOffset;
@@ -46,6 +50,11 @@ namespace Debugger.MetaData
public Value GetValue(StackFrame context)
{
+ if (context == null)
+ throw new ArgumentNullException("context");
+ if (context.MethodInfo != this.Member)
+ throw new GetValueException("Expected stack frame: " + this.Member.ToString());
+
return getter(context);
}
diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
index 4e6b8e15d3..d73ef5dc20 100644
--- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
+++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
@@ -578,6 +578,7 @@ namespace Debugger.MetaData
// Add this
if (!this.IsStatic) {
DebugLocalVariableInfo thisVar = new DebugLocalVariableInfo(
+ this,
"this",
-1,
0, int.MaxValue,
@@ -593,13 +594,14 @@ namespace Debugger.MetaData
return localVariables;
}
- static void AddCapturedLocalVariables(List vars, int scopeStartOffset, int scopeEndOffset, ValueGetter getCaptureClass, DebugType captureClassType)
+ void AddCapturedLocalVariables(List vars, int scopeStartOffset, int scopeEndOffset, ValueGetter getCaptureClass, DebugType captureClassType)
{
if (captureClassType.IsDisplayClass || captureClassType.IsYieldEnumerator || captureClassType.IsAsyncStateMachine) {
foreach(DebugFieldInfo fieldInfo in captureClassType.GetFields()) {
DebugFieldInfo fieldInfoCopy = fieldInfo;
if (fieldInfo.Name.StartsWith("CS$")) continue; // Ignore
DebugLocalVariableInfo locVar = new DebugLocalVariableInfo(
+ this,
fieldInfo.Name,
-1,
scopeStartOffset,
@@ -661,6 +663,7 @@ namespace Debugger.MetaData
}
} else {
DebugLocalVariableInfo locVar = new DebugLocalVariableInfo(
+ this,
symVar.GetName(),
(int)symVar.GetAddressField1(),
// symVar also has Get*Offset methods, but the are not implemented
diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs
index cf95f75558..84cc7203ad 100644
--- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs
+++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs
@@ -45,6 +45,11 @@ namespace Debugger.MetaData
public Value GetValue(StackFrame context)
{
+ if (context == null)
+ throw new ArgumentNullException("context");
+ if (context.MethodInfo != this.Member)
+ throw new GetValueException("Expected stack frame: " + this.Member.ToString());
+
return getter(context);
}
diff --git a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs
index 6e96d8dee8..7a953b0b91 100644
--- a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs
+++ b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs
@@ -345,6 +345,8 @@ namespace Debugger
ICorDebugValue GetArgumentCorValue(int index)
{
+ this.Process.AssertPaused();
+
ICorDebugValue corValue;
try {
// Non-static methods include 'this' as first argument
@@ -382,6 +384,7 @@ namespace Debugger
public Value GetLocalVariableValue(uint address)
{
+ this.Process.AssertPaused();
try {
return new Value(this.AppDomain, this.CorILFrame.GetLocalVariable(address));
} catch (COMException e) {
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
index 7ecf773021..b0044b4805 100755
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
@@ -231,7 +231,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
#region Tooltip
ToolTip toolTip;
- Popup popup;
+ Popup popupToolTip;
void TextEditorMouseHover(object sender, MouseEventArgs e)
{
@@ -272,26 +272,19 @@ namespace ICSharpCode.AvalonEdit.AddIn
ToolTipRequestService.RequestToolTip(args);
}
+ if (!TryCloseExistingPopup(false)) {
+ return;
+ }
+
if (args.ContentToShow != null) {
- var contentToShowITooltip = args.ContentToShow as ITooltip;
+ popupToolTip = args.ContentToShow as Popup;
- if (contentToShowITooltip != null && contentToShowITooltip.ShowAsPopup) {
- if (!(args.ContentToShow is UIElement)) {
- throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow);
- }
- if (popup == null) {
- popup = CreatePopup();
- }
- // if popup was only first level, hovering somewhere else closes it
- if (TryCloseExistingPopup(false)) {
-
- // when popup content decides to close, close the popup
- contentToShowITooltip.Closed += (closedSender, closedArgs) => { popup.IsOpen = false; };
- popup.Child = (UIElement)args.ContentToShow;
- //ICSharpCode.SharpDevelop.Debugging.DebuggerService.CurrentDebugger.IsProcessRunningChanged
- SetPopupPosition(popup, e);
- popup.IsOpen = true;
- }
+ if (popupToolTip != null) {
+ var popupPosition = GetPopupPosition(e);
+ popupToolTip.HorizontalOffset = popupPosition.X;
+ popupToolTip.VerticalOffset = popupPosition.Y;
+ popupToolTip.IsOpen = true;
+ popupToolTip.StaysOpen = true; // We will close it ourselves
e.Handled = true;
} else {
if (toolTip == null) {
@@ -313,35 +306,19 @@ namespace ICSharpCode.AvalonEdit.AddIn
toolTip.IsOpen = true;
e.Handled = true;
}
- } else {
- // close popup if mouse hovered over empty area
- if (popup != null) {
- e.Handled = true;
- }
- TryCloseExistingPopup(false);
}
}
- bool TryCloseExistingPopup(bool hard)
+ bool TryCloseExistingPopup(bool mouseClick)
{
- bool canClose = true;
- if (popup != null) {
- var popupContentITooltip = popup.Child as ITooltip;
- if (popupContentITooltip != null) {
- canClose = popupContentITooltip.Close(hard);
- }
- if (canClose) {
- popup.IsOpen = false;
+ if (popupToolTip != null) {
+ if (popupToolTip.IsOpen && !mouseClick && popupToolTip is ITooltip && !((ITooltip)popupToolTip).CloseOnHoverEnd) {
+ return false; // Popup does not want to be closed yet
}
+ popupToolTip.IsOpen = false;
+ popupToolTip = null;
}
- return canClose;
- }
-
- void SetPopupPosition(Popup popup, MouseEventArgs mouseArgs)
- {
- var popupPosition = GetPopupPosition(mouseArgs);
- popup.HorizontalOffset = popupPosition.X;
- popup.VerticalOffset = popupPosition.Y;
+ return true;
}
/// Returns Popup position based on mouse position, in device independent units
@@ -364,17 +341,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
return positionInPixels.TransformFromDevice(this);
}
- Popup CreatePopup()
- {
- popup = new Popup();
- popup.Closed += PopupClosed;
- popup.AllowsTransparency = true;
- popup.PlacementTarget = this; // required for property inheritance
- popup.Placement = PlacementMode.Absolute;
- popup.StaysOpen = true;
- return popup;
- }
-
void TextEditorMouseHoverStopped(object sender, MouseEventArgs e)
{
if (toolTip != null) {
@@ -385,7 +351,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
void TextEditorMouseLeave(object sender, MouseEventArgs e)
{
- if (popup != null && !popup.IsMouseOver) {
+ if (popupToolTip != null && !popupToolTip.IsMouseOver) {
// do not close popup if mouse moved from editor to popup
TryCloseExistingPopup(false);
}
@@ -396,11 +362,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
toolTip = null;
}
- void PopupClosed(object sender, EventArgs e)
- {
- popup = null;
- }
-
#region GetTooltipTextForCollapsedSection
string GetTooltipTextForCollapsedSection(FoldingSection foldingSection)
{
diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs
index 2c8534419c..47cab50f77 100644
--- a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs
+++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs
@@ -76,7 +76,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
#region Popup
ToolTip toolTip;
- Popup popup;
+ Popup popupToolTip;
void TextEditorMouseHover(object sender, MouseEventArgs e)
{
@@ -92,24 +92,19 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
ToolTipRequestService.RequestToolTip(args);
}
+ if (!TryCloseExistingPopup(false)) {
+ return;
+ }
+
if (args.ContentToShow != null) {
- var contentToShowITooltip = args.ContentToShow as ITooltip;
+ popupToolTip = args.ContentToShow as Popup;
- if (contentToShowITooltip != null && contentToShowITooltip.ShowAsPopup) {
- if (!(args.ContentToShow is UIElement)) {
- throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow);
- }
- if (popup == null) {
- popup = CreatePopup();
- }
- if (TryCloseExistingPopup(false)) {
- // when popup content decides to close, close the popup
- contentToShowITooltip.Closed += (closedSender, closedArgs) => { popup.IsOpen = false; };
- popup.Child = (UIElement)args.ContentToShow;
- //ICSharpCode.SharpDevelop.Debugging.DebuggerService.CurrentDebugger.IsProcessRunningChanged
- SetPopupPosition(popup, e);
- popup.IsOpen = true;
- }
+ if (popupToolTip != null) {
+ var popupPosition = GetPopupPosition(e);
+ popupToolTip.HorizontalOffset = popupPosition.X;
+ popupToolTip.VerticalOffset = popupPosition.Y;
+ popupToolTip.IsOpen = true;
+ popupToolTip.StaysOpen = true; // We will close it ourselves
e.Handled = true;
} else {
if (toolTip == null) {
@@ -131,35 +126,19 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
toolTip.IsOpen = true;
e.Handled = true;
}
- } else {
- // close popup if mouse hovered over empty area
- if (popup != null) {
- e.Handled = true;
- }
- TryCloseExistingPopup(false);
}
}
bool TryCloseExistingPopup(bool mouseClick)
{
- bool canClose = true;
- if (popup != null) {
- var popupContentITooltip = popup.Child as ITooltip;
- if (popupContentITooltip != null) {
- canClose = popupContentITooltip.Close(mouseClick);
- }
- if (canClose) {
- popup.IsOpen = false;
+ if (popupToolTip != null) {
+ if (popupToolTip.IsOpen && !mouseClick && popupToolTip is ITooltip && !((ITooltip)popupToolTip).CloseOnHoverEnd) {
+ return false; // Popup does not want to be closed yet
}
+ popupToolTip.IsOpen = false;
+ popupToolTip = null;
}
- return canClose;
- }
-
- void SetPopupPosition(Popup popup, MouseEventArgs mouseArgs)
- {
- var popupPosition = GetPopupPosition(mouseArgs);
- popup.HorizontalOffset = popupPosition.X;
- popup.VerticalOffset = popupPosition.Y;
+ return true;
}
/// Returns Popup position based on mouse position, in device independent units
@@ -182,17 +161,6 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
return positionInPixels.TransformFromDevice(this);
}
- Popup CreatePopup()
- {
- popup = new Popup();
- popup.Closed += (s, e) => popup = null;
- popup.AllowsTransparency = true;
- popup.PlacementTarget = this; // required for property inheritance
- popup.Placement = PlacementMode.Absolute;
- popup.StaysOpen = true;
- return popup;
- }
-
void TextEditorMouseHoverStopped(object sender, MouseEventArgs e)
{
if (toolTip != null) {
@@ -205,7 +173,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
void TextEditorMouseLeave(object sender, MouseEventArgs e)
{
- if (popup != null && !popup.IsMouseOver) {
+ if (popupToolTip != null && !popupToolTip.IsMouseOver) {
// do not close popup if mouse moved from editor to popup
TryCloseExistingPopup(false);
}
diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index 52dfddb00f..081c6f38e3 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -377,10 +377,6 @@
-
-
-
-
@@ -921,7 +917,6 @@
-
diff --git a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs
index 4df0ee1db7..d9bf53570c 100644
--- a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs
+++ b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs
@@ -64,24 +64,6 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
bbm.Condition = script;
bookmark = bbm;
break;
- case "PinBookmark":
- var pin = new PinBookmark(fileName, new Location(columnNumber, lineNumber));
- pin.Comment = v[4];
- pin.PinPosition =
- new Point
- {
- X = double.Parse(v[5], culture),
- Y = double.Parse(v[6], culture)
- };
-
- // pop-up nodes
- pin.SavedNodes = new System.Collections.Generic.List>();
- for (int i = 7; i < v.Length; i+=3) {
- pin.SavedNodes.Add(new Tuple(v[i], v[i+1], v[i+2]));
- }
-
- bookmark = pin;
- break;
default:
bookmark = new Bookmark(fileName, new Location(columnNumber, lineNumber));
break;
@@ -102,10 +84,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
} else if (bookmark is Debugging.BreakpointBookmark) {
b.Append("Breakpoint");
} else {
- if (bookmark is PinBookmark)
- b.Append("PinBookmark");
- else
- b.Append("Bookmark");
+ b.Append("Bookmark");
}
b.Append('|');
b.Append(bookmark.FileName);
@@ -136,27 +115,6 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
b.Append(bbm.Condition);
}
- if (bookmark is PinBookmark) {
- var pin = (PinBookmark)bookmark;
- b.Append('|');
- b.Append(pin.Comment ?? string.Empty);
-
- // popup position
- b.Append('|');
- b.Append(pin.PinPosition.Value.X);
- b.Append('|');
- b.Append(pin.PinPosition.Value.Y);
-
- //popup nodes
- foreach(var node in pin.Nodes) {
- b.Append('|');
- b.Append(node.ImageName);
- b.Append('|');
- b.Append(node.Name);
- b.Append('|');
- b.Append(node.Text);
- }
- }
return b.ToString();
} else {
return base.ConvertTo(context, culture, value, destinationType);
diff --git a/src/Main/Base/Project/Src/Editor/ITooltip.cs b/src/Main/Base/Project/Src/Editor/ITooltip.cs
index def96396f1..5e338ff1d5 100644
--- a/src/Main/Base/Project/Src/Editor/ITooltip.cs
+++ b/src/Main/Base/Project/Src/Editor/ITooltip.cs
@@ -6,30 +6,9 @@ using System.Windows;
namespace ICSharpCode.SharpDevelop.Editor
{
- ///
- /// Content of text editor tooltip (used as ),
- /// specifying whether it should be displayed in a WPF Popup.
- ///
public interface ITooltip
{
- ///
- /// If true, this ITooltip will be displayed in a WPF Popup.
- /// Otherwise it will be displayed in a WPF Tooltip.
- /// WPF Popups are (unlike WPF Tooltips) focusable.
- ///
- bool ShowAsPopup { get; }
-
- ///
- /// Closes this tooltip.
- ///
- /// True if close request is raised
- /// because of mouse click on some SharpDevelop GUI element.
- /// True if Close succeeded (that is, can close). False otherwise.
- bool Close(bool mouseClick);
-
- ///
- /// Occurs when this tooltip decides to close.
- ///
- event RoutedEventHandler Closed;
+ /// Should the tooltip close when the mouse moves away?
+ bool CloseOnHoverEnd { get; }
}
}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs
deleted file mode 100644
index 835aaa0e25..0000000000
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs
+++ /dev/null
@@ -1,20 +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 ICSharpCode.SharpDevelop.Bookmarks;
-
-namespace ICSharpCode.SharpDevelop.Debugging
-{
- public interface IPinDebuggerControl
- {
- void Open();
- void Close();
- PinBookmark Mark { get; set; }
- IEnumerable ItemsSource { set; }
- Point Location { get; set; }
- }
-}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs
deleted file mode 100644
index 6beb519b07..0000000000
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs
+++ /dev/null
@@ -1,37 +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.Media;
-
-namespace ICSharpCode.SharpDevelop.Debugging
-{
- ///
- /// Node that can be bound to .
- ///
- public interface ITreeNode
- {
- string ImageName { get; }
-
- string Name { get; }
-
- string Text { get; }
-
- bool CanSetText { get; }
-
- string Type { get; }
-
- ImageSource ImageSource { get; }
-
- Func> GetChildren { get; }
-
- IEnumerable VisualizerCommands { get; }
-
- bool HasVisualizerCommands { get; }
-
- bool IsPinned { get; set; }
-
- bool SetText(string newValue);
- }
-}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs
deleted file mode 100644
index a26defcd4b..0000000000
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs
+++ /dev/null
@@ -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.Collections.ObjectModel;
-using System.Collections.Specialized;
-using System.Windows;
-
-using ICSharpCode.Core;
-using ICSharpCode.NRefactory;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Bookmarks;
-using ICSharpCode.SharpDevelop.Debugging;
-
-namespace ICSharpCode.SharpDevelop.Bookmarks
-{
- public class PinBookmark : SDBookmark
- {
- string tooltip;
-
- public IPinDebuggerControl Popup { get; set; }
-
- public static readonly IImage PinImage = new ResourceServiceImage("Bookmarks.Pin");
-
- public PinBookmark(FileName fileName, Location location) : base(fileName, location)
- {
- Nodes = new ObservableCollection();
- IsVisibleInBookmarkPad = false;
- }
-
- ///
- /// Pin's position relative to the layer BUT ABSOLUTE TO THE SCREEN.
- ///
- public Nullable PinPosition { get; set; }
-
- ///
- /// Nodes inside the pin control.
- ///
- public ObservableCollection Nodes { get; set; }
-
- ///
- /// Image, Name, Text
- ///
- public List> SavedNodes { get; set; }
-
- public string Comment { get; set; }
-
- public override IImage Image {
- get {
- return PinImage;
- }
- }
-
- public string Tooltip {
- get { return tooltip; }
- set { tooltip = value; }
- }
-
- public override bool CanDragDrop {
- get { return true; }
- }
-
- public override void Drop(int lineNumber)
- {
- this.Location = new Location(ColumnNumber, lineNumber);
- }
- }
-
- public static class PinBookmarkExtensions
- {
- public static bool ContainsNode(this PinBookmark mark, ITreeNode node)
- {
- if (mark == null)
- throw new ArgumentNullException("mark is null");
- if (node == null)
- throw new ArgumentNullException("Node is null");
-
- foreach (var currentNode in mark.Nodes) {
- if (node.Name == currentNode.Name)
- return true;
- }
-
- return false;
- }
-
- public static void RemoveNode(this PinBookmark mark, ITreeNode node)
- {
- if (mark == null)
- throw new ArgumentNullException("mark is null");
- if (node == null)
- throw new ArgumentNullException("Node is null");
-
- foreach (var currentNode in mark.Nodes) {
- if (node.Name == currentNode.Name) {
- mark.Nodes.Remove(currentNode);
- return;
- }
- }
- }
- }
-}