49 changed files with 2473 additions and 549 deletions
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 671 B |
@ -0,0 +1,229 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<UserControl |
||||||
|
x:Class="Debugger.AddIn.Tooltips.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:Debugger.AddIn.Tooltips" xmlns:core="http://icsharpcode.net/sharpdevelop/core" xmlns:localControls="clr-namespace:Debugger.AddIn.Tooltips" |
||||||
|
Background="Transparent"> |
||||||
|
<UserControl.Resources> |
||||||
|
<ResourceDictionary> |
||||||
|
<ResourceDictionary.MergedDictionaries> |
||||||
|
<ResourceDictionary |
||||||
|
Source="VisualizerPicker.xaml" /> |
||||||
|
<ResourceDictionary |
||||||
|
Source="PinControlsDictionary.xaml" /> |
||||||
|
</ResourceDictionary.MergedDictionaries> |
||||||
|
</ResourceDictionary> |
||||||
|
</UserControl.Resources> |
||||||
|
<StackPanel |
||||||
|
Orientation="Vertical"> |
||||||
|
<RepeatButton |
||||||
|
Name="btnUp" |
||||||
|
Focusable="False" |
||||||
|
Style="{StaticResource upButtonStyle}" |
||||||
|
Content="^" |
||||||
|
Click="BtnUp_Click"></RepeatButton> |
||||||
|
<DataGrid |
||||||
|
VerticalScrollBarVisibility="Disabled" |
||||||
|
HorizontalScrollBarVisibility="Disabled" |
||||||
|
GridLinesVisibility="None" |
||||||
|
RowHeight="18" |
||||||
|
MaxHeight="202" |
||||||
|
SelectionMode="Single" |
||||||
|
SelectionUnit="FullRow" |
||||||
|
ItemsSource="{Binding}" |
||||||
|
Name="dataGrid" |
||||||
|
AutoGenerateColumns="False" |
||||||
|
CanUserAddRows="False" |
||||||
|
HeadersVisibility="None" |
||||||
|
BorderBrush="Gray" |
||||||
|
BorderThickness="1"> |
||||||
|
<DataGrid.Background> |
||||||
|
<!-- Control backgound --> |
||||||
|
<LinearGradientBrush |
||||||
|
StartPoint="0,-0.03" |
||||||
|
EndPoint="0,1"> |
||||||
|
<GradientStop |
||||||
|
Color="White" /> |
||||||
|
<GradientStop |
||||||
|
Color="#FFFAFCFE" |
||||||
|
Offset="0.983" /> |
||||||
|
<GradientStop |
||||||
|
Color="#FFECF7FC" |
||||||
|
Offset="0.07" /> |
||||||
|
<GradientStop |
||||||
|
Color="#FFEEF7FA" |
||||||
|
Offset="0.436" /> |
||||||
|
</LinearGradientBrush> |
||||||
|
</DataGrid.Background> |
||||||
|
<DataGrid.RowStyle> |
||||||
|
<Style |
||||||
|
TargetType="{x:Type DataGridRow}"> |
||||||
|
<Setter |
||||||
|
Property="Background" |
||||||
|
Value="Transparent"></Setter> |
||||||
|
<Style.Triggers> |
||||||
|
<Trigger |
||||||
|
Property="IsMouseOver" |
||||||
|
Value="True"> |
||||||
|
<Setter |
||||||
|
Property="Background" |
||||||
|
Value="#FFE2F6FE" /> |
||||||
|
</Trigger> |
||||||
|
</Style.Triggers> |
||||||
|
</Style> |
||||||
|
</DataGrid.RowStyle> |
||||||
|
<DataGrid.CellStyle> |
||||||
|
<Style |
||||||
|
TargetType="{x:Type DataGridCell}"> |
||||||
|
<Setter |
||||||
|
Property="Focusable" |
||||||
|
Value="false" /> |
||||||
|
<!-- Focusable=true blocks shortcuts if cell is focused --> |
||||||
|
<Setter |
||||||
|
Property="BorderThickness" |
||||||
|
Value="0" /> |
||||||
|
<Style.Triggers> |
||||||
|
<Trigger |
||||||
|
Property="IsSelected" |
||||||
|
Value="True"> |
||||||
|
<!-- disable selection highlight --> |
||||||
|
<Setter |
||||||
|
Property="Foreground" |
||||||
|
Value="Black" /> |
||||||
|
<Setter |
||||||
|
Property="Background" |
||||||
|
Value="{x:Null}" /> |
||||||
|
</Trigger> |
||||||
|
</Style.Triggers> |
||||||
|
</Style> |
||||||
|
</DataGrid.CellStyle> |
||||||
|
<DataGrid.Columns> |
||||||
|
<DataGridTemplateColumn> |
||||||
|
<!-- "Plus" expander --> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<Grid |
||||||
|
Background="White"> |
||||||
|
<StackPanel |
||||||
|
VerticalAlignment="Center"> |
||||||
|
<ToggleButton |
||||||
|
x:Name="btnExpander" |
||||||
|
Style="{StaticResource ExpandCollapseToggleStyle}" |
||||||
|
Click="btnExpander_Click" |
||||||
|
Padding="0" |
||||||
|
Margin="0" /> |
||||||
|
</StackPanel> |
||||||
|
</Grid> |
||||||
|
<DataTemplate.Triggers> |
||||||
|
<DataTrigger |
||||||
|
Binding="{Binding Path=HasChildNodes}" |
||||||
|
Value="False"> |
||||||
|
<Setter |
||||||
|
TargetName="btnExpander" |
||||||
|
Property="Visibility" |
||||||
|
Value="Collapsed" /> |
||||||
|
</DataTrigger> |
||||||
|
</DataTemplate.Triggers> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
<!-- Icon --> |
||||||
|
<DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<Image |
||||||
|
Source="{Binding ImageSource}"></Image> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn |
||||||
|
MinWidth="20" |
||||||
|
Header="Name"> |
||||||
|
<!-- Name --> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<Border |
||||||
|
BorderBrush="#FFDDDDDD" |
||||||
|
BorderThickness="0 0 1 0"> |
||||||
|
<TextBlock |
||||||
|
Style="{StaticResource TextBlockStyle}" |
||||||
|
Text="{Binding Path=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" |
||||||
|
Text="{Binding Path=Text}" /> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn> |
||||||
|
<!-- Pin --> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<ToggleButton |
||||||
|
IsChecked="{Binding IsPinned}" |
||||||
|
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> |
||||||
|
</StackPanel> |
||||||
|
</UserControl> |
||||||
@ -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 |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Default Control used as content of SharpDevelop debugger tooltips.
|
||||||
|
/// </summary>
|
||||||
|
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<ITreeNode> lazyGrid; |
||||||
|
private IEnumerable<ITreeNode> 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<ITreeNode> 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<ITreeNode> ItemsSource { |
||||||
|
get { return this.itemsSource; } |
||||||
|
} |
||||||
|
|
||||||
|
public void SetItemsSource(IEnumerable<ITreeNode> value) { |
||||||
|
this.itemsSource = value; |
||||||
|
this.lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount); |
||||||
|
|
||||||
|
// HACK for updating the pins in tooltip
|
||||||
|
var observable = new List<ITreeNode>(); |
||||||
|
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<ITreeNode>(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; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool ShowAsPopup |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
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; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the child popup of this control, if it exists.
|
||||||
|
/// </summary>
|
||||||
|
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
|
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<UserControl |
||||||
|
Background="Transparent" |
||||||
|
x:Class="Debugger.AddIn.Tooltips.PinCloseControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||||
|
<UserControl.Resources> |
||||||
|
<ResourceDictionary> |
||||||
|
<ResourceDictionary.MergedDictionaries> |
||||||
|
<ResourceDictionary |
||||||
|
Source="PinControlsDictionary.xaml" /> |
||||||
|
</ResourceDictionary.MergedDictionaries> |
||||||
|
</ResourceDictionary> |
||||||
|
</UserControl.Resources> |
||||||
|
<StackPanel> |
||||||
|
<Button |
||||||
|
Name="CloseButton" |
||||||
|
Click="CloseButton_Click" |
||||||
|
Template="{StaticResource CloseButtonTemplate}" /> |
||||||
|
<ToggleButton |
||||||
|
Name="UnpinButton" |
||||||
|
Checked="UnpinButton_Checked" |
||||||
|
Unchecked="UnpinButton_Unchecked" |
||||||
|
Template="{StaticResource PinButtonTemplate}" /> |
||||||
|
<ToggleButton |
||||||
|
Name="CommentButton" |
||||||
|
Checked="CommentButton_Checked" |
||||||
|
Unchecked="CommentButton_Unchecked" |
||||||
|
Template="{StaticResource CommentButtonTemplate}" /> |
||||||
|
</StackPanel> |
||||||
|
</UserControl> |
||||||
@ -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<ShowingCommentEventArgs> ShowingComment; |
||||||
|
|
||||||
|
public PinCloseControl() |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
} |
||||||
|
|
||||||
|
public bool IsChecked { |
||||||
|
get { |
||||||
|
return UnpinButton.IsChecked.GetValueOrDefault(false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CloseButton_Click(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
var handler = Closed; |
||||||
|
if (handler != null) |
||||||
|
handler(this, EventArgs.Empty); |
||||||
|
} |
||||||
|
|
||||||
|
void CommentButton_Checked(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
var handler = ShowingComment; |
||||||
|
if (handler != null) |
||||||
|
handler(this, new ShowingCommentEventArgs(true)); |
||||||
|
} |
||||||
|
|
||||||
|
void CommentButton_Unchecked(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
var handler = ShowingComment; |
||||||
|
if (handler != null) |
||||||
|
handler(this, new ShowingCommentEventArgs(false)); |
||||||
|
} |
||||||
|
|
||||||
|
void UnpinButton_Checked(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
var handler = PinningChanged; |
||||||
|
if (handler != null) |
||||||
|
handler(this, EventArgs.Empty); |
||||||
|
} |
||||||
|
|
||||||
|
void UnpinButton_Unchecked(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
var handler = PinningChanged; |
||||||
|
if (handler != null) |
||||||
|
handler(this, EventArgs.Empty); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,337 @@ |
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
xmlns:local="clr-namespace:Debugger.AddIn.Tooltips" |
||||||
|
> |
||||||
|
<LinearGradientBrush x:Key="OrangeBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||||
|
<LinearGradientBrush.GradientStops> |
||||||
|
<GradientStop Offset="0" Color="White" /> |
||||||
|
<GradientStop Offset="0.5" Color="Orange" /> |
||||||
|
<GradientStop Offset="1" Color="Orange" /> |
||||||
|
</LinearGradientBrush.GradientStops> |
||||||
|
</LinearGradientBrush> |
||||||
|
|
||||||
|
<LinearGradientBrush x:Key="OrangePressedBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||||
|
<LinearGradientBrush.GradientStops> |
||||||
|
<GradientStop Offset="1" Color="White" /> |
||||||
|
<GradientStop Offset="0.5" Color="Orange" /> |
||||||
|
<GradientStop Offset="0" Color="Orange" /> |
||||||
|
</LinearGradientBrush.GradientStops> |
||||||
|
</LinearGradientBrush> |
||||||
|
|
||||||
|
<LinearGradientBrush x:Key="SilverBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||||
|
<LinearGradientBrush.GradientStops> |
||||||
|
<GradientStop Offset="0" Color="White" /> |
||||||
|
<GradientStop Offset="0.5" Color="LightGray" /> |
||||||
|
<GradientStop Offset="1" Color="LightGray" /> |
||||||
|
</LinearGradientBrush.GradientStops> |
||||||
|
</LinearGradientBrush> |
||||||
|
|
||||||
|
<LinearGradientBrush x:Key="SilverPressedBrushKey" EndPoint="0,1" StartPoint="0,0"> |
||||||
|
<LinearGradientBrush.GradientStops> |
||||||
|
<GradientStop Offset="1" Color="White" /> |
||||||
|
<GradientStop Offset="0.5" Color="LightGray" /> |
||||||
|
<GradientStop Offset="0" Color="LightGray" /> |
||||||
|
</LinearGradientBrush.GradientStops> |
||||||
|
</LinearGradientBrush> |
||||||
|
|
||||||
|
<ControlTemplate x:Key="CloseButtonTemplate" TargetType="Button"> |
||||||
|
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="2,2,0,0" BorderThickness="1" BorderBrush="Black" Background="{StaticResource SilverPressedBrushKey}"> |
||||||
|
<Canvas> |
||||||
|
<Line X1="3.5" X2="10.5" Y1="3.5" Y2="10.5" Stroke="Black" StrokeThickness="2"/> |
||||||
|
<Line X1="3.5" X2="10.5" Y1="10.5" Y2="3.5" Stroke="Black" StrokeThickness="2"/> |
||||||
|
</Canvas> |
||||||
|
</Border> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<Trigger Property="UIElement.IsMouseOver" Value="true"> |
||||||
|
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangeBrushKey}"/> |
||||||
|
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||||
|
</Trigger> |
||||||
|
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||||
|
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangePressedBrushKey}"/> |
||||||
|
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||||
|
</Trigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
|
||||||
|
<TransformGroup x:Key="Rotate"> |
||||||
|
<RotateTransform Angle="270" CenterX="7" CenterY="7"/> |
||||||
|
</TransformGroup> |
||||||
|
|
||||||
|
<TransformGroup x:Key="RotateUnpin"> |
||||||
|
<RotateTransform Angle="270" CenterX="7" CenterY="7"/> |
||||||
|
<RotateTransform Angle="-90" CenterX="7" CenterY="7"/> |
||||||
|
<ScaleTransform ScaleY="-1" CenterX="7" CenterY="7"/> |
||||||
|
</TransformGroup> |
||||||
|
|
||||||
|
<TransformGroup x:Key="RotatePin"> |
||||||
|
<RotateTransform Angle="-90" CenterX="7" CenterY="7"/> |
||||||
|
</TransformGroup> |
||||||
|
|
||||||
|
<TransformGroup x:Key="FlipComment"> |
||||||
|
<ScaleTransform CenterX="7" CenterY="7" ScaleY="-1"/> |
||||||
|
</TransformGroup> |
||||||
|
|
||||||
|
<ControlTemplate x:Key="PinButtonTemplate" TargetType="ToggleButton"> |
||||||
|
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="0" BorderThickness="1" BorderBrush="Black" Background="{StaticResource SilverPressedBrushKey}"> |
||||||
|
<Canvas Name="TheCanvas"> |
||||||
|
<Line X1="4" X2="10" Y1="2" Y2="2" Stroke="Black" StrokeThickness="1"/> |
||||||
|
<Line X1="9" X2="9" Y1="2" Y2="8" Stroke="Black" StrokeThickness="1"/> |
||||||
|
<Line X1="2" X2="12" Y1="8" Y2="8" Stroke="Black" StrokeThickness="1"/> |
||||||
|
<Rectangle Fill="Black" Width="2" Height="5" Canvas.Left="4" Canvas.Top="3"/> |
||||||
|
<Line X1="7" X2="7" Y1="9" Y2="12" Stroke="Black" StrokeThickness="1"/> |
||||||
|
</Canvas> |
||||||
|
</Border> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<Trigger Property="UIElement.IsMouseOver" Value="true"> |
||||||
|
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangeBrushKey}"/> |
||||||
|
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||||
|
</Trigger> |
||||||
|
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||||
|
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotatePin}"/> |
||||||
|
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangePressedBrushKey}"/> |
||||||
|
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||||
|
</Trigger> |
||||||
|
<Trigger Property="IsChecked" Value="true"> |
||||||
|
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotatePin}"/> |
||||||
|
</Trigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
|
||||||
|
<ControlTemplate x:Key="CommentButtonTemplate" TargetType="ToggleButton"> |
||||||
|
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="0,0,2,2" BorderThickness="1" BorderBrush="Black" Background="{StaticResource SilverPressedBrushKey}"> |
||||||
|
<Canvas Name="TheCanvas"> |
||||||
|
<Line X1="3" Y1="3" X2="7" Y2="7.5" Stroke="Black" StrokeThickness="1"/> |
||||||
|
<Line X1="7" Y1="7.4" X2="11" Y2="3" Stroke="Black" StrokeThickness="1"/> |
||||||
|
<Line X1="3" Y1="7.5" X2="7" Y2="12" Stroke="Black" StrokeThickness="1"/> |
||||||
|
<Line X1="7" Y1="12" X2="11" Y2="7.5" Stroke="Black" StrokeThickness="1"/> |
||||||
|
</Canvas> |
||||||
|
</Border> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<Trigger Property="UIElement.IsMouseOver" Value="true"> |
||||||
|
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangeBrushKey}"/> |
||||||
|
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||||
|
</Trigger> |
||||||
|
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||||
|
<Setter TargetName="TheBorder" Property="Background" Value="{StaticResource OrangePressedBrushKey}"/> |
||||||
|
<Setter TargetName="TheBorder" Property="BorderBrush" Value="Silver"/> |
||||||
|
</Trigger> |
||||||
|
<Trigger Property="IsChecked" Value="True"> |
||||||
|
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource FlipComment}"/> |
||||||
|
</Trigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
|
||||||
|
<SolidColorBrush x:Key="MouseOverPinBrush" Color="Black" /> |
||||||
|
|
||||||
|
<ControlTemplate x:Key="PinTooltipButtonTemplate" TargetType="ToggleButton"> |
||||||
|
<Border Width="16" Height="16" Name="TheBorder" CornerRadius="2" BorderBrush="Transparent" BorderThickness="1" Background="Transparent"> |
||||||
|
<Canvas RenderTransform="{StaticResource Rotate}" Name="TheCanvas"> |
||||||
|
<Line X1="4" X2="10" Y1="2" Y2="2" Stroke="Silver" StrokeThickness="1" Name="Line1"/> |
||||||
|
<Line X1="9" X2="9" Y1="2" Y2="8" Stroke="Silver" StrokeThickness="1" Name="Line2"/> |
||||||
|
<Line X1="2" X2="12" Y1="8" Y2="8" Stroke="Silver" StrokeThickness="1" Name="Line3"/> |
||||||
|
<Rectangle Fill="Silver" Width="2" Height="7" Canvas.Left="4" Canvas.Top="2" Name="Rectangle"/> |
||||||
|
<Line X1="7" X2="7" Y1="9" Y2="12" Stroke="Silver" StrokeThickness="1" Name="Line4"/> |
||||||
|
</Canvas> |
||||||
|
</Border> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<Trigger Property="ButtonBase.IsPressed" Value="True"> |
||||||
|
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotateUnpin}"/> |
||||||
|
</Trigger> |
||||||
|
<Trigger Property="ButtonBase.IsMouseOver" Value="True"> |
||||||
|
<Setter TargetName="Line1" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||||
|
<Setter TargetName="Line2" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||||
|
<Setter TargetName="Line3" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||||
|
<Setter TargetName="Line4" Property="Stroke" Value="{StaticResource MouseOverPinBrush}"/> |
||||||
|
<Setter TargetName="Rectangle" Property="Fill" Value="{StaticResource MouseOverPinBrush}"/> |
||||||
|
</Trigger> |
||||||
|
<Trigger Property="IsChecked" Value="True"> |
||||||
|
<Setter TargetName="TheCanvas" Property="RenderTransform" Value="{StaticResource RotateUnpin}"/> |
||||||
|
</Trigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
|
||||||
|
<Style |
||||||
|
TargetType="{x:Type TextBox}" |
||||||
|
x:Key="TextStyle"> |
||||||
|
<Setter |
||||||
|
Property="OverridesDefaultStyle" |
||||||
|
Value="True" /> |
||||||
|
<Setter |
||||||
|
Property="VerticalAlignment" |
||||||
|
Value="Center" /> |
||||||
|
<Setter |
||||||
|
Property="FontFamily" Value="Khmer UI" /> |
||||||
|
<Setter Property="FontSize" Value="12" /> |
||||||
|
<Setter |
||||||
|
Property="KeyboardNavigation.TabNavigation" |
||||||
|
Value="None" /> |
||||||
|
<Setter |
||||||
|
Property="FocusVisualStyle" |
||||||
|
Value="{x:Null}" /> |
||||||
|
<Setter |
||||||
|
Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate |
||||||
|
TargetType="{x:Type TextBoxBase}"> |
||||||
|
<Border |
||||||
|
Name="Border" |
||||||
|
Background="Transparent" |
||||||
|
BorderBrush="Transparent" |
||||||
|
BorderThickness="0"> |
||||||
|
<ScrollViewer |
||||||
|
Margin="0" |
||||||
|
Name="PART_ContentHost" /> |
||||||
|
</Border> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="TextBlockStyle"> |
||||||
|
<Setter Property="Margin" Value="4 0" /> |
||||||
|
<Setter |
||||||
|
Property="FontFamily" Value="Khmer UI" /> |
||||||
|
<Setter Property="FontSize" Value="12" /> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style x:Key="PinThumbStyle" TargetType="Thumb"> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="Thumb"> |
||||||
|
<StackPanel x:Name="Container"/> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style |
||||||
|
x:Key="ExpandCollapseToggleStyle" |
||||||
|
TargetType="{x:Type ToggleButton}"> |
||||||
|
<Setter |
||||||
|
Property="Focusable" |
||||||
|
Value="False" /> |
||||||
|
<Setter |
||||||
|
Property="Width" |
||||||
|
Value="19" /> |
||||||
|
<Setter |
||||||
|
Property="Height" |
||||||
|
Value="13" /> |
||||||
|
<Setter |
||||||
|
Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate |
||||||
|
TargetType="{x:Type ToggleButton}"> |
||||||
|
<Border |
||||||
|
Width="19" |
||||||
|
Height="13" |
||||||
|
Background="Transparent"> |
||||||
|
<Border |
||||||
|
Width="9" |
||||||
|
Height="9" |
||||||
|
BorderThickness="1" |
||||||
|
BorderBrush="#FF7898B5" |
||||||
|
CornerRadius="1" |
||||||
|
SnapsToDevicePixels="true"> |
||||||
|
<Border.Background> |
||||||
|
<LinearGradientBrush |
||||||
|
StartPoint="0,0" |
||||||
|
EndPoint="1,1"> |
||||||
|
<LinearGradientBrush.GradientStops> |
||||||
|
<GradientStop |
||||||
|
Color="White" |
||||||
|
Offset=".2" /> |
||||||
|
<GradientStop |
||||||
|
Color="#FFC0B7A6" |
||||||
|
Offset="1" /> |
||||||
|
</LinearGradientBrush.GradientStops> |
||||||
|
</LinearGradientBrush> |
||||||
|
</Border.Background> |
||||||
|
<Path |
||||||
|
x:Name="ExpandPath" |
||||||
|
Margin="1,1,1,1" |
||||||
|
Fill="Black" |
||||||
|
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z" /> |
||||||
|
</Border> |
||||||
|
</Border> |
||||||
|
<ControlTemplate.Triggers> |
||||||
|
<Trigger |
||||||
|
Property="IsChecked" |
||||||
|
Value="True"> |
||||||
|
<Setter |
||||||
|
Property="Data" |
||||||
|
TargetName="ExpandPath" |
||||||
|
Value="M 0 2 L 0 3 L 5 3 L 5 2 Z" /> |
||||||
|
</Trigger> |
||||||
|
</ControlTemplate.Triggers> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
<Style |
||||||
|
x:Key="upDownBorderStyle" |
||||||
|
TargetType="{x:Type Border}"> |
||||||
|
<Setter |
||||||
|
Property="BorderBrush" |
||||||
|
Value="Gray" /> |
||||||
|
<Setter |
||||||
|
Property="HorizontalAlignment" |
||||||
|
Value="Stretch" /> |
||||||
|
<Setter |
||||||
|
Property="Margin" |
||||||
|
Value="0" /> |
||||||
|
<Setter |
||||||
|
Property="Padding" |
||||||
|
Value="0" /> |
||||||
|
<Setter |
||||||
|
Property="Background" |
||||||
|
Value="#FFECF7FC" /> |
||||||
|
<Setter |
||||||
|
Property="Height" |
||||||
|
Value="14" /> |
||||||
|
<Style.Triggers> |
||||||
|
<DataTrigger |
||||||
|
Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" |
||||||
|
Value="False"> |
||||||
|
<Setter |
||||||
|
Property="Background" |
||||||
|
Value="#FFE0E0E0"></Setter> |
||||||
|
</DataTrigger> |
||||||
|
</Style.Triggers> |
||||||
|
</Style> |
||||||
|
<Style |
||||||
|
x:Key="upButtonStyle" |
||||||
|
TargetType="{x:Type RepeatButton}"> |
||||||
|
<Setter |
||||||
|
Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate |
||||||
|
TargetType="{x:Type RepeatButton}"> |
||||||
|
<Border |
||||||
|
Style="{StaticResource upDownBorderStyle}" |
||||||
|
BorderThickness="1 1 1 0"> |
||||||
|
<ContentPresenter |
||||||
|
HorizontalAlignment="Center"></ContentPresenter> |
||||||
|
</Border> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
<Style |
||||||
|
x:Key="downButtonStyle" |
||||||
|
TargetType="{x:Type RepeatButton}"> |
||||||
|
<Setter |
||||||
|
Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate |
||||||
|
TargetType="{x:Type RepeatButton}"> |
||||||
|
<Border |
||||||
|
Style="{StaticResource upDownBorderStyle}" |
||||||
|
BorderThickness="1 0 1 1"> |
||||||
|
<ContentPresenter |
||||||
|
HorizontalAlignment="Center"></ContentPresenter> |
||||||
|
</Border> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
</ResourceDictionary> |
||||||
@ -0,0 +1,262 @@ |
|||||||
|
<UserControl x:Class="Debugger.AddIn.Tooltips.PinDebuggerControl" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:local="clr-namespace:Debugger.AddIn.Tooltips" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||||
|
> |
||||||
|
<UserControl.Resources> |
||||||
|
<ResourceDictionary> |
||||||
|
<ResourceDictionary.MergedDictionaries> |
||||||
|
<ResourceDictionary |
||||||
|
Source="PinControlsDictionary.xaml" /> |
||||||
|
</ResourceDictionary.MergedDictionaries> |
||||||
|
</ResourceDictionary> |
||||||
|
</UserControl.Resources> |
||||||
|
<Grid> |
||||||
|
<Grid.Resources> |
||||||
|
<LinearGradientBrush x:Key="DataGridBackground" |
||||||
|
StartPoint="0,-0.03" |
||||||
|
EndPoint="0,1"> |
||||||
|
<GradientStop |
||||||
|
Color="White" /> |
||||||
|
<GradientStop |
||||||
|
Color="#FFFAFCFE" |
||||||
|
Offset="0.983" /> |
||||||
|
<GradientStop |
||||||
|
Color="#FFECF7FC" |
||||||
|
Offset="0.07" /> |
||||||
|
<GradientStop |
||||||
|
Color="#FFEEF7FA" |
||||||
|
Offset="0.436" /> |
||||||
|
</LinearGradientBrush> |
||||||
|
|
||||||
|
<Style x:Key="CellStyle" |
||||||
|
TargetType="{x:Type DataGridCell}"> |
||||||
|
<Setter |
||||||
|
Property="Focusable" |
||||||
|
Value="false" /> |
||||||
|
<!-- Focusable=true blocks shortcuts if cell is focused --> |
||||||
|
<Setter |
||||||
|
Property="BorderThickness" |
||||||
|
Value="0" /> |
||||||
|
<Setter Property="Width" Value="Auto" /> |
||||||
|
<Style.Triggers> |
||||||
|
<Trigger |
||||||
|
Property="IsSelected" |
||||||
|
Value="True"> |
||||||
|
<!-- disable selection highlight --> |
||||||
|
<Setter |
||||||
|
Property="Foreground" |
||||||
|
Value="Black" /> |
||||||
|
<Setter |
||||||
|
Property="Background" |
||||||
|
Value="{x:Null}" /> |
||||||
|
</Trigger> |
||||||
|
</Style.Triggers> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style x:Key="RowStyle" |
||||||
|
TargetType="{x:Type DataGridRow}"> |
||||||
|
<Setter |
||||||
|
Property="Background" |
||||||
|
Value="Transparent"></Setter> |
||||||
|
</Style> |
||||||
|
|
||||||
|
<Style x:Key="DataGridStyle" TargetType="DataGrid"> |
||||||
|
<Setter Property="VerticalScrollBarVisibility" Value="Disabled"/> |
||||||
|
<Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/> |
||||||
|
<Setter Property="GridLinesVisibility" Value="None"/> |
||||||
|
<Setter Property="RowHeight" Value="18"/> |
||||||
|
<Setter Property="MaxHeight" Value="202"/> |
||||||
|
<Setter Property="MinHeight" Value="20" /> |
||||||
|
<Setter Property="SelectionMode" Value="Single"/> |
||||||
|
<Setter Property="SelectionUnit" Value="FullRow"/> |
||||||
|
<Setter Property="AutoGenerateColumns" Value="False"/> |
||||||
|
<Setter Property="CanUserAddRows" Value="False"/> |
||||||
|
<Setter Property="HeadersVisibility" Value="None"/> |
||||||
|
<Setter Property="BorderBrush" Value="Gray"/> |
||||||
|
<Setter Property="Background" Value="{StaticResource DataGridBackground}"/> |
||||||
|
<Setter Property="CellStyle" Value="{StaticResource CellStyle}"/> |
||||||
|
<Setter Property="RowStyle" Value="{StaticResource RowStyle}"/> |
||||||
|
<Style.Triggers> |
||||||
|
<Trigger Property="IsMouseOver" Value="True"> |
||||||
|
<Setter Property="Cursor" Value="Arrow"/> |
||||||
|
</Trigger> |
||||||
|
</Style.Triggers> |
||||||
|
</Style> |
||||||
|
</Grid.Resources> |
||||||
|
<Grid.ColumnDefinitions> |
||||||
|
<ColumnDefinition Width="Auto"/> |
||||||
|
<ColumnDefinition Width="Auto"/> |
||||||
|
</Grid.ColumnDefinitions> |
||||||
|
<StackPanel VerticalAlignment="Center"> |
||||||
|
<Grid> |
||||||
|
<Grid.ColumnDefinitions> |
||||||
|
<ColumnDefinition Width="Auto"/> |
||||||
|
<ColumnDefinition Width="Auto"/> |
||||||
|
<ColumnDefinition Width="Auto"/> |
||||||
|
</Grid.ColumnDefinitions> |
||||||
|
<DataGrid |
||||||
|
Width="21" |
||||||
|
BorderThickness="1,1,0,1" |
||||||
|
Background="White" |
||||||
|
x:Name="ExpandersGrid" |
||||||
|
Style="{StaticResource DataGridStyle}" |
||||||
|
ItemsSource="{Binding}"> |
||||||
|
<DataGrid.Columns> |
||||||
|
<DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<Grid |
||||||
|
Background="White"> |
||||||
|
<StackPanel |
||||||
|
VerticalAlignment="Center"> |
||||||
|
<ToggleButton |
||||||
|
x:Name="btnExpander" |
||||||
|
Style="{StaticResource ExpandCollapseToggleStyle}" |
||||||
|
Checked="BtnExpander_Checked" |
||||||
|
Unchecked="BtnExpander_Unchecked" |
||||||
|
Padding="0" |
||||||
|
Margin="0" /> |
||||||
|
</StackPanel> |
||||||
|
</Grid> |
||||||
|
<DataTemplate.Triggers> |
||||||
|
<DataTrigger |
||||||
|
Binding="{Binding Path=HasChildNodes}" |
||||||
|
Value="False"> |
||||||
|
<Setter |
||||||
|
TargetName="btnExpander" |
||||||
|
Property="Visibility" |
||||||
|
Value="Collapsed" /> |
||||||
|
</DataTrigger> |
||||||
|
</DataTemplate.Triggers> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
</DataGrid.Columns> |
||||||
|
</DataGrid> |
||||||
|
|
||||||
|
<DataGrid |
||||||
|
BorderThickness="0,1,0,1" |
||||||
|
Grid.Column="1" |
||||||
|
IsEnabled="False" |
||||||
|
ColumnWidth="SizeToCells" |
||||||
|
Style="{StaticResource DataGridStyle}" |
||||||
|
ItemsSource="{Binding}" |
||||||
|
Foreground="Black" |
||||||
|
Name="dataGrid"> |
||||||
|
<DataGrid.Columns> |
||||||
|
<DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<Image |
||||||
|
Source="{Binding ImageSource}"></Image> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn |
||||||
|
MinWidth="20" |
||||||
|
Header="Name"> |
||||||
|
<!-- Name --> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<Border |
||||||
|
BorderBrush="#FFDDDDDD" |
||||||
|
BorderThickness="0 0 1 0"> |
||||||
|
<TextBlock |
||||||
|
Style="{StaticResource TextBlockStyle}" |
||||||
|
Text="{Binding Path=FullName, Mode=OneWay}" |
||||||
|
VerticalAlignment="Center"></TextBlock> |
||||||
|
</Border> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn IsReadOnly="True" |
||||||
|
Width="SizeToCells" |
||||||
|
Header="Text"> |
||||||
|
<!-- Text (value) --> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<TextBox |
||||||
|
Style="{StaticResource TextStyle}" |
||||||
|
IsEnabled="false" |
||||||
|
Text="{Binding Path=Text}" /> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
</DataGrid.Columns> |
||||||
|
</DataGrid> |
||||||
|
|
||||||
|
<DataGrid |
||||||
|
MaxWidth="20" |
||||||
|
BorderThickness="1" |
||||||
|
Grid.Column="2" |
||||||
|
x:Name="ImagesGrid" |
||||||
|
Style="{StaticResource DataGridStyle}" |
||||||
|
ItemsSource="{Binding}"> |
||||||
|
<DataGrid.Columns> |
||||||
|
<DataGridTemplateColumn> |
||||||
|
<DataGridTemplateColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<Border |
||||||
|
Name="ImageBorder" |
||||||
|
CornerRadius="7" |
||||||
|
BorderBrush="Transparent" |
||||||
|
BorderThickness="1" |
||||||
|
Height="14" |
||||||
|
Width="14"> |
||||||
|
<Image Width="9" Height="9" Margin="2 2" |
||||||
|
x:Name="RefreshContentImage" |
||||||
|
MouseDown="RefreshContentImage_MouseDown" |
||||||
|
Tag="{Binding}" |
||||||
|
Source="{core:GetBitmap Icons.16x16.Refresh}"/> |
||||||
|
</Border> |
||||||
|
<DataTemplate.Triggers> |
||||||
|
<Trigger Property="IsMouseOver" Value="true"> |
||||||
|
<Setter |
||||||
|
TargetName="ImageBorder" |
||||||
|
Property="BorderBrush" |
||||||
|
Value="Gray" /> |
||||||
|
</Trigger> |
||||||
|
</DataTemplate.Triggers> |
||||||
|
</DataTemplate> |
||||||
|
</DataGridTemplateColumn.CellTemplate> |
||||||
|
</DataGridTemplateColumn> |
||||||
|
</DataGrid.Columns> |
||||||
|
</DataGrid> |
||||||
|
</Grid> |
||||||
|
<!-- comment textbox --> |
||||||
|
<Border |
||||||
|
Name="BorderComment" |
||||||
|
Background="White" |
||||||
|
BorderThickness="1,0,1,1" |
||||||
|
BorderBrush="Gray" |
||||||
|
Height="0" |
||||||
|
MaxHeight="50"> |
||||||
|
<TextBox |
||||||
|
FontFamily="Khmer UI" |
||||||
|
BorderBrush="Gray" |
||||||
|
BorderThickness="1" |
||||||
|
FontSize="12" |
||||||
|
Name="CommentTextBox" |
||||||
|
TextChanged="CommentTextBox_TextChanged" |
||||||
|
Margin="3"/> |
||||||
|
</Border> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<local:PinCloseControl |
||||||
|
VerticalAlignment="Center" |
||||||
|
Background="Transparent" |
||||||
|
Grid.Column="1" |
||||||
|
Margin="5,0,0,0" |
||||||
|
x:Name="PinCloseControl"> |
||||||
|
<local:PinCloseControl.Effect> |
||||||
|
<DropShadowEffect |
||||||
|
ShadowDepth="5" |
||||||
|
Direction="330" |
||||||
|
Color="Black" |
||||||
|
Opacity="0.5"/> |
||||||
|
</local:PinCloseControl.Effect> |
||||||
|
</local:PinCloseControl> |
||||||
|
</Grid> |
||||||
|
</UserControl> |
||||||
@ -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<ITreeNode> lazyExpandersGrid; |
||||||
|
private LazyItemsControl<ITreeNode> lazyGrid; |
||||||
|
private LazyItemsControl<ITreeNode> lazyImagesGrid; |
||||||
|
private IEnumerable<ITreeNode> itemsSource; |
||||||
|
|
||||||
|
public PinDebuggerControl() |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
|
||||||
|
if (!DebuggerService.IsDebuggerStarted) |
||||||
|
Opacity = MINIMUM_OPACITY; |
||||||
|
this.PinCloseControl.Opacity = 0; |
||||||
|
|
||||||
|
Loaded += OnLoaded; |
||||||
|
this.PinCloseControl.Closed += PinCloseControl_Closed; |
||||||
|
this.PinCloseControl.ShowingComment += PinCloseControl_ShowingComment; |
||||||
|
this.PinCloseControl.PinningChanged += PinCloseControl_PinningChanged; |
||||||
|
|
||||||
|
BookmarkManager.Removed += OnBookmarkRemoved; |
||||||
|
|
||||||
|
currentDebugger = (WindowsDebugger)DebuggerService.CurrentDebugger; |
||||||
|
|
||||||
|
currentDebugger.DebugStopped += OnDebugStopped; |
||||||
|
currentDebugger.ProcessSelected += OnProcessSelected; |
||||||
|
|
||||||
|
if (currentDebugger.DebuggedProcess != null) |
||||||
|
currentDebugger.DebuggedProcess.Paused += OnDebuggedProcessPaused; |
||||||
|
} |
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
public PinBookmark Mark { get; set; } |
||||||
|
|
||||||
|
public IEnumerable<ITreeNode> ItemsSource |
||||||
|
{ |
||||||
|
get { return this.itemsSource; } |
||||||
|
set { |
||||||
|
itemsSource = value; |
||||||
|
var items = new VirtualizingIEnumerable<ITreeNode>(value); |
||||||
|
lazyExpandersGrid = new LazyItemsControl<ITreeNode>(this.ExpandersGrid, InitialItemsCount); |
||||||
|
lazyExpandersGrid.ItemsSource = items; |
||||||
|
|
||||||
|
lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount); |
||||||
|
lazyGrid.ItemsSource = items; |
||||||
|
|
||||||
|
lazyImagesGrid = new LazyItemsControl<ITreeNode>(this.ImagesGrid, InitialItemsCount); |
||||||
|
lazyImagesGrid.ItemsSource = items; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Relative position of the pin with respect to the screen.
|
||||||
|
/// </summary>
|
||||||
|
public Point Location { get; set; } |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Main operations
|
||||||
|
|
||||||
|
public void Open() |
||||||
|
{ |
||||||
|
Pin(); |
||||||
|
} |
||||||
|
|
||||||
|
public void Close() |
||||||
|
{ |
||||||
|
CloseChildPopups(); |
||||||
|
Unpin(); |
||||||
|
|
||||||
|
BookmarkManager.Removed -= OnBookmarkRemoved; |
||||||
|
if (currentDebugger != null) { |
||||||
|
currentDebugger.DebugStopped -= OnDebugStopped; |
||||||
|
currentDebugger.ProcessSelected -= OnProcessSelected; |
||||||
|
currentDebugger = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Pin() |
||||||
|
{ |
||||||
|
var provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider; |
||||||
|
if(provider != null) { |
||||||
|
var pinLayer = PinningBinding.GetPinlayer(provider.TextEditor); |
||||||
|
if (pinLayer != null) |
||||||
|
pinLayer.Pin(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void Unpin() |
||||||
|
{ |
||||||
|
var provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider; |
||||||
|
if(provider != null) { |
||||||
|
var pinLayer = PinningBinding.GetPinlayer(provider.TextEditor); |
||||||
|
if (pinLayer != null) |
||||||
|
pinLayer.Unpin(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Debugger events
|
||||||
|
|
||||||
|
void OnDebugStopped(object sender, EventArgs e) |
||||||
|
{ |
||||||
|
if (currentDebugger.DebuggedProcess != null) |
||||||
|
currentDebugger.DebuggedProcess.Paused -= OnDebuggedProcessPaused; |
||||||
|
} |
||||||
|
|
||||||
|
void OnProcessSelected(object sender, ProcessEventArgs e) |
||||||
|
{ |
||||||
|
Opacity = 1d; |
||||||
|
if (currentDebugger.DebuggedProcess != null) |
||||||
|
currentDebugger.DebuggedProcess.Paused += OnDebuggedProcessPaused; |
||||||
|
} |
||||||
|
|
||||||
|
void OnDebuggedProcessPaused(object sender, ProcessEventArgs e) |
||||||
|
{ |
||||||
|
//var nodes = new StackFrameNode(e.Process.SelectedStackFrame).ChildNodes;
|
||||||
|
|
||||||
|
// if (!lazyGrid.ItemsSource.ContainsNode(node))
|
||||||
|
// return;
|
||||||
|
// TODO : find the current expression so we don't update every pin
|
||||||
|
// var observable = new List<ITreeNode>();
|
||||||
|
//
|
||||||
|
// foreach (var node in lazyGrid.ItemsSource) {
|
||||||
|
// var resultNode = currentDebugger.GetNode(node.FullName);
|
||||||
|
// // HACK for updating the pins in tooltip
|
||||||
|
// observable.Add(resultNode);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // update UI
|
||||||
|
// var newSource = new VirtualizingIEnumerable<ITreeNode>(observable);
|
||||||
|
// lazyGrid.ItemsSource = newSource;
|
||||||
|
// lazyExpandersGrid.ItemsSource = newSource;
|
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Expand buton
|
||||||
|
|
||||||
|
private ToggleButton expandedButton; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the child popup of this control, if it exists.
|
||||||
|
/// </summary>
|
||||||
|
void CloseChildPopups() |
||||||
|
{ |
||||||
|
if (this.expandedButton != null) { |
||||||
|
this.expandedButton = null; |
||||||
|
// nice simple example of indirect recursion
|
||||||
|
this.childPopup.CloseSelfAndChildren(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void BtnExpander_Checked(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
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<ITreeNode>(); |
||||||
|
var source = lazyGrid.ItemsSource; |
||||||
|
source.ForEach(item => { |
||||||
|
if (item.CompareTo(node) == 0) |
||||||
|
observable.Add(resultNode); |
||||||
|
else |
||||||
|
observable.Add(item); |
||||||
|
}); |
||||||
|
|
||||||
|
Mark.Nodes = observable; |
||||||
|
// update UI
|
||||||
|
var newSource = new VirtualizingIEnumerable<ITreeNode>(observable); |
||||||
|
lazyGrid.ItemsSource = newSource; |
||||||
|
lazyExpandersGrid.ItemsSource = newSource; |
||||||
|
} |
||||||
|
|
||||||
|
#region 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
|
||||||
|
} |
||||||
|
} |
||||||
@ -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 |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Pin layer class. This class handles the pinning and unpinning operations.
|
||||||
|
/// </summary>
|
||||||
|
public class PinLayer : Canvas |
||||||
|
{ |
||||||
|
private double verticalOffset = 0; |
||||||
|
private double horizontalOffset = 0; |
||||||
|
|
||||||
|
private TextView textView; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PinLayer constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textArea">Text area for this layer.</param>
|
||||||
|
public PinLayer(TextArea textArea) |
||||||
|
{ |
||||||
|
textView = textArea.TextView; |
||||||
|
textView.VisualLinesChanged += textView_VisualLinesChanged; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pins an element;
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">Element to pin.</param>
|
||||||
|
public void Pin(PinDebuggerControl element) |
||||||
|
{ |
||||||
|
if (element == null) |
||||||
|
throw new NullReferenceException("Element is null!"); |
||||||
|
|
||||||
|
Thumb currentThumb = new Thumb(); |
||||||
|
// check for saved position
|
||||||
|
if (!element.Mark.PinPosition.HasValue) { |
||||||
|
// this is satisfied when pinning the first time
|
||||||
|
element.Mark.PinPosition = new Point { |
||||||
|
X = element.Location.X + textView.HorizontalOffset, |
||||||
|
Y = element.Location.Y + textView.VerticalOffset |
||||||
|
}; |
||||||
|
|
||||||
|
Canvas.SetTop(currentThumb, element.Location.Y); |
||||||
|
Canvas.SetLeft(currentThumb, element.Location.X); |
||||||
|
} |
||||||
|
else { |
||||||
|
// this is satisfied when loading the pins - so we might have hidden pins
|
||||||
|
element.Location = new Point { |
||||||
|
X = element.Mark.PinPosition.Value.X - textView.HorizontalOffset, |
||||||
|
Y = element.Mark.PinPosition.Value.Y - textView.VerticalOffset |
||||||
|
}; |
||||||
|
|
||||||
|
Canvas.SetTop(currentThumb, element.Mark.PinPosition.Value.Y); |
||||||
|
Canvas.SetLeft(currentThumb, element.Mark.PinPosition.Value.X); |
||||||
|
} |
||||||
|
|
||||||
|
currentThumb.Style = element.TryFindResource("PinThumbStyle") as Style; |
||||||
|
currentThumb.ApplyTemplate(); |
||||||
|
currentThumb.DragDelta += onDragDelta; |
||||||
|
currentThumb.DragStarted += currentThumb_DragStarted; |
||||||
|
currentThumb.DragCompleted += currentThumb_DragCompleted; |
||||||
|
|
||||||
|
var container = TryFindChild<StackPanel>(currentThumb); |
||||||
|
container.Children.Add(element); |
||||||
|
this.Children.Add(currentThumb); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unpins an element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">Element to unpin.</param>
|
||||||
|
public void Unpin(PinDebuggerControl element) |
||||||
|
{ |
||||||
|
if (element == null) |
||||||
|
throw new NullReferenceException("Element is null!"); |
||||||
|
|
||||||
|
foreach (var thumb in this.Children) { |
||||||
|
PinDebuggerControl pinControl = TryFindChild<PinDebuggerControl>((DependencyObject)thumb); |
||||||
|
if (pinControl != null && pinControl == element) |
||||||
|
{ |
||||||
|
this.Children.Remove((UIElement)thumb); |
||||||
|
element.Close(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void textView_VisualLinesChanged(object sender, EventArgs e) |
||||||
|
{ |
||||||
|
foreach (var ctrl in this.Children) { |
||||||
|
var currentThumb = ctrl as Thumb; |
||||||
|
PinDebuggerControl pinControl = TryFindChild<PinDebuggerControl>(currentThumb); |
||||||
|
if (pinControl != null) |
||||||
|
{ |
||||||
|
// update relative location
|
||||||
|
Point location = pinControl.Location; |
||||||
|
location.X += horizontalOffset - textView.HorizontalOffset; |
||||||
|
location.Y += verticalOffset - textView.VerticalOffset; |
||||||
|
|
||||||
|
Canvas.SetLeft(currentThumb, location.X); |
||||||
|
Canvas.SetTop(currentThumb, location.Y); |
||||||
|
|
||||||
|
pinControl.Location = location; |
||||||
|
pinControl.Mark.PinPosition = new Point { |
||||||
|
X = location.X + textView.HorizontalOffset, |
||||||
|
Y = location.Y + textView.VerticalOffset, |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
verticalOffset = textView.VerticalOffset; |
||||||
|
horizontalOffset = textView.HorizontalOffset; |
||||||
|
} |
||||||
|
|
||||||
|
#region Mouse move
|
||||||
|
|
||||||
|
void onDragDelta(object sender, DragDeltaEventArgs e) |
||||||
|
{ |
||||||
|
Thumb currnetThumb = (Thumb)sender; |
||||||
|
currnetThumb.Cursor = Cursors.Arrow; |
||||||
|
double left = Canvas.GetLeft(currnetThumb) + e.HorizontalChange; |
||||||
|
double top = Canvas.GetTop(currnetThumb) + e.VerticalChange; |
||||||
|
|
||||||
|
Canvas.SetLeft(currnetThumb, left); |
||||||
|
Canvas.SetTop(currnetThumb, top); |
||||||
|
} |
||||||
|
|
||||||
|
void currentThumb_DragCompleted(object sender, DragCompletedEventArgs e) |
||||||
|
{ |
||||||
|
Thumb currnetThumb = (Thumb)sender; |
||||||
|
currnetThumb.Cursor = Cursors.Arrow; |
||||||
|
|
||||||
|
var pinControl = TryFindChild<PinDebuggerControl>(currnetThumb); |
||||||
|
if (pinControl != null) { |
||||||
|
double left = Canvas.GetLeft(currnetThumb); |
||||||
|
double top = Canvas.GetTop(currnetThumb); |
||||||
|
pinControl.Opacity = 1d; |
||||||
|
pinControl.Location = new Point { X = left, Y = top }; |
||||||
|
|
||||||
|
// pin's position is with respect to the layer.
|
||||||
|
pinControl.Mark.PinPosition = |
||||||
|
new Point |
||||||
|
{ |
||||||
|
X = textView.HorizontalOffset + left, |
||||||
|
Y = textView.VerticalOffset + top |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void currentThumb_DragStarted(object sender, DragStartedEventArgs e) |
||||||
|
{ |
||||||
|
Thumb currnetThumb = (Thumb)sender; |
||||||
|
currnetThumb.Cursor = Cursors.Arrow; |
||||||
|
|
||||||
|
var pinControl = TryFindChild<PinDebuggerControl>(currnetThumb); |
||||||
|
if (pinControl != null) |
||||||
|
pinControl.Opacity = 1d; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Static helpers
|
||||||
|
|
||||||
|
static T TryFindChild<T>(DependencyObject root) where T : DependencyObject |
||||||
|
{ |
||||||
|
return ContextActionsControl.SearchVisualTree<T>(root); |
||||||
|
} |
||||||
|
|
||||||
|
static T TryFindParent<T>(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<T>(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
|
||||||
|
} |
||||||
|
} |
||||||
@ -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<ITreeNode>(); |
||||||
|
foreach (var tuple in pin.SavedNodes) { |
||||||
|
string imageName = !string.IsNullOrEmpty(tuple.Item1) ? tuple.Item1 : "Icons.16x16.Field"; |
||||||
|
var node = new Debugger.AddIn.TreeModel.SavedTreeNode( |
||||||
|
new ResourceServiceImage(imageName), |
||||||
|
tuple.Item2, |
||||||
|
tuple.Item3); |
||||||
|
node.ImageName = imageName; |
||||||
|
nodes.Add(node); |
||||||
|
} |
||||||
|
|
||||||
|
pin.SavedNodes.Clear(); |
||||||
|
pin.Popup.ItemsSource = nodes; |
||||||
|
pin.Nodes = nodes; |
||||||
|
|
||||||
|
pinLayer.Pin((PinDebuggerControl)pin.Popup); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void ClosePins(ITextEditor editor) |
||||||
|
{ |
||||||
|
// save pins
|
||||||
|
var pins = BookmarkManager.Bookmarks.FindAll( |
||||||
|
b => b is PinBookmark && b.FileName == editor.FileName); |
||||||
|
|
||||||
|
foreach (var bookmark in pins) { |
||||||
|
var pin = (PinBookmark)bookmark; |
||||||
|
if (!pin.PinPosition.HasValue) |
||||||
|
pin.PinPosition = pin.Popup.Location; |
||||||
|
|
||||||
|
// nodes
|
||||||
|
if (pin.SavedNodes == null) |
||||||
|
pin.SavedNodes = new System.Collections.Generic.List<Tuple<string, string, string>>(); |
||||||
|
|
||||||
|
foreach (var node in pin.Nodes) { |
||||||
|
pin.SavedNodes.Add( |
||||||
|
new Tuple<string, string, string>( |
||||||
|
"Icons.16x16.Field", |
||||||
|
node.FullName, |
||||||
|
node.Text)); |
||||||
|
} |
||||||
|
|
||||||
|
pinLayer.Unpin((PinDebuggerControl)pin.Popup); |
||||||
|
pin.Popup = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static PinLayer GetPinlayer(ITextEditor editor) { |
||||||
|
var textEditor = editor.GetService(typeof(TextEditor)) as TextEditor; |
||||||
|
if (textEditor != null) { |
||||||
|
return textEditor.TextArea.TextView.Layers[3] as PinLayer; |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,13 +1,15 @@ |
|||||||
// 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 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 ICSharpCode.Core; |
|
||||||
using System; |
using System; |
||||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||||
using System.Linq; |
using System.Linq; |
||||||
using System.Windows.Controls; |
using System.Windows.Controls; |
||||||
|
|
||||||
namespace ICSharpCode.SharpDevelop.Debugging |
using ICSharpCode.Core; |
||||||
|
using ICSharpCode.SharpDevelop.Debugging; |
||||||
|
|
||||||
|
namespace Debugger.AddIn.Tooltips |
||||||
{ |
{ |
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Control displaying and executing <see cref="IVisualizerCommand">visualizer commands</see>.
|
/// Control displaying and executing <see cref="IVisualizerCommand">visualizer commands</see>.
|
||||||
@ -1,7 +1,7 @@ |
|||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" |
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" |
||||||
xmlns:debugging="clr-namespace:ICSharpCode.SharpDevelop.Debugging"> |
xmlns:debugging="clr-namespace:Debugger.AddIn.Tooltips"> |
||||||
|
|
||||||
<BitmapImage x:Key="MagnifierImage" UriSource="magnifier.png" /> |
<BitmapImage x:Key="MagnifierImage" UriSource="magnifier.png" /> |
||||||
|
|
||||||
|
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 564 B |
@ -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 |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Description of SavedTreeNode.
|
||||||
|
/// </summary>
|
||||||
|
public class SavedTreeNode : TreeNode |
||||||
|
{ |
||||||
|
public override bool CanSetText { |
||||||
|
get { return true; } |
||||||
|
} |
||||||
|
|
||||||
|
public SavedTreeNode(IImage image, string fullname, string text) |
||||||
|
{ |
||||||
|
base.IconImage = image; |
||||||
|
FullName = fullname; |
||||||
|
Text = text; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool SetText(string newValue) { |
||||||
|
Text = newValue; |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -1,205 +0,0 @@ |
|||||||
<UserControl 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" |
|
||||||
> |
|
||||||
<UserControl.Resources> |
|
||||||
<ResourceDictionary> |
|
||||||
<ResourceDictionary.MergedDictionaries> |
|
||||||
<ResourceDictionary Source="VisualizerPicker.xaml" /> |
|
||||||
</ResourceDictionary.MergedDictionaries> |
|
||||||
|
|
||||||
<!-- TODO move styles to ResourceDictionary --> |
|
||||||
<Style x:Key="ExpandCollapseToggleStyle" |
|
||||||
TargetType="{x:Type ToggleButton}"> |
|
||||||
<Setter Property="Focusable" |
|
||||||
Value="False"/> |
|
||||||
<Setter Property="Width" |
|
||||||
Value="19"/> |
|
||||||
<Setter Property="Height" |
|
||||||
Value="13"/> |
|
||||||
<Setter Property="Template"> |
|
||||||
<Setter.Value> |
|
||||||
<ControlTemplate TargetType="{x:Type ToggleButton}"> |
|
||||||
<Border Width="19" |
|
||||||
Height="13" |
|
||||||
Background="Transparent"> |
|
||||||
<Border Width="9" |
|
||||||
Height="9" |
|
||||||
BorderThickness="1" |
|
||||||
BorderBrush="#FF7898B5" |
|
||||||
CornerRadius="1" |
|
||||||
SnapsToDevicePixels="true"> |
|
||||||
<Border.Background> |
|
||||||
<LinearGradientBrush StartPoint="0,0" |
|
||||||
EndPoint="1,1"> |
|
||||||
<LinearGradientBrush.GradientStops> |
|
||||||
<GradientStop Color="White" |
|
||||||
Offset=".2"/> |
|
||||||
<GradientStop Color="#FFC0B7A6" |
|
||||||
Offset="1"/> |
|
||||||
</LinearGradientBrush.GradientStops> |
|
||||||
</LinearGradientBrush> |
|
||||||
</Border.Background> |
|
||||||
<Path x:Name="ExpandPath" |
|
||||||
Margin="1,1,1,1" |
|
||||||
Fill="Black" |
|
||||||
Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/> |
|
||||||
</Border> |
|
||||||
</Border> |
|
||||||
<ControlTemplate.Triggers> |
|
||||||
<Trigger Property="IsChecked" |
|
||||||
Value="True"> |
|
||||||
<Setter Property="Data" |
|
||||||
TargetName="ExpandPath" |
|
||||||
Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/> |
|
||||||
</Trigger> |
|
||||||
</ControlTemplate.Triggers> |
|
||||||
</ControlTemplate> |
|
||||||
</Setter.Value> |
|
||||||
</Setter> |
|
||||||
</Style> |
|
||||||
<Style x:Key="upDownBorderStyle" TargetType="{x:Type Border}"> |
|
||||||
<Setter Property="BorderBrush" Value="Gray" /> |
|
||||||
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
|
||||||
<Setter Property="Margin" Value="0" /> |
|
||||||
<Setter Property="Padding" Value="0" /> |
|
||||||
<Setter Property="Background" Value="#FFECF7FC" /> |
|
||||||
<Setter Property="Height" Value="14" /> |
|
||||||
<Style.Triggers> |
|
||||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False"> |
|
||||||
<Setter Property="Background" Value="#FFE0E0E0"></Setter> |
|
||||||
</DataTrigger> |
|
||||||
</Style.Triggers> |
|
||||||
</Style> |
|
||||||
<Style x:Key="upButtonStyle" TargetType="{x:Type RepeatButton}"> |
|
||||||
<Setter Property="Template"> |
|
||||||
<Setter.Value> |
|
||||||
<ControlTemplate TargetType="{x:Type RepeatButton}"> |
|
||||||
<Border Style="{StaticResource upDownBorderStyle}" BorderThickness="1 1 1 0"> |
|
||||||
<ContentPresenter HorizontalAlignment="Center"></ContentPresenter> |
|
||||||
</Border> |
|
||||||
</ControlTemplate> |
|
||||||
</Setter.Value> |
|
||||||
</Setter> |
|
||||||
</Style> |
|
||||||
<Style x:Key="downButtonStyle" TargetType="{x:Type RepeatButton}"> |
|
||||||
<Setter Property="Template"> |
|
||||||
<Setter.Value> |
|
||||||
<ControlTemplate TargetType="{x:Type RepeatButton}"> |
|
||||||
<Border Style="{StaticResource upDownBorderStyle}" BorderThickness="1 0 1 1"> |
|
||||||
<ContentPresenter HorizontalAlignment="Center"></ContentPresenter> |
|
||||||
</Border> |
|
||||||
</ControlTemplate> |
|
||||||
</Setter.Value> |
|
||||||
</Setter> |
|
||||||
</Style> |
|
||||||
</ResourceDictionary> |
|
||||||
</UserControl.Resources> |
|
||||||
<StackPanel Orientation="Vertical"> |
|
||||||
<RepeatButton Name="btnUp" Focusable="False" Style="{StaticResource upButtonStyle}" Content="^" Click="BtnUp_Click"></RepeatButton> |
|
||||||
<DataGrid VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" |
|
||||||
GridLinesVisibility="None" |
|
||||||
RowHeight="18" MaxHeight="202" |
|
||||||
SelectionMode="Single" |
|
||||||
SelectionUnit="FullRow" |
|
||||||
ItemsSource="{Binding}" |
|
||||||
Name="dataGrid" |
|
||||||
AutoGenerateColumns="False" |
|
||||||
CanUserAddRows="False" HeadersVisibility="None" |
|
||||||
BorderBrush="Gray" |
|
||||||
BorderThickness="1"> |
|
||||||
<DataGrid.Background> |
|
||||||
|
|
||||||
<!-- Control backgound --> |
|
||||||
<LinearGradientBrush StartPoint="0,-0.03" EndPoint="0,1"> |
|
||||||
<GradientStop Color="White"/> |
|
||||||
<GradientStop Color="#FFFAFCFE" Offset="0.983"/> |
|
||||||
<GradientStop Color="#FFECF7FC" Offset="0.07"/> |
|
||||||
<GradientStop Color="#FFEEF7FA" Offset="0.436"/> |
|
||||||
</LinearGradientBrush> |
|
||||||
</DataGrid.Background> |
|
||||||
<DataGrid.RowStyle> |
|
||||||
<Style TargetType="{x:Type DataGridRow}"> |
|
||||||
<Setter Property="Background" Value="Transparent"></Setter> |
|
||||||
<Style.Triggers> |
|
||||||
<Trigger Property="IsMouseOver" Value="True"> |
|
||||||
<Setter Property="Background" Value="#FFE2F6FE" /> |
|
||||||
</Trigger> |
|
||||||
</Style.Triggers> |
|
||||||
</Style> |
|
||||||
</DataGrid.RowStyle> |
|
||||||
<DataGrid.CellStyle> |
|
||||||
<Style TargetType="{x:Type DataGridCell}"> |
|
||||||
<Setter Property="Focusable" Value="false" /> <!-- Focusable=true blocks shortcuts if cell is focused --> |
|
||||||
<Setter Property="BorderThickness" Value="0" /> |
|
||||||
<Style.Triggers> |
|
||||||
<Trigger Property="IsSelected" Value="True"> <!-- disable selection highlight --> |
|
||||||
<Setter Property="Foreground" Value="Black" /> |
|
||||||
<Setter Property="Background" Value="{x:Null}" /> |
|
||||||
</Trigger> |
|
||||||
</Style.Triggers> |
|
||||||
</Style> |
|
||||||
</DataGrid.CellStyle> |
|
||||||
<DataGrid.Columns> |
|
||||||
<DataGridTemplateColumn> <!-- "Plus" expander --> |
|
||||||
<DataGridTemplateColumn.CellTemplate> |
|
||||||
<DataTemplate> |
|
||||||
<Grid Background="White"> |
|
||||||
<StackPanel VerticalAlignment="Center"> |
|
||||||
<ToggleButton x:Name="btnExpander" Style="{StaticResource ExpandCollapseToggleStyle}" Click="btnExpander_Click" Padding="0" Margin="0" /> |
|
||||||
</StackPanel> |
|
||||||
</Grid> |
|
||||||
<DataTemplate.Triggers> |
|
||||||
<DataTrigger Binding="{Binding Path=HasChildNodes}" Value="False"> |
|
||||||
<Setter TargetName="btnExpander" |
|
||||||
Property="Visibility" Value="Collapsed"/> |
|
||||||
</DataTrigger> |
|
||||||
</DataTemplate.Triggers> |
|
||||||
</DataTemplate> |
|
||||||
</DataGridTemplateColumn.CellTemplate> |
|
||||||
</DataGridTemplateColumn> |
|
||||||
<!-- Icon --> |
|
||||||
<DataGridTemplateColumn> |
|
||||||
<DataGridTemplateColumn.CellTemplate> |
|
||||||
<DataTemplate> |
|
||||||
<Image Source="{Binding ImageSource}"></Image> |
|
||||||
</DataTemplate> |
|
||||||
</DataGridTemplateColumn.CellTemplate> |
|
||||||
</DataGridTemplateColumn> |
|
||||||
<DataGridTemplateColumn MinWidth="20" Header="Name"> <!-- Name --> |
|
||||||
<DataGridTemplateColumn.CellTemplate> |
|
||||||
<DataTemplate> |
|
||||||
<Border BorderBrush="#FFDDDDDD" BorderThickness="0 0 1 0"> |
|
||||||
<TextBlock 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> |
|
||||||
<TextBlock Margin="4 0" Text="{Binding Path=Text, Mode=OneWay}" VerticalAlignment="Top"></TextBlock> |
|
||||||
</DataTemplate> |
|
||||||
</DataGridTemplateColumn.CellTemplate> |
|
||||||
</DataGridTemplateColumn> |
|
||||||
</DataGrid.Columns> |
|
||||||
</DataGrid> |
|
||||||
<RepeatButton Name="btnDown" Focusable="False" Style="{StaticResource downButtonStyle}" Content="v" Click="BtnDown_Click"></RepeatButton> |
|
||||||
</StackPanel> |
|
||||||
</UserControl> |
|
||||||
@ -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 |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Default Control used as content of SharpDevelop debugger tooltips.
|
|
||||||
/// </summary>
|
|
||||||
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<ITreeNode> 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<ITreeNode> lazyGrid; |
|
||||||
|
|
||||||
private IEnumerable<ITreeNode> itemsSource; |
|
||||||
public IEnumerable<ITreeNode> ItemsSource |
|
||||||
{ |
|
||||||
get { return this.itemsSource; } |
|
||||||
set |
|
||||||
{ |
|
||||||
this.itemsSource = value; |
|
||||||
this.lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount); |
|
||||||
lazyGrid.ItemsSource = new VirtualizingIEnumerable<ITreeNode>(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; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool ShowAsPopup |
|
||||||
{ |
|
||||||
get |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
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; |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Closes the child popup of this control, if it exists.
|
|
||||||
/// </summary>
|
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -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<ITreeNode> ItemsSource { set; } |
||||||
|
Point Location { get; set; } |
||||||
|
} |
||||||
|
} |
||||||
@ -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<ITreeNode>(); |
||||||
|
IsVisibleInBookmarkPad = false; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pin's position relative to the layer BUT ABSOLUTE TO THE SCREEN.
|
||||||
|
/// </summary>
|
||||||
|
public Nullable<Point> PinPosition { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Nodes inside the pin control.
|
||||||
|
/// </summary>
|
||||||
|
public ObservableCollection<ITreeNode> Nodes { get; set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Image, Name, Text
|
||||||
|
/// </summary>
|
||||||
|
public List<Tuple<string, string, string>> 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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Binary file not shown.
Loading…
Reference in new issue