Browse Source

Edit pin control v0.2

pull/11/head
eusebiu 15 years ago
parent
commit
1d934de1b4
  1. 1
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  2. 1
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
  3. 1
      src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
  4. 1
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
  5. 1
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs
  6. 67
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs
  7. 1
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/Adapters/TreeViewVarNode.cs
  8. 1
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs
  9. 1
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs
  10. 5
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs
  11. 1
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs
  12. 1
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/ICorDebug.cs
  13. 5
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/IEnumerableNode.cs
  14. 75
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/PinLayer.cs
  15. 7
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs
  16. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  17. 28
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/Layer.cs
  18. 6
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/LayerPosition.cs
  19. 7
      src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
  20. 4
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  21. 55
      src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs
  22. 55
      src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerPopup.cs
  23. 684
      src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml
  24. 327
      src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml.cs
  25. 2
      src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs
  26. 54
      src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs
  27. 59
      src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinCloseControl.xaml.cs
  28. 86
      src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinningBinding.cs
  29. 123
      src/Main/Base/Project/Src/Services/Debugger/TreeNode.cs

1
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj

@ -247,7 +247,6 @@
</Compile> </Compile>
<Compile Include="Pads\DebuggerPad.cs" /> <Compile Include="Pads\DebuggerPad.cs" />
<Compile Include="Pads\RunningThreadsPad.Menu.cs" /> <Compile Include="Pads\RunningThreadsPad.Menu.cs" />
<Compile Include="TreeModel\TreeNode.cs" />
<Compile Include="TreeModel\Adapters\TreeViewVarNode.cs"> <Compile Include="TreeModel\Adapters\TreeViewVarNode.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>

1
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs

