diff --git a/data/resources/StringResources.resx b/data/resources/StringResources.resx
index 98bace9f94..ac4d13f4e8 100644
--- a/data/resources/StringResources.resx
+++ b/data/resources/StringResources.resx
@@ -4500,6 +4500,9 @@ has been changed externally do you want to reload it?
Unhandled exception has occured
+
+ Saved
+
Can't deserialize form. Possible reason: Initialize component method was changed manually.
diff --git a/data/resources/image/BitmapResources/BitmapResources-data/Icons.16x16.Refresh.png b/data/resources/image/BitmapResources/BitmapResources-data/Icons.16x16.Refresh.png
new file mode 100644
index 0000000000..51c3c653ce
Binary files /dev/null and b/data/resources/image/BitmapResources/BitmapResources-data/Icons.16x16.Refresh.png differ
diff --git a/data/resources/image/BitmapResources/BitmapResources.res b/data/resources/image/BitmapResources/BitmapResources.res
index eaf2aa2126..c409431afa 100644
--- a/data/resources/image/BitmapResources/BitmapResources.res
+++ b/data/resources/image/BitmapResources/BitmapResources.res
@@ -226,6 +226,7 @@ Icons.16x16.OpenFileIcon = BitmapResources-data\Icons.1
Icons.16x16.HtmlElements.FieldSetElement = BitmapResources-data\Icons.16x16.HtmlElements.FieldSetElement.png
Icons.16x16.SplitWindow = BitmapResources-data\Icons.16x16.SplitWindow.png
Icons.16x16.DeleteHistory = BitmapResources-data\Icons.16x16.DeleteHistory.png
+Icons.16x16.Refresh = BitmapResources-data\Icons.16x16.Refresh.png
#pad icons
PadIcons.ErrorList = PadIcons\ErrorList.png
@@ -347,6 +348,8 @@ Bookmarks.DisableAllBreakpoints = Bookmarks\DisableAllBreakpoi
Bookmarks.NextBreakpoint = Bookmarks\NextBreakpoint.png
Bookmarks.PrevBreakpoint = Bookmarks\PrevBreakpoint.png
+Bookmarks.Pin = Bookmarks\Pin.png
+
#backend icons
C#.ProjectIcon = backendicons\CSharp\SmallProject.png
C#.FileIcon = backendicons\CSharp\SmallFile.png
diff --git a/data/resources/image/BitmapResources/Bookmarks/Pin.png b/data/resources/image/BitmapResources/Bookmarks/Pin.png
new file mode 100644
index 0000000000..a93b751c8b
Binary files /dev/null and b/data/resources/image/BitmapResources/Bookmarks/Pin.png differ
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
index 3d4cc96e78..89209b2151 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
+++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
@@ -14,7 +14,14 @@
-
+
+
+
+
+
3.0
-
- 3.0
-
4.0
@@ -160,7 +157,26 @@
EditBreakpointScriptWindow.xaml
Code
+
+
+ DebuggerTooltipControl.xaml
+
+
+
+ PinCloseControl.xaml
+
+
+ PinDebuggerControl.xaml
+
+
+
+
+
+ VisualizerPicker.xaml
+
+
+
@@ -252,7 +268,6 @@
-
Component
@@ -304,6 +319,7 @@
+
@@ -354,6 +370,11 @@
+
+
+
+
+
@@ -375,6 +396,7 @@
False
+
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 8e793188cf..82ce6d4bd0 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
@@ -11,6 +11,7 @@ using System.Windows.Input;
using System.Windows.Media;
using Debugger.AddIn.TreeModel;
+using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.Pads.Controls
{
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
index 4b64b1caea..c2669f3ce7 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
@@ -7,6 +7,7 @@ using Debugger.AddIn.Pads.Controls;
using Debugger.AddIn.TreeModel;
using ICSharpCode.Core;
using Exception = System.Exception;
+using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
index e6e43021b2..5ff26e1fbc 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
@@ -15,6 +15,7 @@ using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Project;
using Exception = System.Exception;
+using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs
index 7e48745708..d5723c9858 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs
@@ -17,6 +17,7 @@ using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui.Pads;
using ICSharpCode.SharpDevelop.Project;
+using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn
{
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs
index 84fbf600ee..ce3906bf27 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs
@@ -1,17 +1,14 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
-using ICSharpCode.NRefactory;
using System;
-using System.Windows.Forms;
-using Aga.Controls.Tree;
-using Aga.Controls.Tree.NodeControls;
using Debugger.AddIn.TreeModel;
-using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
+using ICSharpCode.NRefactory;
+using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
- public class TextNode : Debugger.AddIn.TreeModel.TreeNode, ISetText
+ public class TextNode : TreeNode, ISetText
{
public TextNode(string text, SupportedLanguage language)
{
@@ -25,7 +22,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
}
- public new bool SetText(string text)
+ public override bool SetText(string text)
{
this.Text = text;
return true;
@@ -47,62 +44,4 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
IconImage = DebuggerResourceService.GetImage("Icons.16x16.Error");
}
}
-
- public sealed class WatchItemName: NodeTextBox {
- public WatchItemName()
- {
- this.EditEnabled = true;
- this.EditOnClick = true;
- }
- protected override bool CanEdit(TreeNodeAdv node)
- {
- TreeNode content = ((TreeViewVarNode)node).Content;
- return (content is ISetText) && ((ISetText)content).CanSetText;
- }
- public override object GetValue(TreeNodeAdv node)
- {
- if (node is TreeViewVarNode) {
- return ((TreeViewVarNode)node).Content.Name;
- } else {
- // Happens during incremental search
- return base.GetValue(node);
- }
- }
- public override void SetValue(TreeNodeAdv node, object value)
- {
- if (string.IsNullOrEmpty(value as string))
- MessageBox.Show("You can not set name to an empty string!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- else
- {
-// if (((TreeViewVarNode)node).Content is ExpressionNode) {
-// WatchPad.Instance.Watches.RemoveAll(item => item.Name == ((ExpressionNode)((TreeViewVarNode)node).Content).Name);
-// ((ExpressionNode)((TreeViewVarNode)node).Content).Name = value.ToString();
-// } else {
-// if (((TreeViewVarNode)node).Content is TextNode) {
-// WatchPad.Instance.Watches.RemoveAll(item => item.Name == ((TextNode)((TreeViewVarNode)node).Content).Name);
-// ((TextNode)((TreeViewVarNode)node).Content).Name = value.ToString();
-// }
-// }
-//
-// WatchPad.Instance.Watches.Add(new TextNode(value as string, SupportedLanguage.CSharp));
- }
- }
- public override void MouseDown(TreeNodeAdvMouseEventArgs args)
- {
- if (args.Node == null) {
- base.MouseDown(args);
- return;
- }
- TreeNode content = ((TreeViewVarNode)args.Node).Content;
- if (content is IContextMenu && args.Button == MouseButtons.Right) {
- ContextMenuStrip menu = ((IContextMenu)content).GetContextMenu();
- if (menu != null) {
- menu.Show(args.Node.Tree, args.Location);
- args.Handled = true;
- }
- } else {
- base.MouseDown(args);
- }
- }
- }
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
index 5e62a70437..70cb6d607e 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
@@ -11,7 +11,7 @@ using System.Text;
using System.Windows.Forms;
using Debugger;
-using Debugger.AddIn;
+using Debugger.AddIn.Tooltips;
using Debugger.AddIn.TreeModel;
using Debugger.Interop.CorPublish;
using ICSharpCode.Core;
@@ -400,12 +400,36 @@ namespace ICSharpCode.SharpDevelop.Services
/// Gets the tooltip control that shows the value of given variable.
/// Return null if no tooltip is available.
///
- public object GetTooltipControl(string variableName)
+ public object GetTooltipControl(Location logicalPosition, string variableName)
{
try {
var tooltipExpression = GetExpression(variableName);
- ExpressionNode expressionNode = new ExpressionNode(ExpressionNode.GetImageForLocalVariable(), variableName, tooltipExpression);
- return new DebuggerTooltipControl(expressionNode);
+ string imageName;
+ var image = ExpressionNode.GetImageForLocalVariable(out imageName);
+ ExpressionNode expressionNode = new ExpressionNode(image, variableName, tooltipExpression);
+ expressionNode.ImageName = imageName;
+ return new DebuggerTooltipControl(logicalPosition, expressionNode);
+ } catch (GetValueException) {
+ return null;
+ }
+ }
+
+ public ITreeNode GetNode(string variable, string currentImageName = null)
+ {
+ try {
+ var expression = GetExpression(variable);
+ string imageName;
+ IImage image;
+ if (string.IsNullOrEmpty(currentImageName)) {
+ image = ExpressionNode.GetImageForLocalVariable(out imageName);
+ }
+ else {
+ image = new ResourceServiceImage(currentImageName);
+ imageName = currentImageName;
+ }
+ ExpressionNode expressionNode = new ExpressionNode(image, variable, expression);
+ expressionNode.ImageName = imageName;
+ return expressionNode;
} catch (GetValueException) {
return null;
}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerPopup.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs
similarity index 88%
rename from src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerPopup.cs
rename to src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs
index 2f045b5450..87529f37e1 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerPopup.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerPopup.cs
@@ -8,20 +8,22 @@ using System.Windows.Controls.Primitives;
using System.Windows.Input;
using ICSharpCode.Core;
+using ICSharpCode.NRefactory;
+using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Gui;
-namespace ICSharpCode.SharpDevelop.Debugging
+namespace Debugger.AddIn.Tooltips
{
///
/// Popup containing .
///
public class DebuggerPopup : Popup
{
- private DebuggerTooltipControl contentControl;
+ internal DebuggerTooltipControl contentControl;
- public DebuggerPopup(DebuggerTooltipControl parentControl)
+ public DebuggerPopup(DebuggerTooltipControl parentControl, Location logicalPosition, bool showPins = true)
{
- this.contentControl = new DebuggerTooltipControl(parentControl);
+ this.contentControl = new DebuggerTooltipControl(parentControl, logicalPosition, showPins);
this.contentControl.containingPopup = this;
this.Child = this.contentControl;
this.IsLeaf = false;
@@ -63,7 +65,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
public IEnumerable ItemsSource
{
get { return this.contentControl.ItemsSource; }
- set { this.contentControl.ItemsSource = value; }
+ set { this.contentControl.SetItemsSource(value); }
}
private bool isLeaf;
@@ -97,4 +99,4 @@ namespace ICSharpCode.SharpDevelop.Debugging
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
new file mode 100644
index 0000000000..2d2a44abba
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 0000000000..b3fbf47370
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
@@ -0,0 +1,407 @@
+// 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.Globalization;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+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;
+using Services.Debugger.Tooltips;
+
+namespace Debugger.AddIn.Tooltips
+{
+ ///
+ /// Default Control used as content of SharpDevelop debugger tooltips.
+ ///
+ public partial class DebuggerTooltipControl : UserControl, ITooltip
+ {
+ private const double ChildPopupOpenXOffet = 16;
+ private const double ChildPopupOpenYOffet = 15;
+ private const int InitialItemsCount = 12;
+ private const int VisibleItemsCount = 11;
+
+ private bool showPins = true;
+ private LazyItemsControl lazyGrid;
+ private IEnumerable itemsSource;
+ readonly Location logicalPosition;
+
+ public DebuggerTooltipControl(Location logicalPosition)
+ {
+ this.logicalPosition = logicalPosition;
+ InitializeComponent();
+
+ Loaded += new RoutedEventHandler(OnLoaded);
+ }
+
+ public DebuggerTooltipControl(Location logicalPosition, ITreeNode node)
+ : this(logicalPosition, new ITreeNode[] { node })
+ {
+
+ }
+
+ public DebuggerTooltipControl(Location logicalPosition, IEnumerable nodes)
+ : this(logicalPosition)
+ {
+ this.itemsSource = nodes;
+ }
+
+ public DebuggerTooltipControl(DebuggerTooltipControl parentControl, Location logicalPosition, bool showPins = true)
+ : this(logicalPosition)
+ {
+ this.parentControl = parentControl;
+ this.showPins = showPins;
+ }
+
+ 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()
+ {
+ if (this.Closed != null) {
+ this.Closed(this, new RoutedEventArgs());
+ }
+ }
+
+ 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
+ ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider;
+ var editor = provider.TextEditor;
+ if (editor != null) {
+ var pin = BookmarkManager.Bookmarks.Find(
+ b => b is PinBookmark &&
+ b.Location.Line == logicalPosition.Line &&
+ b.FileName == editor.FileName) as PinBookmark;
+
+ 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;
+ }
+ }
+
+ //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;
+ }
+ }
+ }
+
+ private void btnExpander_Click(object sender, RoutedEventArgs 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);
+ 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;
+ this.childPopup.ItemsSource = clickedNode.ChildNodes;
+ this.childPopup.Open();
+ } else {
+ CloseChildPopups();
+ }
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Saved Adorner
+
+ class SavedAdorner : Adorner
+ {
+ public SavedAdorner(UIElement adornedElement) : base(adornedElement)
+ {
+ Loaded += delegate { Show(); };
+ }
+
+ 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));
+ }
+
+ 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);
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/LazyItemsControl.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/LazyItemsControl.cs
similarity index 97%
rename from src/Main/Base/Project/Src/Services/Debugger/Tooltips/LazyItemsControl.cs
rename to src/AddIns/Debugger/Debugger.AddIn/Tooltips/LazyItemsControl.cs
index d769bfafb8..f4af8a0aa7 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/LazyItemsControl.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/LazyItemsControl.cs
@@ -5,7 +5,9 @@ using System;
using System.Collections.Generic;
using System.Windows.Controls;
-namespace ICSharpCode.SharpDevelop.Debugging
+using ICSharpCode.SharpDevelop;
+
+namespace Debugger.AddIn.Tooltips
{
///
/// ItemsControl wrapper that takes VirtualizingIEnumerable as source,
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml
new file mode 100644
index 0000000000..c2fc077e1e
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 0000000000..d417c5ba38
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinCloseControl.xaml.cs
@@ -0,0 +1,74 @@
+// 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
new file mode 100644
index 0000000000..a55dce2e3e
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinControlsDictionary.xaml
@@ -0,0 +1,337 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 0000000000..7752bc8bb0
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 0000000000..6dd6e313d3
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs
@@ -0,0 +1,380 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Bookmarks;
+using ICSharpCode.SharpDevelop.Debugging;
+using ICSharpCode.SharpDevelop.Editor;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Services;
+using Services.Debugger.Tooltips;
+
+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 buton
+
+ 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)
+ {
+ 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;
+ this.childPopup.ItemsSource = clickedNode.ChildNodes;
+ this.childPopup.Open();
+ } else {
+
+ }
+ }
+
+ void PinDebuggerControl_Closed(object sender, EventArgs e)
+ {
+ if (expandedButton != null && expandedButton.IsChecked.GetValueOrDefault(false))
+ expandedButton.IsChecked = false;
+ }
+
+ void BtnExpander_Unchecked(object sender, RoutedEventArgs e)
+ {
+ CloseChildPopups();
+ }
+
+ #endregion
+
+ #region PinCloseControl
+
+ void PinCloseControl_Closed(object sender, EventArgs e)
+ {
+ BookmarkManager.RemoveMark(Mark);
+ Close();
+ }
+
+ void PinCloseControl_PinningChanged(object sender, EventArgs e)
+ {
+ if (this.PinCloseControl.IsChecked) {
+ BookmarkManager.RemoveMark(Mark);
+ }
+ else {
+ if(BookmarkManager.Bookmarks.Contains(Mark))
+ BookmarkManager.RemoveMark(Mark);
+
+ BookmarkManager.AddMark(Mark);
+ }
+ }
+
+ void PinCloseControl_ShowingComment(object sender, ShowingCommentEventArgs e)
+ {
+ ShowComment(e.ShowComment);
+ }
+
+ void AnimateCloseControl(bool show)
+ {
+ DoubleAnimation animation = new DoubleAnimation();
+ animation.From = show ? 0 : 1;
+ animation.To = show ? 1 : 0;
+ animation.BeginTime = new TimeSpan(0, 0, show ? 0 : 1);
+ animation.Duration = new Duration(TimeSpan.FromMilliseconds(500));
+ animation.SetValue(Storyboard.TargetProperty, this.PinCloseControl);
+ animation.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath(Rectangle.OpacityProperty));
+
+ Storyboard board = new Storyboard();
+ board.Children.Add(animation);
+
+ board.Begin(this);
+ }
+
+ #endregion
+
+ void OnBookmarkRemoved(object sender, BookmarkEventArgs e)
+ {
+ // if the bookmark was removed from pressing the button, return
+ if (this.PinCloseControl.IsChecked)
+ return;
+
+ if (e.Bookmark is PinBookmark) {
+ var pin = (PinBookmark)e.Bookmark;
+ if (pin.Location == Mark.Location && pin.FileName == Mark.FileName) {
+ Close();
+ }
+ }
+ }
+
+ void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ this.CommentTextBox.Text = Mark.Comment;
+ }
+
+ #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
+
+ void RefreshContentImage_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ // refresh content
+ ITreeNode node = ((Image)sender).DataContext as ITreeNode;
+
+ if (!DebuggerService.IsDebuggerStarted)
+ return;
+
+ var resultNode = currentDebugger.GetNode(node.FullName, 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.CompareTo(node) == 0)
+ observable.Add(resultNode);
+ else
+ observable.Add(item);
+ });
+
+ Mark.Nodes = observable;
+ // update UI
+ var newSource = new VirtualizingIEnumerable(observable);
+ lazyGrid.ItemsSource = newSource;
+ lazyExpandersGrid.ItemsSource = newSource;
+ }
+
+ #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
new file mode 100644
index 0000000000..f0a3e2a22e
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinLayer.cs
@@ -0,0 +1,225 @@
+// 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.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 ContextActionsControl.SearchVisualTree(root);
+ }
+
+ static T TryFindParent(DependencyObject child) where T : DependencyObject
+ {
+ if (child is T) return child as T;
+
+ DependencyObject parentObject = GetParentObject(child);
+ if (parentObject == null) return null;
+
+ var parent = parentObject as T;
+ if (parent != null && parent is T)
+ {
+ return parent;
+ }
+ else
+ {
+ return TryFindParent(parentObject);
+ }
+ }
+
+ static DependencyObject GetParentObject(DependencyObject child)
+ {
+ if (child == null) return null;
+
+ ContentElement contentElement = child as ContentElement;
+ if (contentElement != null)
+ {
+ DependencyObject parent = ContentOperations.GetParent(contentElement);
+ if (parent != null) return parent;
+
+ FrameworkContentElement fce = contentElement as FrameworkContentElement;
+ return fce != null ? fce.Parent : null;
+ }
+
+ FrameworkElement frameworkElement = child as FrameworkElement;
+ if (frameworkElement != null)
+ {
+ DependencyObject parent = frameworkElement.Parent;
+ if (parent != null) return parent;
+ }
+
+ return VisualTreeHelper.GetParent(child);
+ }
+
+ #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
new file mode 100644
index 0000000000..fb5e0d5e47
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs
@@ -0,0 +1,118 @@
+// 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;
+using Services.Debugger.Tooltips;
+
+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) {
+ string imageName = !string.IsNullOrEmpty(tuple.Item1) ? tuple.Item1 : "Icons.16x16.Field";
+ var node = new Debugger.AddIn.TreeModel.SavedTreeNode(
+ new ResourceServiceImage(imageName),
+ tuple.Item2,
+ tuple.Item3);
+ node.ImageName = imageName;
+ nodes.Add(node);
+ }
+
+ pin.SavedNodes.Clear();
+ pin.Popup.ItemsSource = nodes;
+ pin.Nodes = nodes;
+
+ pinLayer.Pin((PinDebuggerControl)pin.Popup);
+ }
+ }
+
+ public void ClosePins(ITextEditor editor)
+ {
+ // save pins
+ var pins = BookmarkManager.Bookmarks.FindAll(
+ b => b is PinBookmark && b.FileName == editor.FileName);
+
+ foreach (var bookmark in pins) {
+ var pin = (PinBookmark)bookmark;
+ if (!pin.PinPosition.HasValue)
+ pin.PinPosition = pin.Popup.Location;
+
+ // nodes
+ if (pin.SavedNodes == null)
+ pin.SavedNodes = new System.Collections.Generic.List>();
+
+ foreach (var node in pin.Nodes) {
+ pin.SavedNodes.Add(
+ new Tuple(
+ "Icons.16x16.Field",
+ node.FullName,
+ node.Text));
+ }
+
+ pinLayer.Unpin((PinDebuggerControl)pin.Popup);
+ pin.Popup = null;
+ }
+ }
+
+ public static PinLayer GetPinlayer(ITextEditor editor) {
+ var textEditor = editor.GetService(typeof(TextEditor)) as TextEditor;
+ if (textEditor != null) {
+ return textEditor.TextArea.TextView.Layers[3] as PinLayer;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/VirtualizingIEnumerable.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VirtualizingIEnumerable.cs
similarity index 97%
rename from src/Main/Base/Project/Src/Services/Debugger/Tooltips/VirtualizingIEnumerable.cs
rename to src/AddIns/Debugger/Debugger.AddIn/Tooltips/VirtualizingIEnumerable.cs
index c18209b02f..ca51500f2e 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/VirtualizingIEnumerable.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VirtualizingIEnumerable.cs
@@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-namespace ICSharpCode.SharpDevelop.Debugging
+namespace Debugger.AddIn.Tooltips
{
///
/// A wrapper around IEnumerable<T> with AddNextItems method for pulling additional items
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/VisualizerPicker.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs
similarity index 95%
rename from src/Main/Base/Project/Src/Services/Debugger/Tooltips/VisualizerPicker.cs
rename to src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs
index 7b418a5429..82606236aa 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/VisualizerPicker.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs
@@ -1,13 +1,15 @@
// 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 ICSharpCode.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
-namespace ICSharpCode.SharpDevelop.Debugging
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Debugging;
+
+namespace Debugger.AddIn.Tooltips
{
///
/// Control displaying and executing visualizer commands.
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/VisualizerPicker.xaml b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.xaml
similarity index 98%
rename from src/Main/Base/Project/Src/Services/Debugger/Tooltips/VisualizerPicker.xaml
rename to src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.xaml
index ecd25b595b..41abaf39d7 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/VisualizerPicker.xaml
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.xaml
@@ -1,7 +1,7 @@
+ xmlns:debugging="clr-namespace:Debugger.AddIn.Tooltips">
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/magnifier.png b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/magnifier.png
similarity index 100%
rename from src/Main/Base/Project/Src/Services/Debugger/Tooltips/magnifier.png
rename to src/AddIns/Debugger/Debugger.AddIn/Tooltips/magnifier.png
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Adapters/TreeViewVarNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Adapters/TreeViewVarNode.cs
index e329a560e8..da531692d9 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Adapters/TreeViewVarNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/Adapters/TreeViewVarNode.cs
@@ -10,6 +10,7 @@ using System.Windows.Forms;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using ICSharpCode.Core;
+using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
namespace Debugger.AddIn.TreeModel
{
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs
index 19c80d87b5..814b3ce198 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Text;
using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel
{
@@ -84,7 +85,11 @@ namespace Debugger.AddIn.TreeModel
// The whole array is small - just add all elements as childs
if (bounds.TotalElementCount <= MaxElementCount) {
foreach(int[] indices in bounds.Indices) {
- yield return new ExpressionNode(ExpressionNode.GetImageForArrayIndexer(), GetName(indices), arrayTarget.AppendIndexer(indices));
+ string imageName;
+ var image = ExpressionNode.GetImageForArrayIndexer(out imageName);
+ var expression = new ExpressionNode(image, GetName(indices), arrayTarget.AppendIndexer(indices));
+ expression.ImageName = imageName;
+ yield return expression;
}
yield break;
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs
index b5e3cea2c5..08b296f393 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs
@@ -11,6 +11,7 @@ using ICSharpCode.Core;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Services;
+using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel
{
@@ -84,7 +85,11 @@ namespace Debugger.AddIn.TreeModel
{
List nodes = new List();
foreach(MemberInfo memberInfo in members) {
- nodes.Add(new ExpressionNode(ExpressionNode.GetImageForMember((IDebugMemberInfo)memberInfo), memberInfo.Name, expression.AppendMemberReference((IDebugMemberInfo)memberInfo)));
+ string imageName;
+ var image = ExpressionNode.GetImageForMember((IDebugMemberInfo)memberInfo, out imageName);
+ var exp = new ExpressionNode(image, memberInfo.Name, expression.AppendMemberReference((IDebugMemberInfo)memberInfo));
+ exp.ImageName = imageName;
+ nodes.Add(exp);
}
nodes.Sort();
return nodes;
@@ -113,7 +118,11 @@ namespace Debugger.AddIn.TreeModel
yield return new TreeNode(null, "(empty)", null, null, null);
} else {
for(int i = 0; i < count; i++) {
- yield return new ExpressionNode(ExpressionNode.GetImageForArrayIndexer(), "[" + i + "]", targetObject.AppendIndexer(i));
+ string imageName;
+ var image = ExpressionNode.GetImageForArrayIndexer(out imageName);
+ var expression = new ExpressionNode(image, "[" + i + "]", targetObject.AppendIndexer(i));
+ expression.ImageName = imageName;
+ yield return expression;
}
}
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs
index fcb53a93a1..b98e3edd52 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs
@@ -4,22 +4,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
-using System.Drawing;
using System.Globalization;
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.Core.WinForms;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
-using ICSharpCode.SharpDevelop.Gui.Pads;
using ICSharpCode.SharpDevelop.Services;
+using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
namespace Debugger.AddIn.TreeModel
{
@@ -34,10 +31,10 @@ namespace Debugger.AddIn.TreeModel
Expression expression;
bool canSetText;
GetValueException error;
-
+ string fullName;
string fullText;
- public bool Evaluated {
+ public bool Evaluated {
get { return evaluated; }
set { evaluated = value; }
}
@@ -60,7 +57,7 @@ namespace Debugger.AddIn.TreeModel
}
}
- public string FullText {
+ public string FullText {
get { return fullText; }
}
@@ -77,6 +74,14 @@ namespace Debugger.AddIn.TreeModel
}
}
+ public override string FullName {
+ get {
+ if (!evaluated) EvaluateExpression();
+
+ return this.expression.PrettyPrint() ?? Name.Trim();
+ }
+ }
+
public override string Type {
get {
if (!evaluated) EvaluateExpression();
@@ -96,7 +101,7 @@ namespace Debugger.AddIn.TreeModel
if (!evaluated) EvaluateExpression();
return base.HasChildNodes;
}
- }
+ }
/// Used to determine available VisualizerCommands
private DebugType expressionType;
@@ -227,7 +232,7 @@ namespace Debugger.AddIn.TreeModel
.Replace("\a", "\\a")
.Replace("\f", "\\f")
.Replace("\v", "\\v")
- .Replace("\"", "\\\"");
+ .Replace("\"", "\\\"");
}
string FormatInteger(object i)
@@ -287,6 +292,8 @@ namespace Debugger.AddIn.TreeModel
public override bool SetText(string newText)
{
+ string fullName = FullName;
+
Value val = null;
try {
val = this.Expression.Evaluate(WindowsDebugger.DebuggedProcess);
@@ -316,27 +323,31 @@ namespace Debugger.AddIn.TreeModel
return false;
}
- public static IImage GetImageForThis()
+ public static IImage GetImageForThis(out string imageName)
{
- return DebuggerResourceService.GetImage("Icons.16x16.Parameter");
+ imageName = "Icons.16x16.Parameter";
+ return DebuggerResourceService.GetImage(imageName);
}
- public static IImage GetImageForParameter()
+ public static IImage GetImageForParameter(out string imageName)
{
- return DebuggerResourceService.GetImage("Icons.16x16.Parameter");
+ imageName = "Icons.16x16.Parameter";
+ return DebuggerResourceService.GetImage(imageName);
}
- public static IImage GetImageForLocalVariable()
+ public static IImage GetImageForLocalVariable(out string imageName)
{
- return DebuggerResourceService.GetImage("Icons.16x16.Local");
+ imageName = "Icons.16x16.Local";
+ return DebuggerResourceService.GetImage(imageName);
}
- public static IImage GetImageForArrayIndexer()
+ public static IImage GetImageForArrayIndexer(out string imageName)
{
- return DebuggerResourceService.GetImage("Icons.16x16.Field");
+ imageName = "Icons.16x16.Field";
+ return DebuggerResourceService.GetImage(imageName);
}
- public static IImage GetImageForMember(IDebugMemberInfo memberInfo)
+ public static IImage GetImageForMember(IDebugMemberInfo memberInfo, out string imageName)
{
string name = string.Empty;
if (memberInfo.IsPublic) {
@@ -356,15 +367,17 @@ namespace Debugger.AddIn.TreeModel
} else {
throw new DebuggerException("Unknown member type " + memberInfo.GetType().FullName);
}
- return DebuggerResourceService.GetImage("Icons.16x16." + name);
+
+ imageName = "Icons.16x16." + name;
+ return DebuggerResourceService.GetImage(imageName);
}
// public ContextMenuStrip GetContextMenu()
// {
// if (this.Error != null) return GetErrorContextMenu();
-//
+//
// ContextMenuStrip menu = new ContextMenuStrip();
-//
+//
// ToolStripMenuItem copyItem;
// copyItem = new ToolStripMenuItem();
// copyItem.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CopyToClipboard");
@@ -372,7 +385,7 @@ namespace Debugger.AddIn.TreeModel
// copyItem.Click += delegate {
// ClipboardWrapper.SetText(fullText);
// };
-
+
// ToolStripMenuItem hexView;
// hexView = new ToolStripMenuItem();
// hexView.Text = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.ShowInHexadecimal");
@@ -386,12 +399,12 @@ namespace Debugger.AddIn.TreeModel
// if (WatchPad.Instance != null)
// WatchPad.Instance.RefreshPad();
// };
-
+
// menu.Items.AddRange(new ToolStripItem[] {
// copyItem,
// //hexView
// });
-//
+//
// return menu;
// }
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/SavedTreeNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/SavedTreeNode.cs
new file mode 100644
index 0000000000..d81712624b
--- /dev/null
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/SavedTreeNode.cs
@@ -0,0 +1,30 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using ICSharpCode.SharpDevelop;
+
+namespace Debugger.AddIn.TreeModel
+{
+ ///
+ /// Description of SavedTreeNode.
+ ///
+ public class SavedTreeNode : TreeNode
+ {
+ public override bool CanSetText {
+ get { return true; }
+ }
+
+ public SavedTreeNode(IImage image, string fullname, string text)
+ {
+ base.IconImage = image;
+ FullName = fullname;
+ Text = text;
+ }
+
+ public override bool SetText(string newValue) {
+ Text = newValue;
+ return false;
+ }
+ }
+}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs
index 187fe31e5b..99affbdabe 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs
@@ -4,6 +4,7 @@
using Debugger.MetaData;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel
{
@@ -26,10 +27,18 @@ namespace Debugger.AddIn.TreeModel
IEnumerable LazyGetChildNodes()
{
foreach(DebugParameterInfo par in stackFrame.MethodInfo.GetParameters()) {
- yield return new ExpressionNode(ExpressionNode.GetImageForParameter(), par.Name, par.GetExpression());
+ string imageName;
+ var image = ExpressionNode.GetImageForParameter(out imageName);
+ var expression = new ExpressionNode(image, par.Name, par.GetExpression());
+ expression.ImageName = imageName;
+ yield return expression;
}
foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(this.StackFrame.IP)) {
- yield return new ExpressionNode(ExpressionNode.GetImageForLocalVariable(), locVar.Name, locVar.GetExpression());
+ string imageName;
+ var image = ExpressionNode.GetImageForLocalVariable(out imageName);
+ var expression = new ExpressionNode(image, locVar.Name, locVar.GetExpression());
+ expression.ImageName = imageName;
+ yield return expression;
}
if (stackFrame.Thread.CurrentException != null) {
yield return new ExpressionNode(null, "__exception", new IdentifierExpression("__exception"));
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs
index ca328cd1ae..a02329c1b1 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs
@@ -17,10 +17,11 @@ namespace Debugger.AddIn.TreeModel
/// A node in the variable tree.
/// The node is imutable.
///
- public class TreeNode: IComparable, ITreeNode
+ public class TreeNode : ITreeNode
{
IImage iconImage = null;
string name = string.Empty;
+ string imageName = string.Empty;
string text = string.Empty;
string type = string.Empty;
IEnumerable childNodes = null;
@@ -56,6 +57,16 @@ namespace Debugger.AddIn.TreeModel
set { name = value; }
}
+ public string ImageName {
+ get { return imageName; }
+ set { imageName = value; }
+ }
+
+ public virtual string FullName {
+ get { return name; }
+ set { name = value; }
+ }
+
public virtual string Text
{
get { return text; }
@@ -96,6 +107,8 @@ namespace Debugger.AddIn.TreeModel
}
}
+ public bool IsPinned { get; set; }
+
public TreeNode()
{
}
@@ -109,13 +122,13 @@ namespace Debugger.AddIn.TreeModel
this.childNodes = childNodes;
}
- public int CompareTo(TreeNode other)
+ public int CompareTo(ITreeNode other)
{
- return this.Name.CompareTo(other.Name);
+ return this.FullName.CompareTo(other.FullName);
}
public virtual bool SetText(string newValue) {
return false;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/ICorDebug.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/ICorDebug.cs
index 7ff9328f62..cfd1a5dc56 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/ICorDebug.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/ICorDebug.cs
@@ -5,6 +5,7 @@ using Debugger.Interop.CorDebug;
using System;
using System.Collections.Generic;
using Debugger.MetaData;
+using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel
{
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IEnumerableNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IEnumerableNode.cs
index dccffc428e..eb316a3f7f 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IEnumerableNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/IEnumerableNode.cs
@@ -1,12 +1,11 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
-using Debugger.MetaData;
using System;
-using System.Collections.Generic;
-using System.Linq;
using Debugger.AddIn.Visualizers.Utils;
+using Debugger.MetaData;
using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel
{
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
index b467774c84..2875913005 100755
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
@@ -13,6 +13,8 @@ using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
+using System.Windows.Media;
+
using ICSharpCode.AvalonEdit.AddIn.Options;
using ICSharpCode.AvalonEdit.AddIn.Snippets;
using ICSharpCode.AvalonEdit.Editing;
@@ -323,6 +325,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
{
popup = new Popup();
popup.Closed += PopupClosed;
+ popup.AllowsTransparency = true;
popup.PlacementTarget = this; // required for property inheritance
popup.Placement = PlacementMode.Absolute;
popup.StaysOpen = true;
diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index 1f461b2ba4..4522d5ff81 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -312,16 +312,10 @@
-
-
- DebuggerTooltipControl.xaml
- Code
-
+
-
-
-
+
@@ -385,9 +379,6 @@
-
- Never
-
@@ -850,6 +841,7 @@
+
@@ -887,8 +879,6 @@
-
-
diff --git a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs
index 6f43fd5ab3..7114dc41a7 100644
--- a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs
+++ b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs
@@ -5,9 +5,11 @@ using System;
using System.ComponentModel;
using System.Globalization;
using System.Text;
+using System.Windows;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
+using Services.Debugger.Tooltips;
namespace ICSharpCode.SharpDevelop.Bookmarks
{
@@ -30,14 +32,6 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
FileName fileName = FileName.Create(v[1]);
int lineNumber = int.Parse(v[2], culture);
int columnNumber = int.Parse(v[3], culture);
- Debugging.BreakpointAction action = Debugging.BreakpointAction.Break;
- string scriptLanguage = "";
- string script = "";
- if (v[0] == "Breakpoint") {
- action = (Debugging.BreakpointAction)Enum.Parse(typeof(Debugging.BreakpointAction), v[5]);
- scriptLanguage = v[6];
- script = v[7];
- }
if (lineNumber < 0)
return null;
if (columnNumber < 0)
@@ -45,10 +39,38 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
SDBookmark bookmark;
switch (v[0]) {
case "Breakpoint":
+ Debugging.BreakpointAction action = Debugging.BreakpointAction.Break;
+ string scriptLanguage = "";
+ string script = "";
+ action = (Debugging.BreakpointAction)Enum.Parse(typeof(Debugging.BreakpointAction), v[5]);
+ scriptLanguage = v[6];
+ script = v[7];
+
var bbm = new Debugging.BreakpointBookmark(fileName, new Location(columnNumber, lineNumber), action, scriptLanguage, script);
bbm.IsEnabled = bool.Parse(v[4]);
+ bbm.Action = action;
+ bbm.ScriptLanguage = scriptLanguage;
+ 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 SDBookmark(fileName, new Location(columnNumber, lineNumber));
break;
@@ -67,7 +89,10 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
if (bookmark is Debugging.BreakpointBookmark) {
b.Append("Breakpoint");
} else {
- b.Append("Bookmark");
+ if (bookmark is PinBookmark)
+ b.Append("PinBookmark");
+ else
+ b.Append("Bookmark");
}
b.Append('|');
b.Append(bookmark.FileName);
@@ -88,6 +113,27 @@ 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.FullName);
+ 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/Services/Debugger/DebuggerService.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
index 168c3f751c..30aa00cb4e 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
@@ -282,7 +282,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
if (toolTipText != null) {
if (debuggerCanShowValue && currentDebugger != null) {
- object toolTip = currentDebugger.GetTooltipControl(expressionResult.Expression);
+ object toolTip = currentDebugger.GetTooltipControl(e.LogicalPosition, expressionResult.Expression);
if (toolTip != null)
e.SetToolTip(toolTip);
else
diff --git a/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs b/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs
index f01904145e..448d77676b 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
@@ -126,7 +127,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
/// Gets the tooltip control that shows the value of given variable.
/// Return null if no tooltip is available.
///
- public object GetTooltipControl(string variable)
+ public object GetTooltipControl(Location logicalPosition, string variable)
{
return null;
}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs b/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs
index 553bf45550..734b355f4b 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Debugging
@@ -73,7 +74,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
/// Gets the tooltip control that shows the value of given variable.
/// Return null if no tooltip is available.
///
- object GetTooltipControl(string variable);
+ object GetTooltipControl(Location logicalPosition, string variable);
///
/// Queries the debugger whether it is possible to set the instruction pointer to a given position.
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml
deleted file mode 100644
index f9af4fca25..0000000000
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml
+++ /dev/null
@@ -1,205 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml.cs
deleted file mode 100644
index 7fe7c0ee6d..0000000000
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml.cs
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using ICSharpCode.SharpDevelop.Editor;
-
-namespace ICSharpCode.SharpDevelop.Debugging
-{
- ///
- /// Default Control used as content of SharpDevelop debugger tooltips.
- ///
- public partial class DebuggerTooltipControl : UserControl, ITooltip
- {
- private readonly double ChildPopupOpenXOffet = 16;
- private readonly double ChildPopupOpenYOffet = 15;
- private readonly int InitialItemsCount = 12;
- private readonly int VisibleItemsCount = 11;
-
- public DebuggerTooltipControl()
- {
- InitializeComponent();
- }
-
- public DebuggerTooltipControl(ITreeNode node)
- : this(new ITreeNode[] { node })
- {
- }
-
- public DebuggerTooltipControl(IEnumerable nodes)
- : this()
- {
- this.ItemsSource = nodes;
- }
-
- public DebuggerTooltipControl(DebuggerTooltipControl parentControl)
- : this()
- {
- this.parentControl = parentControl;
- }
-
- public event RoutedEventHandler Closed;
- protected void OnClosed()
- {
- if (this.Closed != null) {
- this.Closed(this, new RoutedEventArgs());
- }
- }
-
- private LazyItemsControl lazyGrid;
-
- private IEnumerable itemsSource;
- public IEnumerable ItemsSource
- {
- get { return this.itemsSource; }
- set
- {
- this.itemsSource = value;
- this.lazyGrid = new LazyItemsControl(this.dataGrid, InitialItemsCount);
- lazyGrid.ItemsSource = new VirtualizingIEnumerable(value);
- 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;
- }
- }
-
- }
-
- ///
- public bool ShowAsPopup
- {
- get
- {
- return true;
- }
- }
-
- ///
- public bool Close(bool mouseClick)
- {
- if (mouseClick || (!mouseClick && !isChildExpanded)) {
- CloseChildPopups();
- return true;
- } else {
- return false;
- }
- }
-
- DebuggerPopup childPopup { get; set; }
- 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;
- }
- }
- }
-
- private void btnExpander_Click(object sender, RoutedEventArgs 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);
- 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;
- this.childPopup.ItemsSource = clickedNode.ChildNodes;
- this.childPopup.Open();
- } else {
- CloseChildPopups();
- }
- }
-
- 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);
- }
- }
-}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs
new file mode 100644
index 0000000000..b3e531820c
--- /dev/null
+++ b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs
@@ -0,0 +1,20 @@
+// 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.Debugging;
+
+namespace Services.Debugger.Tooltips
+{
+ 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
index abc88cdd3b..59762e5870 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs
@@ -10,12 +10,18 @@ namespace ICSharpCode.SharpDevelop.Debugging
///
/// Node that can be bound to .
///
- public interface ITreeNode
+ public interface ITreeNode : IComparable
{
string Name { get; }
+ string FullName { get; }
+
+ string ImageName { get; }
+
string Text { get; }
+ bool CanSetText { get; }
+
string Type { get; }
ImageSource ImageSource { get; }
@@ -27,5 +33,9 @@ namespace ICSharpCode.SharpDevelop.Debugging
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
new file mode 100644
index 0000000000..cf758a382b
--- /dev/null
+++ b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs
@@ -0,0 +1,102 @@
+// 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 Services.Debugger.Tooltips
+{
+ 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.FullName == currentNode.FullName)
+ 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.FullName == currentNode.FullName) {
+ mark.Nodes.Remove(currentNode);
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingDescriptor.cs b/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingDescriptor.cs
index 5371c06fca..0311e62d79 100644
--- a/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingDescriptor.cs
+++ b/src/Main/Base/Project/Src/Services/LanguageBinding/LanguageBindingDescriptor.cs
@@ -24,6 +24,9 @@ namespace ICSharpCode.SharpDevelop
internal bool CanAttach(ITextEditor editor)
{
+ if (Extensions == null || Extensions.Length == 0)
+ return true;
+
if (!string.IsNullOrEmpty(editor.FileName)) {
string extension = Path.GetExtension(editor.FileName).ToLowerInvariant();
foreach (var ext in Extensions) {
diff --git a/src/Main/StartUp/Project/Resources/BitmapResources.resources b/src/Main/StartUp/Project/Resources/BitmapResources.resources
index 00029d6f0b..0b467fe1f0 100644
Binary files a/src/Main/StartUp/Project/Resources/BitmapResources.resources and b/src/Main/StartUp/Project/Resources/BitmapResources.resources differ