@ -11,6 +11,7 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Debugger.AddIn.TreeModel; using Debugger.AddIn.TreeModel;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.Pads.Controls namespace Debugger.AddIn.Pads.Controls
{ {

1
src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs

@ -7,6 +7,7 @@ using Debugger.AddIn.Pads.Controls;
using Debugger.AddIn.TreeModel; using Debugger.AddIn.TreeModel;
using ICSharpCode.Core; using ICSharpCode.Core;
using Exception = System.Exception; using Exception = System.Exception;
using TreeNode = ICSharpCode.SharpDevelop.Debugging.TreeNode;
namespace ICSharpCode.SharpDevelop.Gui.Pads namespace ICSharpCode.SharpDevelop.Gui.Pads
{ {

1
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs

@ -15,6 +15,7 @@ using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using Exception = System.Exception; using Exception = System.Exception;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Gui.Pads namespace ICSharpCode.SharpDevelop.Gui.Pads
{ {

1
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadCommands.cs

@ -17,6 +17,7 @@ using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui.Pads; using ICSharpCode.SharpDevelop.Gui.Pads;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn namespace Debugger.AddIn
{ {

67
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) // 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) // 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;
using System.Windows.Forms;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using Debugger.AddIn.TreeModel; using Debugger.AddIn.TreeModel;
using TreeNode = Debugger.AddIn.TreeModel.TreeNode; using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Gui.Pads namespace ICSharpCode.SharpDevelop.Gui.Pads
{ {
public class TextNode : Debugger.AddIn.TreeModel.TreeNode, ISetText public class TextNode : TreeNode, ISetText
{ {
public TextNode(string text, SupportedLanguage language) public TextNode(string text, SupportedLanguage language)
{ {
@ -47,62 +44,4 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
IconImage = DebuggerResourceService.GetImage("Icons.16x16.Error"); 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);
}
}
}
} }

1
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;
using Aga.Controls.Tree.NodeControls; using Aga.Controls.Tree.NodeControls;
using ICSharpCode.Core; using ICSharpCode.Core;
using TreeNode = ICSharpCode.SharpDevelop.Debugging.TreeNode;
namespace Debugger.AddIn.TreeModel namespace Debugger.AddIn.TreeModel
{ {

1
src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel namespace Debugger.AddIn.TreeModel
{ {

1
src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs

@ -11,6 +11,7 @@ using ICSharpCode.Core;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Services; using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel namespace Debugger.AddIn.TreeModel
{ {

5
src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs

@ -4,22 +4,19 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Forms; using System.Windows.Forms;
using Debugger.AddIn.Visualizers; using Debugger.AddIn.Visualizers;
using Debugger.AddIn.Visualizers.Utils;
using Debugger.MetaData; using Debugger.MetaData;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Gui.Pads;
using ICSharpCode.SharpDevelop.Services; using ICSharpCode.SharpDevelop.Services;
using TreeNode = ICSharpCode.SharpDevelop.Debugging.TreeNode;
namespace Debugger.AddIn.TreeModel namespace Debugger.AddIn.TreeModel
{ {

1
src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs

@ -4,6 +4,7 @@
using Debugger.MetaData; using Debugger.MetaData;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel namespace Debugger.AddIn.TreeModel
{ {

1
src/AddIns/Debugger/Debugger.AddIn/Visualizers/ICorDebug.cs

@ -5,6 +5,7 @@ using Debugger.Interop.CorDebug;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Debugger.MetaData; using Debugger.MetaData;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel namespace Debugger.AddIn.TreeModel
{ {

5
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) // 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) // 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;
using System.Collections.Generic;
using System.Linq;
using Debugger.AddIn.Visualizers.Utils; using Debugger.AddIn.Visualizers.Utils;
using Debugger.MetaData;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.TreeModel namespace Debugger.AddIn.TreeModel
{ {

75
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/PinLayer.cs

@ -0,0 +1,75 @@
// 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.Media;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Editing
{
/// <summary>
/// Pin layer class. This class handles the pinning and unpinning operations.
/// </summary>
public class PinLayer : Layer, IWeakEventListener
{
private Canvas pinningSurface;
/// <summary>
/// PinLayer constructor.
/// </summary>
/// <param name="textArea">Text area for this layer.</param>
public PinLayer(TextArea textArea) : base(textArea.TextView, KnownLayer.Pins)
{
pinningSurface = new Canvas();
pinningSurface.Background = Brushes.Red;
pinningSurface.HorizontalAlignment = HorizontalAlignment.Stretch;
pinningSurface.VerticalAlignment = VerticalAlignment.Stretch;
TextViewWeakEventManager.VisualLinesChanged.AddListener(textArea.TextView, this);
}
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(TextViewWeakEventManager.VisualLinesChanged))
{
pinningSurface.InvalidateVisual();
InvalidateVisual();
return true;
}
return false;
}
/// <summary>
/// Pins an element;
/// </summary>
/// <param name="element">Element to pin.</param>
public void Pin(Popup element)
{
if (element == null)
throw new NullReferenceException("Element is null!");
element.Placement = PlacementMode.Absolute;
pinningSurface.SetValue(Canvas.TopProperty, element.VerticalOffset);
pinningSurface.SetValue(Canvas.LeftProperty, element.HorizontalOffset);
pinningSurface.Children.Add(element);
}
/// <summary>
/// Unpins an element.
/// </summary>
/// <param name="element">Element to unpin.</param>
public void Unpin(Popup element)
{
if (element == null)
throw new NullReferenceException("Element is null!");
pinningSurface.Children.Remove(element);
}
}
}

7
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs

@ -71,9 +71,16 @@ namespace ICSharpCode.AvalonEdit.Editing
this.DefaultInputHandler = new TextAreaDefaultInputHandler(this); this.DefaultInputHandler = new TextAreaDefaultInputHandler(this);
this.ActiveInputHandler = this.DefaultInputHandler; this.ActiveInputHandler = this.DefaultInputHandler;
PinningLayer = new PinLayer(this);
textView.InsertLayer(PinningLayer, KnownLayer.Caret, LayerInsertionPosition.Above);
} }
#endregion #endregion
/// <summary>
/// Gets the pinning layer.
/// </summary>
public PinLayer PinningLayer { get; private set; }
#region InputHandler management #region InputHandler management
/// <summary> /// <summary>
/// Gets the default input handler. /// Gets the default input handler.

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -144,6 +144,7 @@
<Compile Include="Editing\DottedLineMargin.cs" /> <Compile Include="Editing\DottedLineMargin.cs" />
<Compile Include="Editing\DragDropException.cs" /> <Compile Include="Editing\DragDropException.cs" />
<Compile Include="Editing\EditingCommandHandler.cs" /> <Compile Include="Editing\EditingCommandHandler.cs" />
<Compile Include="Editing\PinLayer.cs" />
<Compile Include="Folding\AbstractFoldingStrategy.cs" /> <Compile Include="Folding\AbstractFoldingStrategy.cs" />
<Compile Include="Folding\FoldingElementGenerator.cs" /> <Compile Include="Folding\FoldingElementGenerator.cs" />
<Compile Include="Folding\FoldingManager.cs" /> <Compile Include="Folding\FoldingManager.cs" />

28
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/Layer.cs

@ -11,11 +11,23 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// <summary> /// <summary>
/// Base class for known layers. /// Base class for known layers.
/// </summary> /// </summary>
class Layer : UIElement public class Layer : UIElement
{ {
/// <summary>
/// Text view.
/// </summary>
protected readonly TextView textView; protected readonly TextView textView;
/// <summary>
/// Known layer.
/// </summary>
protected readonly KnownLayer knownLayer; protected readonly KnownLayer knownLayer;
/// <summary>
/// Constructor for base layer class.
/// </summary>
/// <param name="textView">Text view</param>
/// <param name="knownLayer">Known layer.</param>
public Layer(TextView textView, KnownLayer knownLayer) public Layer(TextView textView, KnownLayer knownLayer)
{ {
Debug.Assert(textView != null); Debug.Assert(textView != null);
@ -24,16 +36,30 @@ namespace ICSharpCode.AvalonEdit.Rendering
this.Focusable = false; this.Focusable = false;
} }
/// <summary>
/// HitTestCore method.
/// </summary>
/// <param name="hitTestParameters">Hit test parameters.</param>
/// <returns>A GeometryHitTestResult.</returns>
protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters) protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters)
{ {
return null; return null;
} }
/// <summary>
/// HitTestCore method.
/// </summary>
/// <param name="hitTestParameters">Hit test parameters.</param>
/// <returns>A HitTestResult.</returns>
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{ {
return null; return null;
} }
/// <summary>
/// Override for Render.
/// </summary>
/// <param name="drawingContext">Drawing context.</param>
protected override void OnRender(DrawingContext drawingContext) protected override void OnRender(DrawingContext drawingContext)
{ {
base.OnRender(drawingContext); base.OnRender(drawingContext);

6
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/LayerPosition.cs

@ -32,7 +32,11 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// This layer contains the blinking caret. /// This layer contains the blinking caret.
/// </summary> /// </summary>
/// <remarks>This layer is above the Text layer. All items on this layer will blink with the same frequency as the caret.</remarks> /// <remarks>This layer is above the Text layer. All items on this layer will blink with the same frequency as the caret.</remarks>
Caret Caret,
/// <summary>
/// This layer contains the data pins
/// </summary>
Pins
} }
/// <summary> /// <summary>

7
src/Main/Base/Project/ICSharpCode.SharpDevelop.addin

@ -61,6 +61,13 @@
class = "ICSharpCode.SharpDevelop.BrowserDisplayBinding.BrowserDisplayBinding"/> class = "ICSharpCode.SharpDevelop.BrowserDisplayBinding.BrowserDisplayBinding"/>
</Path> </Path>
<Path name="/SharpDevelop/Workbench/LanguageBindings">
<LanguageBinding
id="Pin"
class="Services.Debugger.Tooltips.PinningBinding"
extensions=".cs;.vb" />
</Path>
<Path name = "/SharpDevelop/Workbench/FileFilter"> <Path name = "/SharpDevelop/Workbench/FileFilter">
<FileFilter id = "AllFiles" <FileFilter id = "AllFiles"
name = "${res:SharpDevelop.FileFilter.AllFiles}" name = "${res:SharpDevelop.FileFilter.AllFiles}"

4
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -324,8 +324,10 @@
<Compile Include="Src\Services\Debugger\Tooltips\PinCloseControl.xaml.cs"> <Compile Include="Src\Services\Debugger\Tooltips\PinCloseControl.xaml.cs">
<DependentUpon>PinCloseControl.xaml</DependentUpon> <DependentUpon>PinCloseControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Src\Services\Debugger\Tooltips\PinningBinding.cs" />
<Compile Include="Src\Services\Debugger\Tooltips\VirtualizingIEnumerable.cs" /> <Compile Include="Src\Services\Debugger\Tooltips\VirtualizingIEnumerable.cs" />
<Compile Include="Src\Services\Debugger\Tooltips\VisualizerPicker.cs" /> <Compile Include="Src\Services\Debugger\Tooltips\VisualizerPicker.cs" />
<Compile Include="Src\Services\Debugger\TreeNode.cs" />
<Compile Include="Src\Services\DisplayBinding\ExternalProcessDisplayBinding.cs" /> <Compile Include="Src\Services\DisplayBinding\ExternalProcessDisplayBinding.cs" />
<Compile Include="Src\Services\DisplayBinding\ISecondaryDisplayBinding.cs" /> <Compile Include="Src\Services\DisplayBinding\ISecondaryDisplayBinding.cs" />
<Compile Include="Src\Services\DisplayBinding\ShellExecuteDisplayBinding.cs" /> <Compile Include="Src\Services\DisplayBinding\ShellExecuteDisplayBinding.cs" />
@ -825,6 +827,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Src\Bookmarks\Pad\Controls\ListViewPad.xaml" /> <Page Include="Src\Bookmarks\Pad\Controls\ListViewPad.xaml" />
<Page Include="Src\Services\Debugger\Tooltips\PinCloseControl.xaml" />
<Page Include="Src\Services\Debugger\Tooltips\PinControlsDictionary.xaml" />
<Page Include="Src\Services\RefactoringService\ContextActions\ContextActionsBulbControl.xaml" /> <Page Include="Src\Services\RefactoringService\ContextActions\ContextActionsBulbControl.xaml" />
<Page Include="Src\Services\RefactoringService\ContextActions\ContextActionsControl.xaml" /> <Page Include="Src\Services\RefactoringService\ContextActions\ContextActionsControl.xaml" />
<Page Include="Src\Services\RefactoringService\ContextActions\ContextActionsHeaderedControl.xaml" /> <Page Include="Src\Services\RefactoringService\ContextActions\ContextActionsHeaderedControl.xaml" />

55
src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs

@ -5,9 +5,11 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Text; using System.Text;
using System.Windows;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using Services.Debugger.Tooltips;
namespace ICSharpCode.SharpDevelop.Bookmarks namespace ICSharpCode.SharpDevelop.Bookmarks
{ {
@ -34,7 +36,6 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
return null; return null;
if (columnNumber < 0) if (columnNumber < 0)
return null; return null;
SDBookmark bookmark; SDBookmark bookmark;
switch (v[0]) { switch (v[0]) {
case "Breakpoint": case "Breakpoint":
@ -44,22 +45,33 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
action = (Debugging.BreakpointAction)Enum.Parse(typeof(Debugging.BreakpointAction), v[5]); action = (Debugging.BreakpointAction)Enum.Parse(typeof(Debugging.BreakpointAction), v[5]);
scriptLanguage = v[6]; scriptLanguage = v[6];
script = v[7]; script = v[7];
var bbm = new Debugging.BreakpointBookmark(fileName, new Location(columnNumber, lineNumber), action, scriptLanguage, script); var bbm = new Debugging.BreakpointBookmark(fileName, new Location(columnNumber, lineNumber), action, scriptLanguage, script);
bbm.IsEnabled = bool.Parse(v[4]); bbm.IsEnabled = bool.Parse(v[4]);
bookmark = bbm;
bbm.Action = action; bbm.Action = action;
bbm.ScriptLanguage = scriptLanguage; bbm.ScriptLanguage = scriptLanguage;
bbm.Condition = script; bbm.Condition = script;
bookmark = bbm;
break;
case "PinBookmark":
var pin = new PinBookmark(fileName, new Location(columnNumber, lineNumber));
pin.Comment = v[4];
// pop-up position
pin.SavedPopupPosition =
new Point
{
X = int.Parse(v[5], culture),
Y = int.Parse(v[6], culture)
};
// pop-up nodes
pin.SavedNodes = new System.Collections.Generic.List<Tuple<string, string, string>>();
for (int i = 7; i < v.Length; i+=3) {
pin.SavedNodes.Add(new Tuple<string, string, string>(v[i], v[i+1], v[i+2]));
}
bookmark = pin;
break; break;
// case "PinBookmark":
// var pin = new PinBookmark(fileName, new Location(columnNumber, lineNumber));
// pin.Comment = v[3];
// for (int i = 4; i < v.Length; i+=2) {
// pin.SavedNodes.Add(new Tuple<string, string>(v[i], v[i+1]));
// }
//
// bookmark = pin;
// break;
default: default:
bookmark = new SDBookmark(fileName, new Location(columnNumber, lineNumber)); bookmark = new SDBookmark(fileName, new Location(columnNumber, lineNumber));
break; break;
@ -102,6 +114,27 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
b.Append(bbm.Condition); 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.Popup.HorizontalOffset);
b.Append('|');
b.Append(pin.Popup.VerticalOffset);
b.Append('|');
//popup nodes
foreach(var node in pin.Nodes) {
b.Append("");
b.Append('|');
b.Append(node.Name);
b.Append('|');
b.Append(node.Text);
}
}
return b.ToString(); return b.ToString();
} else { } else {
return base.ConvertTo(context, culture, value, destinationType); return base.ConvertTo(context, culture, value, destinationType);

55
src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerPopup.cs

@ -3,13 +3,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
using System.Windows.Input;
using ICSharpCode.Core; using ICSharpCode.AvalonEdit;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using Services.Debugger.Tooltips;
namespace ICSharpCode.SharpDevelop.Debugging namespace ICSharpCode.SharpDevelop.Debugging
{ {
@ -18,10 +16,13 @@ namespace ICSharpCode.SharpDevelop.Debugging
/// </summary> /// </summary>
public class DebuggerPopup : Popup public class DebuggerPopup : Popup
{ {
private bool showPinControl;
internal DebuggerTooltipControl contentControl; internal DebuggerTooltipControl contentControl;
public DebuggerPopup(DebuggerTooltipControl parentControl, bool showPinControl) public DebuggerPopup(DebuggerTooltipControl parentControl, bool showPinControl)
{ {
this.showPinControl = showPinControl;
this.contentControl = new DebuggerTooltipControl(parentControl, showPinControl); this.contentControl = new DebuggerTooltipControl(parentControl, showPinControl);
this.contentControl.containingPopup = this; this.contentControl.containingPopup = this;
this.Child = this.contentControl; this.Child = this.contentControl;
@ -34,8 +35,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
this.AllowsTransparency = true; this.AllowsTransparency = true;
//this.PopupAnimation = PopupAnimation.Slide; //this.PopupAnimation = PopupAnimation.Slide;
} }
public PinBookmark Mark { get; set; }
// attempt to propagate shortcuts to main windows when Popup is focusable (needed for keyboard scrolling + editing) // attempt to propagate shortcuts to main windows when Popup is focusable (needed for keyboard scrolling + editing)
/*void DebuggerPopup_KeyDown(object sender, KeyEventArgs e) /*void DebuggerPopup_KeyDown(object sender, KeyEventArgs e)
@ -63,10 +62,9 @@ namespace ICSharpCode.SharpDevelop.Debugging
return args.Handled; return args.Handled;
}*/ }*/
public IEnumerable<ITreeNode> ItemsSource public void SetItemsSource(IEnumerable<ITreeNode> value)
{ {
get { return this.contentControl.ItemsSource; } this.contentControl.SetItemsSource(value);
set { this.contentControl.ItemsSource = value; }
} }
private bool isLeaf; private bool isLeaf;
@ -87,10 +85,31 @@ namespace ICSharpCode.SharpDevelop.Debugging
if (isLeaf) { if (isLeaf) {
this.contentControl.CloseOnLostFocus(); this.contentControl.CloseOnLostFocus();
} }
// unpin from surface
if (this.showPinControl) {
var provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider;
if(provider != null) {
var editor = (TextEditor)provider.TextEditor.GetService(typeof(TextEditor));
editor.TextArea.PinningLayer.Unpin(this);
}
}
} }
public void Open() public void Open()
{ {
if (this.IsOpen)
return;
// pin onto surface
if (this.showPinControl) {
var provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider;
if(provider != null) {
var editor = (TextEditor)provider.TextEditor.GetService(typeof(TextEditor));
editor.TextArea.PinningLayer.Pin(this);
}
}
this.IsOpen = true; this.IsOpen = true;
} }
@ -99,5 +118,23 @@ namespace ICSharpCode.SharpDevelop.Debugging
this.contentControl.CloseChildPopups(); this.contentControl.CloseChildPopups();
this.IsOpen = false; this.IsOpen = false;
} }
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
if (showPinControl) {
Child.Opacity = 1d;
}
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
{
if (showPinControl) {
Child.Opacity = DebuggerTooltipControl.MINIMUM_OPACITY;
}
base.OnMouseLeave(e);
}
} }
} }

684
src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml

@ -1,272 +1,426 @@
<UserControl x:Class="ICSharpCode.SharpDevelop.Debugging.DebuggerTooltipControl" <?xml version="1.0" encoding="utf-8"?>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <UserControl
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ICSharpCode.SharpDevelop.Debugging.DebuggerTooltipControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" xmlns:debugging="clr-namespace:ICSharpCode.SharpDevelop.Debugging" xmlns:core="http://icsharpcode.net/sharpdevelop/core" xmlns:localControls="clr-namespace:Services.Debugger.Tooltips"
xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" Background="Transparent">
xmlns:debugging="clr-namespace:ICSharpCode.SharpDevelop.Debugging" <UserControl.Resources>
xmlns:core="http://icsharpcode.net/sharpdevelop/core" <ResourceDictionary>
xmlns:localControls="clr-namespace:Services.Debugger.Tooltips" <ResourceDictionary.MergedDictionaries>
Background="Transparent" <ResourceDictionary
> Source="VisualizerPicker.xaml" />
<UserControl.Resources> <ResourceDictionary
<ResourceDictionary> Source="PinControlsDictionary.xaml" />
<ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="VisualizerPicker.xaml" /> <!-- TODO move styles to ResourceDictionary -->
<ResourceDictionary Source="PinControlsDictionary.xaml"/> <Style
</ResourceDictionary.MergedDictionaries> x:Key="ExpandCollapseToggleStyle"
TargetType="{x:Type ToggleButton}">
<!-- TODO move styles to ResourceDictionary --> <Setter
<Style x:Key="ExpandCollapseToggleStyle" Property="Focusable"
TargetType="{x:Type ToggleButton}"> Value="False" />
<Setter Property="Focusable" <Setter
Value="False"/> Property="Width"
<Setter Property="Width" Value="19" />
Value="19"/> <Setter
<Setter Property="Height" Property="Height"
Value="13"/> Value="13" />
<Setter Property="Template"> <Setter
<Setter.Value> Property="Template">
<ControlTemplate TargetType="{x:Type ToggleButton}"> <Setter.Value>
<Border Width="19" <ControlTemplate
Height="13" TargetType="{x:Type ToggleButton}">
Background="Transparent"> <Border
<Border Width="9" Width="19"
Height="9" Height="13"
BorderThickness="1" Background="Transparent">
BorderBrush="#FF7898B5" <Border
CornerRadius="1" Width="9"
SnapsToDevicePixels="true"> Height="9"
<Border.Background> BorderThickness="1"
<LinearGradientBrush StartPoint="0,0" BorderBrush="#FF7898B5"
EndPoint="1,1"> CornerRadius="1"
<LinearGradientBrush.GradientStops> SnapsToDevicePixels="true">
<GradientStop Color="White" <Border.Background>
Offset=".2"/> <LinearGradientBrush
<GradientStop Color="#FFC0B7A6" StartPoint="0,0"
Offset="1"/> EndPoint="1,1">
</LinearGradientBrush.GradientStops> <LinearGradientBrush.GradientStops>
</LinearGradientBrush> <GradientStop
</Border.Background> Color="White"
<Path x:Name="ExpandPath" Offset=".2" />
Margin="1,1,1,1" <GradientStop
Fill="Black" Color="#FFC0B7A6"
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/> Offset="1" />
</Border> </LinearGradientBrush.GradientStops>
</Border> </LinearGradientBrush>
<ControlTemplate.Triggers> </Border.Background>
<Trigger Property="IsChecked" <Path
Value="True"> x:Name="ExpandPath"
<Setter Property="Data" Margin="1,1,1,1"
TargetName="ExpandPath" Fill="Black"
Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/> Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z" />
</Trigger> </Border>
</ControlTemplate.Triggers> </Border>
</ControlTemplate> <ControlTemplate.Triggers>
</Setter.Value> <Trigger
</Setter> Property="IsChecked"
</Style> Value="True">
<Style x:Key="upDownBorderStyle" TargetType="{x:Type Border}"> <Setter
<Setter Property="BorderBrush" Value="Gray" /> Property="Data"
<Setter Property="HorizontalAlignment" Value="Stretch" /> TargetName="ExpandPath"
<Setter Property="Margin" Value="0" /> Value="M 0 2 L 0 3 L 5 3 L 5 2 Z" />
<Setter Property="Padding" Value="0" /> </Trigger>
<Setter Property="Background" Value="#FFECF7FC" /> </ControlTemplate.Triggers>
<Setter Property="Height" Value="14" /> </ControlTemplate>
<Style.Triggers> </Setter.Value>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False"> </Setter>
<Setter Property="Background" Value="#FFE0E0E0"></Setter> </Style>
</DataTrigger> <Style
</Style.Triggers> x:Key="upDownBorderStyle"
</Style> TargetType="{x:Type Border}">
<Style x:Key="upButtonStyle" TargetType="{x:Type RepeatButton}"> <Setter
<Setter Property="Template"> Property="BorderBrush"
<Setter.Value> Value="Gray" />
<ControlTemplate TargetType="{x:Type RepeatButton}"> <Setter
<Border Style="{StaticResource upDownBorderStyle}" BorderThickness="1 1 1 0"> Property="HorizontalAlignment"
<ContentPresenter HorizontalAlignment="Center"></ContentPresenter> Value="Stretch" />
</Border> <Setter
</ControlTemplate> Property="Margin"
</Setter.Value> Value="0" />
</Setter> <Setter
</Style> Property="Padding"
<Style x:Key="downButtonStyle" TargetType="{x:Type RepeatButton}"> Value="0" />
<Setter Property="Template"> <Setter
<Setter.Value> Property="Background"
<ControlTemplate TargetType="{x:Type RepeatButton}"> Value="#FFECF7FC" />
<Border Style="{StaticResource upDownBorderStyle}" BorderThickness="1 0 1 1"> <Setter
<ContentPresenter HorizontalAlignment="Center"></ContentPresenter> Property="Height"
</Border> Value="14" />
</ControlTemplate> <Style.Triggers>
</Setter.Value> <DataTrigger
</Setter> Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}"
</Style> Value="False">
<Style TargetType="{x:Type TextBox}" x:Key="TextStyle"> <Setter
<Setter Property="OverridesDefaultStyle" Value="True"/> Property="Background"
<Setter Property="VerticalAlignment" Value="Top"/> Value="#FFE0E0E0"></Setter>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/> </DataTrigger>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/> </Style.Triggers>
<Setter Property="Template"> </Style>
<Setter.Value> <Style
<ControlTemplate TargetType="{x:Type TextBoxBase}"> x:Key="upButtonStyle"
<Border TargetType="{x:Type RepeatButton}">
Name="Border" <Setter
Background="Transparent" Property="Template">
BorderBrush="Transparent" <Setter.Value>
BorderThickness="0"> <ControlTemplate
<ScrollViewer Margin="0" Name="PART_ContentHost" /> TargetType="{x:Type RepeatButton}">
</Border> <Border
</ControlTemplate> Style="{StaticResource upDownBorderStyle}"
</Setter.Value> BorderThickness="1 1 1 0">
</Setter> <ContentPresenter
</Style> HorizontalAlignment="Center"></ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="downButtonStyle"
TargetType="{x:Type RepeatButton}">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type RepeatButton}">
<Border
Style="{StaticResource upDownBorderStyle}"
BorderThickness="1 0 1 1">
<ContentPresenter
HorizontalAlignment="Center"></ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
TargetType="{x:Type TextBox}"
x:Key="TextStyle">
<Setter
Property="OverridesDefaultStyle"
Value="True" />
<Setter
Property="VerticalAlignment"
Value="Top" />
<Setter
Property="KeyboardNavigation.TabNavigation"
Value="None" />
<Setter
Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type TextBoxBase}">
<Border
Name="Border"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0">
<ScrollViewer
Margin="0"
Name="PART_ContentHost" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary> </ResourceDictionary>
</UserControl.Resources> </UserControl.Resources>
<Grid Background="Transparent" Name="ParentGrid"> <Grid
<Grid.ColumnDefinitions> Background="Transparent"
<ColumnDefinition/> Name="ParentGrid">
<ColumnDefinition/> <Grid.ColumnDefinitions>
</Grid.ColumnDefinitions> <ColumnDefinition />
<Grid.RowDefinitions> <ColumnDefinition />
<RowDefinition Height="Auto"/> </Grid.ColumnDefinitions>
<RowDefinition Height="50"/> <Grid.RowDefinitions>
</Grid.RowDefinitions> <RowDefinition
<StackPanel Orientation="Vertical"> Height="Auto" />
<RepeatButton Name="btnUp" Focusable="False" Style="{StaticResource upButtonStyle}" Content="^" Click="BtnUp_Click"></RepeatButton> <RowDefinition
<DataGrid VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" Height="50" />
GridLinesVisibility="None" </Grid.RowDefinitions>
RowHeight="18" MaxHeight="202" <StackPanel
SelectionMode="Single" Orientation="Vertical">
SelectionUnit="FullRow" <RepeatButton
ItemsSource="{Binding}" Name="btnUp"
Name="dataGrid" Focusable="False"
AutoGenerateColumns="False" Style="{StaticResource upButtonStyle}"
CanUserAddRows="False" HeadersVisibility="None" Content="^"
BorderBrush="Gray" Click="BtnUp_Click"></RepeatButton>
BorderThickness="1"> <DataGrid
<DataGrid.Background> VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled"
<!-- Control backgound --> GridLinesVisibility="None"
<LinearGradientBrush StartPoint="0,-0.03" EndPoint="0,1"> RowHeight="18"
<GradientStop Color="White"/> MaxHeight="202"
<GradientStop Color="#FFFAFCFE" Offset="0.983"/> SelectionMode="Single"
<GradientStop Color="#FFECF7FC" Offset="0.07"/> SelectionUnit="FullRow"
<GradientStop Color="#FFEEF7FA" Offset="0.436"/> ItemsSource="{Binding}"
</LinearGradientBrush> Name="dataGrid"
</DataGrid.Background> AutoGenerateColumns="False"
<DataGrid.RowStyle> CanUserAddRows="False"
<Style TargetType="{x:Type DataGridRow}"> HeadersVisibility="None"
<Setter Property="Background" Value="Transparent"></Setter> BorderBrush="Gray"
<Style.Triggers> BorderThickness="1">
<Trigger Property="IsMouseOver" Value="True"> <DataGrid.Background>
<Setter Property="Background" Value="#FFE2F6FE" /> <!-- Control backgound -->
</Trigger> <LinearGradientBrush
</Style.Triggers> StartPoint="0,-0.03"
</Style> EndPoint="0,1">
</DataGrid.RowStyle> <GradientStop
<DataGrid.CellStyle> Color="White" />
<Style TargetType="{x:Type DataGridCell}"> <GradientStop
<Setter Property="Focusable" Value="false" /> <!-- Focusable=true blocks shortcuts if cell is focused --> Color="#FFFAFCFE"
<Setter Property="BorderThickness" Value="0" /> Offset="0.983" />
<Style.Triggers> <GradientStop
<Trigger Property="IsSelected" Value="True"> <!-- disable selection highlight --> Color="#FFECF7FC"
<Setter Property="Foreground" Value="Black" /> Offset="0.07" />
<Setter Property="Background" Value="{x:Null}" /> <GradientStop
</Trigger> Color="#FFEEF7FA"
</Style.Triggers> Offset="0.436" />
</Style> </LinearGradientBrush>
</DataGrid.CellStyle> </DataGrid.Background>
<DataGrid.Columns> <DataGrid.RowStyle>
<DataGridTemplateColumn> <!-- "Plus" expander --> <Style
<DataGridTemplateColumn.CellTemplate> TargetType="{x:Type DataGridRow}">
<DataTemplate> <Setter
<Grid Background="White"> Property="Background"
<StackPanel VerticalAlignment="Center"> Value="Transparent"></Setter>
<ToggleButton x:Name="btnExpander" Style="{StaticResource ExpandCollapseToggleStyle}" Click="btnExpander_Click" Padding="0" Margin="0" /> <Style.Triggers>
</StackPanel> <Trigger
</Grid> Property="IsMouseOver"
<DataTemplate.Triggers> Value="True">
<DataTrigger Binding="{Binding Path=HasChildNodes}" Value="False"> <Setter
<Setter TargetName="btnExpander" Property="Background"
Property="Visibility" Value="Collapsed"/> Value="#FFE2F6FE" />
</DataTrigger> </Trigger>
</DataTemplate.Triggers> </Style.Triggers>
</DataTemplate> </Style>
</DataGridTemplateColumn.CellTemplate> </DataGrid.RowStyle>
</DataGridTemplateColumn> <DataGrid.CellStyle>
<!-- Icon --> <Style
<DataGridTemplateColumn> TargetType="{x:Type DataGridCell}">
<DataGridTemplateColumn.CellTemplate> <Setter
<DataTemplate> Property="Focusable"
<Image Source="{Binding ImageSource}"></Image> Value="false" />
</DataTemplate> <!-- Focusable=true blocks shortcuts if cell is focused -->
</DataGridTemplateColumn.CellTemplate> <Setter
</DataGridTemplateColumn> Property="BorderThickness"
<DataGridTemplateColumn MinWidth="20" Header="Name"> <!-- Name --> Value="0" />
<DataGridTemplateColumn.CellTemplate> <Style.Triggers>
<DataTemplate> <Trigger
<Border BorderBrush="#FFDDDDDD" BorderThickness="0 0 1 0"> Property="IsSelected"
<TextBlock Margin="6 0" Text="{Binding Path=Name, Mode=OneWay}" VerticalAlignment="Top"></TextBlock> Value="True">
</Border> <!-- disable selection highlight -->
</DataTemplate> <Setter
</DataGridTemplateColumn.CellTemplate> Property="Foreground"
</DataGridTemplateColumn> Value="Black" />
<!-- Visualizer picker --> <Setter
<DataGridTemplateColumn> Property="Background"
<DataGridTemplateColumn.CellTemplate> Value="{x:Null}" />
<DataTemplate> </Trigger>
<debugging:VisualizerPicker Focusable="False" x:Name="visPicker" ItemsSource="{Binding Path=VisualizerCommands, Mode=OneWay}" Margin="4 0 0 0"></debugging:VisualizerPicker> </Style.Triggers>
<DataTemplate.Triggers> </Style>
<DataTrigger Binding="{Binding Path=HasVisualizerCommands}" Value="False"> </DataGrid.CellStyle>
<Setter TargetName="visPicker" Property="Visibility" Value="Collapsed"/> <DataGrid.Columns>
</DataTrigger> <DataGridTemplateColumn>
</DataTemplate.Triggers> <!-- "Plus" expander -->
</DataTemplate> <DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn.CellTemplate> <DataTemplate>
</DataGridTemplateColumn> <Grid
Background="White">
<DataGridTemplateColumn MinWidth="20" Header="Text"> <!-- Text (value) --> <StackPanel
<DataGridTemplateColumn.CellTemplate> VerticalAlignment="Center">
<DataTemplate> <ToggleButton
<TextBox x:Name="btnExpander"
Style="{StaticResource TextStyle}" Style="{StaticResource ExpandCollapseToggleStyle}"
IsEnabled="{Binding CanSetText}" Click="btnExpander_Click"
KeyUp="TextBox_KeyUp" Padding="0"
Margin="4 0" Margin="0" />
Text="{Binding Path=Text}"/> </StackPanel>
</DataTemplate> </Grid>
</DataGridTemplateColumn.CellTemplate> <DataTemplate.Triggers>
</DataGridTemplateColumn> <DataTrigger
Binding="{Binding Path=HasChildNodes}"
<DataGridTemplateColumn> <!-- Pin --> Value="False">
<Setter
<DataGridTemplateColumn.CellTemplate> TargetName="btnExpander"
<DataTemplate> Property="Visibility"
<ToggleButton Value="Collapsed" />
DataContext="{Binding}" </DataTrigger>
Visibility="Collapsed" </DataTemplate.Triggers>
Name="PinButton" </DataTemplate>
VerticalAlignment="Center" </DataGridTemplateColumn.CellTemplate>
Checked="PinButton_Checked"
Unchecked="PinButton_Unchecked"
Template="{StaticResource PinTooltipButtonTemplate}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}" Value="True">
<Setter TargetName="PinButton" Property="Visibility" Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
</DataGrid.Columns> <!-- Icon -->
</DataGrid> <DataGridTemplateColumn>
<RepeatButton Name="btnDown" Focusable="False" Style="{StaticResource downButtonStyle}" Content="v" Click="BtnDown_Click"></RepeatButton> <DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- commentTextbox --> <Image
<Border Name="BorderComment" Background="White" BorderThickness="1,0,1,1" BorderBrush="Black" Height="0" MaxHeight="50"> Source="{Binding ImageSource}"></Image>
<TextBox Name="CommentTextBox" Margin="3" Height="34" TextChanged="CommentTextBox_TextChanged"/> </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn
MinWidth="20"
Header="Name">
<!-- Name -->
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border
BorderBrush="#FFDDDDDD"
BorderThickness="0 0 1 0">
<TextBlock
Margin="6 0"
Text="{Binding Path=Name, Mode=OneWay}"
VerticalAlignment="Top"></TextBlock>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- Visualizer picker -->
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<debugging:VisualizerPicker
Focusable="False"
x:Name="visPicker"
ItemsSource="{Binding Path=VisualizerCommands, Mode=OneWay}"
Margin="4 0 0 0"></debugging:VisualizerPicker>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding Path=HasVisualizerCommands}"
Value="False">
<Setter
TargetName="visPicker"
Property="Visibility"
Value="Collapsed" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn
MinWidth="20"
Header="Text">
<!-- Text (value) -->
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox
Style="{StaticResource TextStyle}"
IsEnabled="{Binding CanSetText}"
KeyUp="TextBox_KeyUp"
LostFocus="TextBox_LostFocus"
Margin="4 0"
Text="{Binding Path=Text}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<!-- Pin -->
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ToggleButton
IsChecked="{Binding IsChecked}"
DataContext="{Binding}"
Visibility="Collapsed"
Name="PinButton"
VerticalAlignment="Center"
Checked="PinButton_Checked"
Unchecked="PinButton_Unchecked"
Template="{StaticResource PinTooltipButtonTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}"
Value="True">
<Setter
TargetName="PinButton"
Property="Visibility"
Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<RepeatButton
Name="btnDown"
Focusable="False"
Style="{StaticResource downButtonStyle}"
Content="v"
Click="BtnDown_Click"></RepeatButton>
<!-- commentTextbox -->
<Border
Name="BorderComment"
Background="White"
BorderThickness="1,0,1,1"
BorderBrush="Black"
Height="0"
MaxHeight="50">
<TextBox
Name="CommentTextBox"
TextChanged="CommentTextBox_TextChanged"
Margin="3"/>
</Border> </Border>
</StackPanel> </StackPanel>
<Canvas MinWidth="25" Background="Transparent" Grid.Column="1" Name="PinControlCanvas" Visibility="Collapsed"> <Canvas
MinWidth="25"
Background="Transparent"
Grid.Column="1"
Name="PinControlCanvas"
Visibility="Collapsed">
<!-- Pin close control --> <!-- Pin close control -->
</Canvas> </Canvas>
</Grid> </Grid>
</UserControl> </UserControl>

327
src/Main/Base/Project/Src/Services/Debugger/Tooltips/DebuggerTooltipControl.xaml.cs

@ -27,13 +27,15 @@ namespace ICSharpCode.SharpDevelop.Debugging
/// </summary> /// </summary>
public partial class DebuggerTooltipControl : UserControl, ITooltip public partial class DebuggerTooltipControl : UserControl, ITooltip
{ {
public const double MINIMUM_OPACITY = .3d;
private readonly double ChildPopupOpenXOffet = 16; private readonly double ChildPopupOpenXOffet = 16;
private readonly double ChildPopupOpenYOffet = 15; private readonly double ChildPopupOpenYOffet = 15;
private readonly int InitialItemsCount = 12; private readonly int InitialItemsCount = 12;
private readonly int VisibleItemsCount = 11; private readonly int VisibleItemsCount = 11;
private readonly ITextEditor editor;
bool showPinControl; #region Contructors
PinCloseControl pinCloseControl;
public DebuggerTooltipControl(bool showPinControl = false) public DebuggerTooltipControl(bool showPinControl = false)
{ {
@ -41,6 +43,10 @@ namespace ICSharpCode.SharpDevelop.Debugging
this.showPinControl = showPinControl; this.showPinControl = showPinControl;
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider;
if (provider != null)
editor = provider.TextEditor;
// show pin close control // show pin close control
if (this.showPinControl) { if (this.showPinControl) {
dataGrid.Columns[5].Visibility = Visibility.Collapsed; dataGrid.Columns[5].Visibility = Visibility.Collapsed;
@ -49,10 +55,13 @@ namespace ICSharpCode.SharpDevelop.Debugging
pinCloseControl.Visibility = Visibility.Visible; pinCloseControl.Visibility = Visibility.Visible;
PinControlCanvas.Visibility = Visibility.Visible; PinControlCanvas.Visibility = Visibility.Visible;
PinControlCanvas.Children.Add(pinCloseControl); PinControlCanvas.Children.Add(pinCloseControl);
this.Opacity = MINIMUM_OPACITY;
} }
else { else {
PinControlCanvas.Visibility = Visibility.Collapsed; PinControlCanvas.Visibility = Visibility.Collapsed;
} }
Loaded += new RoutedEventHandler(OnLoaded);
} }
public DebuggerTooltipControl(ITreeNode node) public DebuggerTooltipControl(ITreeNode node)
@ -63,7 +72,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
public DebuggerTooltipControl(IEnumerable<ITreeNode> nodes) public DebuggerTooltipControl(IEnumerable<ITreeNode> nodes)
: this() : this()
{ {
this.ItemsSource = nodes; this.itemsSource = nodes;
} }
public DebuggerTooltipControl(DebuggerTooltipControl parentControl, bool showPinControl = false) public DebuggerTooltipControl(DebuggerTooltipControl parentControl, bool showPinControl = false)
@ -71,49 +80,103 @@ namespace ICSharpCode.SharpDevelop.Debugging
{ {
this.parentControl = parentControl; this.parentControl = parentControl;
} }
public event RoutedEventHandler Closed; private void OnLoaded(object sender, RoutedEventArgs e)
protected void OnClosed()
{ {
if (this.Closed != null) { // verify if at the line of the root there's a pin bookmark
this.Closed(this, new RoutedEventArgs()); var pin = BookmarkManager.Bookmarks.Find(
b => b is PinBookmark &&
b.Location.Line == LogicalPosition.Line &&
b.FileName == editor.FileName) as PinBookmark;
if (pin != null) {
foreach (var node in this.itemsSource) {
if (pin.ContainsNode(node))
node.IsChecked = true;
}
} }
SetItemsSource(this.itemsSource);
} }
#endregion
private bool showPinControl;
internal PinCloseControl pinCloseControl;
private DebuggerPopup childPopup { get; set; }
private DebuggerTooltipControl parentControl { get; set; }
internal DebuggerPopup containingPopup { get; set; }
private LazyItemsControl<ITreeNode> lazyGrid; private LazyItemsControl<ITreeNode> lazyGrid;
private IEnumerable<ITreeNode> itemsSource; private IEnumerable<ITreeNode> itemsSource;
public IEnumerable<ITreeNode> ItemsSource
public void SetItemsSource(IEnumerable<ITreeNode> value)
{ {
get { return this.itemsSource; } this.itemsSource = value;
set
{ this.lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount);
this.itemsSource = value; lazyGrid.ItemsSource = new VirtualizingIEnumerable<ITreeNode>(value);
this.lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount); this.dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll));
lazyGrid.ItemsSource = new VirtualizingIEnumerable<ITreeNode>(value);
this.dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll));
if (this.lazyGrid.ItemsSourceTotalCount != null) { if (this.lazyGrid.ItemsSourceTotalCount != null) {
// hide up/down buttons if too few items // hide up/down buttons if too few items
btnUp.Visibility = btnDown.Visibility = btnUp.Visibility = btnDown.Visibility =
this.lazyGrid.ItemsSourceTotalCount.Value <= VisibleItemsCount ? Visibility.Collapsed : Visibility.Visible; this.lazyGrid.ItemsSourceTotalCount.Value <= VisibleItemsCount ? Visibility.Collapsed : Visibility.Visible;
}
} }
} }
/// <inheritdoc/> /// <inheritdoc/>
public bool ShowAsPopup public bool ShowAsPopup { get { return true; } }
/// <summary>
/// Position within the document
/// </summary>
public Location LogicalPosition { get; set; }
#region Expander
bool isChildExpanded
{ {
get get
{ {
return true; return this.childPopup != null && this.childPopup.IsOpen;
} }
} }
private ToggleButton expandedButton;
/// <summary> private void btnExpander_Click(object sender, RoutedEventArgs e)
/// Position within the document {
/// </summary> var clickedButton = (ToggleButton)e.OriginalSource;
public Location LogicalPosition { get; set; } 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, showPinControl);
this.childPopup.Placement = PlacementMode.Absolute;
this.childPopup.contentControl.LogicalPosition = LogicalPosition;
}
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.SetItemsSource(clickedNode.ChildNodes);
this.childPopup.Open();
} else {
CloseChildPopups();
}
}
#endregion
#region Close
/// <inheritdoc/> /// <inheritdoc/>
public bool Close(bool mouseClick) public bool Close(bool mouseClick)
@ -126,20 +189,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
} }
} }
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;
/// <summary> /// <summary>
/// Closes the child popup of this control, if it exists. /// Closes the child popup of this control, if it exists.
/// </summary> /// </summary>
@ -176,37 +225,19 @@ namespace ICSharpCode.SharpDevelop.Debugging
} }
} }
} }
private void btnExpander_Click(object sender, RoutedEventArgs e) public event RoutedEventHandler Closed;
protected void OnClosed()
{ {
var clickedButton = (ToggleButton)e.OriginalSource; if (this.Closed != null) {
var clickedNode = (ITreeNode)clickedButton.DataContext; this.Closed(this, new RoutedEventArgs());
// 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, showPinControl);
this.childPopup.Placement = PlacementMode.Absolute;
}
if (this.containingPopup != null) {
this.containingPopup.IsLeaf = false;
}
this.childPopup.contentControl.LogicalPosition = LogicalPosition;
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();
} }
} }
#endregion
#region Scrolling
private void handleScroll(object sender, ScrollChangedEventArgs e) private void handleScroll(object sender, ScrollChangedEventArgs e)
{ {
btnUp.IsEnabled = !this.lazyGrid.IsScrolledToStart; btnUp.IsEnabled = !this.lazyGrid.IsScrolledToStart;
@ -223,6 +254,10 @@ namespace ICSharpCode.SharpDevelop.Debugging
this.lazyGrid.ScrollViewer.ScrollDown(1); this.lazyGrid.ScrollViewer.ScrollDown(1);
} }
#endregion
#region Edit value in tooltip
void TextBox_KeyUp(object sender, KeyEventArgs e) void TextBox_KeyUp(object sender, KeyEventArgs e)
{ {
if (e.Key == Key.Escape) { if (e.Key == Key.Escape) {
@ -233,16 +268,24 @@ namespace ICSharpCode.SharpDevelop.Debugging
if (e.Key == Key.Enter) { if (e.Key == Key.Enter) {
dataGrid.Focus(); dataGrid.Focus();
// set new value // set new value
var textBox = (TextBox)sender; var textBox = (TextBox)e.OriginalSource;
var newValue = textBox.Text; var newValue = textBox.Text;
var node = ((FrameworkElement)sender).DataContext as ITreeNode; var node = ((FrameworkElement)sender).DataContext as ITreeNode;
SaveNewValue(node, textBox.Text); 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) void SaveNewValue(ITreeNode node, string newValue)
{ {
if(node != null && node.SetText(newValue)) { if(node != null && node.SetText(newValue)) {
// show adorner // show adorner
var adornerLayer = AdornerLayer.GetAdornerLayer(dataGrid); var adornerLayer = AdornerLayer.GetAdornerLayer(dataGrid);
var adorners = adornerLayer.GetAdorners(dataGrid); var adorners = adornerLayer.GetAdorners(dataGrid);
@ -253,80 +296,79 @@ namespace ICSharpCode.SharpDevelop.Debugging
} }
} }
#endregion
#region Pining checked/unchecked
void PinButton_Checked(object sender, RoutedEventArgs e) void PinButton_Checked(object sender, RoutedEventArgs e)
{ {
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider; var node = (ITreeNode)(((ToggleButton)(e.OriginalSource)).DataContext);
ToggleButton button = (ToggleButton)e.OriginalSource;
if (provider != null) { if (!string.IsNullOrEmpty(editor.FileName)) {
ITextEditor editor = provider.TextEditor;
if (!string.IsNullOrEmpty(editor.FileName)) { // verify if at the line of the root there's a pin bookmark
var pin = BookmarkManager.Bookmarks.Find(
var location = LogicalPosition; b => b is PinBookmark &&
b.LineNumber == LogicalPosition.Line &&
var pin = BookmarkManager.Bookmarks.Find(b => b is PinBookmark && b.FileName == editor.FileName) as PinBookmark;
b.FileName == editor.FileName &&
b.Location.Line == location.Line) as PinBookmark; if (pin == null) {
bool found = false; pin = new PinBookmark(editor.FileName, LogicalPosition);
if (pin == null) { // show pinned DebuggerPopup
pin = new PinBookmark(editor.FileName, location); pin.Popup = new DebuggerPopup(null, true);
} pin.Popup.contentControl.LogicalPosition = LogicalPosition;
else { pin.Popup.contentControl.pinCloseControl.Mark = pin;
found = true; Rect rect = new Rect(this.DesiredSize);
} var point = this.PointToScreen(rect.TopRight);
pin.Popup.HorizontalOffset = 650;
pin.Popup.VerticalOffset = point.Y - 50;
pin.SavedPopupPosition = new Point { X = pin.Popup.HorizontalOffset, Y = pin.Popup.VerticalOffset };
pin.Nodes.Add(node);
var popup = pin.Popup; // actions
if (!found) { pin.Popup.Open();
// TODO set the pin inside the code editor pinning surface BookmarkManager.AddMark(pin);
// show pinned DebuggerPopup }
if (popup == null) { else
popup = new DebuggerPopup(null, true); {
}
popup.Mark = pin;
popup.Placement = PlacementMode.Absolute;
Rect rect = new Rect(this.DesiredSize);
var point = this.PointToScreen(rect.TopRight);
popup.HorizontalOffset = 650;
popup.StaysOpen = true;
popup.VerticalOffset = point.Y - 50;
pin.Popup = popup;
pin.Nodes.Add((ITreeNode)button.DataContext);
BookmarkManager.ToggleBookmark(
editor,
location.Line,
b => b is PinBookmark,
l => pin);
popup.Open();
}
else
{
popup = pin.Popup;
pin.Nodes.Add((ITreeNode)button.DataContext);
}
popup.ItemsSource = pin.Nodes; if (!pin.ContainsNode(node))
pin.Nodes.Add(node);
} }
} }
} }
void PinButton_Unchecked(object sender, RoutedEventArgs e) void PinButton_Unchecked(object sender, RoutedEventArgs e)
{ {
// remove from pinned DebuggerPopup if (!string.IsNullOrEmpty(editor.FileName)) {
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider; // remove from pinned DebuggerPopup
if (provider != null) { var pin = BookmarkManager.Bookmarks.Find(
ITextEditor editor = provider.TextEditor; b => b is PinBookmark &&
if (!string.IsNullOrEmpty(editor.FileName)) { b.LineNumber == LogicalPosition.Line &&
var pin = BookmarkManager.Bookmarks.Find(b => b is PinBookmark && b.FileName == editor.FileName) as PinBookmark;
b.FileName == editor.FileName && if (pin == null) return;
b.Location.Line == LogicalPosition.Line) as PinBookmark;
ToggleButton button = (ToggleButton)e.OriginalSource;
pin.RemoveNode((ITreeNode)button.DataContext);
// remove if no more data pins are available
if (pin.Nodes.Count == 0) {
pin.Popup.CloseSelfAndChildren();
ToggleButton button = (ToggleButton)e.OriginalSource; BookmarkManager.RemoveMark(pin);
pin.Nodes.Remove((ITreeNode)button.DataContext);
pin.Popup.ItemsSource = pin.Nodes;
} }
} }
}
#endregion
#region Comment
public event EventHandler CommentChanged;
public string Comment {
get { return CommentTextBox.Text; }
set { CommentTextBox.Text = value; }
} }
public void ShowComment(bool show) public void ShowComment(bool show)
@ -349,20 +391,17 @@ namespace ICSharpCode.SharpDevelop.Debugging
board.Begin(this); board.Begin(this);
} }
public string Comment {
get { return CommentTextBox.Text; }
set { CommentTextBox.Text = value; }
}
public event EventHandler CommentChanged;
void CommentTextBox_TextChanged(object sender, TextChangedEventArgs e) void CommentTextBox_TextChanged(object sender, TextChangedEventArgs e)
{ {
var handler = CommentChanged; var handler = CommentChanged;
if(handler != null) if (handler != null)
handler(this, EventArgs.Empty); handler(this, EventArgs.Empty);
} }
#endregion
#region Saved Adorner
class SavedAdorner : Adorner class SavedAdorner : Adorner
{ {
public SavedAdorner(UIElement adornedElement) : base(adornedElement) public SavedAdorner(UIElement adornedElement) : base(adornedElement)
@ -407,5 +446,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
board.Begin(this); board.Begin(this);
} }
} }
#endregion
} }
} }

2
src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs

@ -30,6 +30,8 @@ namespace ICSharpCode.SharpDevelop.Debugging
bool HasVisualizerCommands { get; } bool HasVisualizerCommands { get; }
bool IsChecked { get; set; }
bool SetText(string newValue); bool SetText(string newValue);
} }
} }

54
src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs

@ -5,12 +5,14 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Windows;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Bookmarks; using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
namespace Services.Debugger.Tooltips namespace Services.Debugger.Tooltips
{ {
@ -18,31 +20,32 @@ namespace Services.Debugger.Tooltips
{ {
string tooltip; string tooltip;
public event NotifyCollectionChangedEventHandler CollectionChanged; public DebuggerPopup Popup { get; set; }
public static readonly IImage PinImage = new ResourceServiceImage("Bookmarks.Pin"); public static readonly IImage PinImage = new ResourceServiceImage("Bookmarks.Pin");
public PinBookmark(FileName fileName, Location location) : base(fileName, location) public PinBookmark(FileName fileName, Location location) : base(fileName, location)
{ {
Nodes = new ObservableCollection<ITreeNode>(); Nodes = new ObservableCollection<ITreeNode>();
SavedNodes = new List<Tuple<string, string>>();
Nodes.CollectionChanged += new NotifyCollectionChangedEventHandler(Nodes_CollectionChanged); Nodes.CollectionChanged += new NotifyCollectionChangedEventHandler(Nodes_CollectionChanged);
IsVisibleInBookmarkPad = false; IsVisibleInBookmarkPad = false;
} }
//TODO this should not be here but onto pinning surface of the code editor
public DebuggerPopup Popup { get; set; }
void Nodes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) void Nodes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{ {
var handler = CollectionChanged; if (e.Action == NotifyCollectionChangedAction.Add ||
if (handler != null) e.Action == NotifyCollectionChangedAction.Remove)
handler.Invoke(this, e); Popup.contentControl.SetItemsSource(Nodes);
} }
public Point SavedPopupPosition { get; set; }
public ObservableCollection<ITreeNode> Nodes { get; set; } public ObservableCollection<ITreeNode> Nodes { get; set; }
public List<Tuple<string, string>> SavedNodes { get; set; } /// <summary>
/// Image, Name, Text
/// </summary>
public List<Tuple<string, string, string>> SavedNodes { get; set; }
public string Comment { get; set; } public string Comment { get; set; }
@ -57,4 +60,37 @@ namespace Services.Debugger.Tooltips
set { tooltip = value; } set { tooltip = value; }
} }
} }
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;
}
}
}
}
} }

59
src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinCloseControl.xaml.cs

@ -2,9 +2,15 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections.Specialized; using System.Collections.Generic;
using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Controls; 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.Bookmarks; using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Debugging;
@ -13,21 +19,35 @@ using ICSharpCode.SharpDevelop.Gui;
namespace Services.Debugger.Tooltips namespace Services.Debugger.Tooltips
{ {
/// <summary>
/// Interaction logic for PinCloseControl.xaml
/// </summary>
public partial class PinCloseControl : UserControl public partial class PinCloseControl : UserControl
{ {
readonly DebuggerTooltipControl control; private readonly DebuggerTooltipControl toolTipControl;
public PinCloseControl(DebuggerTooltipControl control) public PinBookmark Mark { get; set; }
public PinCloseControl(DebuggerTooltipControl parent)
{ {
Margin = new Thickness(5, 0, 0, 0); Margin = new Thickness(5, 0, 0, 0);
InitializeComponent(); InitializeComponent();
this.toolTipControl = parent;
DebuggerService.DebugStopped += new EventHandler(DebuggerService_DebugStopped);
DebuggerService.DebugStarted += new EventHandler(DebuggerService_DebugStarted);
this.toolTipControl.CommentChanged += delegate { Mark.Comment = this.toolTipControl.Comment; };
}
this.control = control; void DebuggerService_DebugStarted(object sender, EventArgs e)
this.control.CommentChanged += delegate { Mark.Comment = control.Comment; }; {
//this.toolTipControl.containingPopup.Open();
} }
private PinBookmark Mark { void DebuggerService_DebugStopped(object sender, EventArgs e)
get { return this.control.containingPopup.Mark; } {
this.toolTipControl.containingPopup.CloseSelfAndChildren();
} }
void Unpin() void Unpin()
@ -38,18 +58,17 @@ namespace Services.Debugger.Tooltips
void CloseButton_Click(object sender, RoutedEventArgs e) void CloseButton_Click(object sender, RoutedEventArgs e)
{ {
Unpin(); Unpin();
this.toolTipControl.containingPopup.CloseSelfAndChildren();
this.control.containingPopup.CloseSelfAndChildren();
} }
void CommentButton_Checked(object sender, RoutedEventArgs e) void CommentButton_Checked(object sender, RoutedEventArgs e)
{ {
this.control.ShowComment(true); this.toolTipControl.ShowComment(true);
} }
void CommentButton_Unchecked(object sender, RoutedEventArgs e) void CommentButton_Unchecked(object sender, RoutedEventArgs e)
{ {
this.control.ShowComment(false); this.toolTipControl.ShowComment(false);
} }
void UnpinButton_Checked(object sender, RoutedEventArgs e) void UnpinButton_Checked(object sender, RoutedEventArgs e)
@ -59,18 +78,10 @@ namespace Services.Debugger.Tooltips
void UnpinButton_Unchecked(object sender, RoutedEventArgs e) void UnpinButton_Unchecked(object sender, RoutedEventArgs e)
{ {
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider; if(BookmarkManager.Bookmarks.Contains(Mark))
if (provider != null) { BookmarkManager.RemoveMark(Mark);
ITextEditor editor = provider.TextEditor;
if (!string.IsNullOrEmpty(editor.FileName)) { BookmarkManager.AddMark(Mark);
BookmarkManager.ToggleBookmark(
editor,
Mark.Location.Line,
b => b.CanToggle && b is PinBookmark,
location => Mark);
}
}
} }
} }
} }

86
src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinningBinding.cs

@ -0,0 +1,86 @@
// 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 System.Windows;
using ICSharpCode.AvalonEdit;
using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
namespace Services.Debugger.Tooltips
{
public class PinningBinding : DefaultLanguageBinding
{
ITextEditor _editor;
public PinningBinding()
{}
public override void Attach(ITextEditor editor)
{
if (editor == null)
return;
_editor = 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 DebuggerPopup(null, true);
pin.Popup.HorizontalOffset = pin.SavedPopupPosition.X;
pin.Popup.VerticalOffset = pin.SavedPopupPosition.Y;
pin.Popup.contentControl.pinCloseControl.Mark = pin;
var nodes = new ObservableCollection<ITreeNode>();
foreach (var tuple in pin.SavedNodes) {
var node = new TreeNode();
node.IconImage =
new ResourceServiceImage(
!string.IsNullOrEmpty(tuple.Item1) ? tuple.Item1 : "Icons.16x16.Field");
node.Name = tuple.Item2;
node.Text = tuple.Item3;
nodes.Add(node);
}
pin.SavedNodes.Clear();
pin.Popup.SetItemsSource(nodes);
pin.Nodes = nodes;
pin.Popup.Open();
}
base.Attach(editor);
}
public override void Detach()
{
// save pins
var pins = BookmarkManager.Bookmarks.FindAll(
b => b is PinBookmark && b.FileName == _editor.FileName);
foreach (var bookmark in pins) {
var pin = (PinBookmark)bookmark;
pin.SavedPopupPosition = new Point
{
X = pin.Popup.HorizontalOffset,
Y = pin.Popup.VerticalOffset
};
pin.Popup.CloseSelfAndChildren();
}
base.Detach();
}
}
}

123
src/Main/Base/Project/Src/Services/Debugger/TreeNode.cs

@ -0,0 +1,123 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Media;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Debugging
{
/// <summary>
/// A node in the variable tree.
/// The node is imutable.
/// </summary>
public class TreeNode: IComparable<TreeNode>, ITreeNode
{
IImage iconImage = null;
string name = string.Empty;
string text = string.Empty;
string type = string.Empty;
IEnumerable<TreeNode> childNodes = null;
/// <summary>
/// The image displayed for this node.
/// </summary>
public IImage IconImage {
get { return iconImage; }
set { iconImage = value; }
}
/// <summary>
/// System.Windows.Media.ImageSource version of <see cref="IconImage"/>.
/// </summary>
public ImageSource ImageSource {
get {
return iconImage == null ? null : iconImage.ImageSource;
}
}
/// <summary>
/// System.Drawing.Image version of <see cref="IconImage"/>.
/// </summary>
public Image Image {
get {
return iconImage == null ? null : iconImage.Bitmap;
}
}
public string Name {
get { return name; }
set { name = value; }
}
public virtual string Text
{
get { return text; }
set { text = value; }
}
public virtual string Type {
get { return type; }
protected set { type = value; }
}
public virtual IEnumerable<TreeNode> ChildNodes {
get { return childNodes; }
protected set { childNodes = value; }
}
IEnumerable<ITreeNode> ITreeNode.ChildNodes {
get { return childNodes; }
}
public virtual bool HasChildNodes {
get { return childNodes != null; }
}
public virtual bool CanSetText {
get { return false; }
}
public virtual IEnumerable<IVisualizerCommand> VisualizerCommands {
get {
return null;
}
}
public virtual bool HasVisualizerCommands {
get {
return (VisualizerCommands != null) && (VisualizerCommands.Count() > 0);
}
}
public bool IsChecked { get; set; }
public TreeNode()
{
}
public TreeNode(IImage iconImage, string name, string text, string type, IEnumerable<TreeNode> childNodes)
{
this.iconImage = iconImage;
this.name = name;
this.text = text;
this.type = type;
this.childNodes = childNodes;
}
public int CompareTo(TreeNode other)
{
return this.Name.CompareTo(other.Name);
}
public virtual bool SetText(string newValue) {
return false;
}
}
}
Loading…
Cancel
Save