|
|
|
@ -27,140 +27,130 @@ namespace ICSharpCode.SharpDevelop.Debugging |
|
|
|
private readonly double ChildPopupOpenYOffet = 15; |
|
|
|
private readonly double ChildPopupOpenYOffet = 15; |
|
|
|
private readonly int InitialItemsCount = 12; |
|
|
|
private readonly int InitialItemsCount = 12; |
|
|
|
private readonly int VisibleItemsCount = 11; |
|
|
|
private readonly int VisibleItemsCount = 11; |
|
|
|
|
|
|
|
|
|
|
|
public DebuggerTooltipControl() |
|
|
|
public DebuggerTooltipControl() |
|
|
|
{ |
|
|
|
{ |
|
|
|
InitializeComponent(); |
|
|
|
InitializeComponent(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public DebuggerTooltipControl(ITreeNode node) |
|
|
|
public DebuggerTooltipControl(ITreeNode node) |
|
|
|
: this(new ITreeNode[] { node }) |
|
|
|
: this(new ITreeNode[] { node }) |
|
|
|
{ |
|
|
|
{ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public DebuggerTooltipControl(IEnumerable<ITreeNode> nodes) |
|
|
|
public DebuggerTooltipControl(IEnumerable<ITreeNode> nodes) |
|
|
|
: this() |
|
|
|
: this() |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.ItemsSource = nodes; |
|
|
|
this.ItemsSource = nodes; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public DebuggerTooltipControl(DebuggerTooltipControl parentControl) |
|
|
|
public DebuggerTooltipControl(DebuggerTooltipControl parentControl) |
|
|
|
: this() |
|
|
|
: this() |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.parentControl = parentControl; |
|
|
|
this.parentControl = parentControl; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public event RoutedEventHandler Closed; |
|
|
|
public event RoutedEventHandler Closed; |
|
|
|
protected void OnClosed() |
|
|
|
protected void OnClosed() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (this.Closed != null) |
|
|
|
if (this.Closed != null) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.Closed(this, new RoutedEventArgs()); |
|
|
|
this.Closed(this, new RoutedEventArgs()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private LazyItemsControl<ITreeNode> lazyGrid; |
|
|
|
private LazyItemsControl<ITreeNode> lazyGrid; |
|
|
|
|
|
|
|
|
|
|
|
private IEnumerable<ITreeNode> itemsSource; |
|
|
|
private IEnumerable<ITreeNode> itemsSource; |
|
|
|
public IEnumerable<ITreeNode> ItemsSource |
|
|
|
public IEnumerable<ITreeNode> ItemsSource |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
get { return this.itemsSource; } |
|
|
|
set |
|
|
|
set |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.itemsSource = value; |
|
|
|
this.itemsSource = value; |
|
|
|
this.lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount); |
|
|
|
this.lazyGrid = new LazyItemsControl<ITreeNode>(this.dataGrid, InitialItemsCount); |
|
|
|
lazyGrid.ItemsSource = new VirtualizingIEnumerable<ITreeNode>(value); |
|
|
|
lazyGrid.ItemsSource = new VirtualizingIEnumerable<ITreeNode>(value); |
|
|
|
this.dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll)); |
|
|
|
this.dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(handleScroll)); |
|
|
|
|
|
|
|
|
|
|
|
if (this.lazyGrid.ItemsSourceTotalCount != null) |
|
|
|
if (this.lazyGrid.ItemsSourceTotalCount != null) { |
|
|
|
{ |
|
|
|
|
|
|
|
// hide up/down buttons if too few items
|
|
|
|
// hide up/down buttons if too few items
|
|
|
|
btnUp.Visibility = btnDown.Visibility = |
|
|
|
btnUp.Visibility = btnDown.Visibility = |
|
|
|
this.lazyGrid.ItemsSourceTotalCount.Value <= VisibleItemsCount ? Visibility.Collapsed : Visibility.Visible; |
|
|
|
this.lazyGrid.ItemsSourceTotalCount.Value <= VisibleItemsCount ? Visibility.Collapsed : Visibility.Visible; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
get |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return this.itemsSource; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public bool ShowAsPopup { |
|
|
|
public bool ShowAsPopup |
|
|
|
get { |
|
|
|
{ |
|
|
|
|
|
|
|
get |
|
|
|
|
|
|
|
{ |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public bool Close(bool mouseClick) |
|
|
|
public bool Close(bool mouseClick) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (mouseClick || (!mouseClick && !isChildExpanded)) |
|
|
|
if (mouseClick || (!mouseClick && !isChildExpanded)) { |
|
|
|
{ |
|
|
|
|
|
|
|
CloseChildPopups(); |
|
|
|
CloseChildPopups(); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DebuggerPopup childPopup { get; set; } |
|
|
|
DebuggerPopup childPopup { get; set; } |
|
|
|
DebuggerTooltipControl parentControl { get; set; } |
|
|
|
DebuggerTooltipControl parentControl { get; set; } |
|
|
|
internal DebuggerPopup containingPopup { get; set; } |
|
|
|
internal DebuggerPopup containingPopup { get; set; } |
|
|
|
|
|
|
|
|
|
|
|
bool isChildExpanded |
|
|
|
bool isChildExpanded |
|
|
|
{ |
|
|
|
{ |
|
|
|
get { |
|
|
|
get |
|
|
|
|
|
|
|
{ |
|
|
|
return this.childPopup != null && this.childPopup.IsOpen; |
|
|
|
return this.childPopup != null && this.childPopup.IsOpen; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private ToggleButton expandedButton; |
|
|
|
private ToggleButton expandedButton; |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// Closes the child popup of this control, if it exists.
|
|
|
|
/// Closes the child popup of this control, if it exists.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public void CloseChildPopups() |
|
|
|
public void CloseChildPopups() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (this.expandedButton != null) |
|
|
|
if (this.expandedButton != null) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.expandedButton.IsChecked = false; |
|
|
|
this.expandedButton.IsChecked = false; |
|
|
|
this.expandedButton = null; |
|
|
|
this.expandedButton = null; |
|
|
|
// nice simple example of indirect recursion
|
|
|
|
// nice simple example of indirect recursion
|
|
|
|
this.childPopup.CloseSelfAndChildren(); |
|
|
|
this.childPopup.CloseSelfAndChildren(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void CloseOnLostFocus() |
|
|
|
public void CloseOnLostFocus() |
|
|
|
{ |
|
|
|
{ |
|
|
|
// when leaf below us closes, we become the leaf
|
|
|
|
// when leaf below us closes, we become the leaf
|
|
|
|
if (this.containingPopup != null) |
|
|
|
if (this.containingPopup != null) { |
|
|
|
this.containingPopup.IsLeaf = true; |
|
|
|
this.containingPopup.IsLeaf = true; |
|
|
|
if (!this.IsMouseOver) |
|
|
|
} |
|
|
|
{ |
|
|
|
if (!this.IsMouseOver) { |
|
|
|
if (this.containingPopup != null) |
|
|
|
if (this.containingPopup != null) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.containingPopup.IsOpen = false; |
|
|
|
this.containingPopup.IsOpen = false; |
|
|
|
this.containingPopup.IsLeaf = false; |
|
|
|
this.containingPopup.IsLeaf = false; |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.parentControl != null) |
|
|
|
if (this.parentControl != null) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.parentControl.CloseOnLostFocus(); |
|
|
|
this.parentControl.CloseOnLostFocus(); |
|
|
|
} |
|
|
|
} |
|
|
|
OnClosed(); |
|
|
|
OnClosed(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// leaf closed because of click inside this control - stop the closing chain
|
|
|
|
// leaf closed because of click inside this control - stop the closing chain
|
|
|
|
if (this.expandedButton != null && !this.expandedButton.IsMouseOver) |
|
|
|
if (this.expandedButton != null && !this.expandedButton.IsMouseOver) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.expandedButton.IsChecked = false; |
|
|
|
this.expandedButton.IsChecked = false; |
|
|
|
this.expandedButton = null; |
|
|
|
this.expandedButton = null; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void btnExpander_Click(object sender, RoutedEventArgs e) |
|
|
|
private void btnExpander_Click(object sender, RoutedEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var clickedButton = (ToggleButton)e.OriginalSource; |
|
|
|
var clickedButton = (ToggleButton)e.OriginalSource; |
|
|
|
@ -168,19 +158,16 @@ namespace ICSharpCode.SharpDevelop.Debugging |
|
|
|
// use device independent units, because child popup Left/Top are in independent units
|
|
|
|
// use device independent units, because child popup Left/Top are in independent units
|
|
|
|
Point buttonPos = clickedButton.PointToScreen(new Point(0, 0)).TransformFromDevice(clickedButton); |
|
|
|
Point buttonPos = clickedButton.PointToScreen(new Point(0, 0)).TransformFromDevice(clickedButton); |
|
|
|
|
|
|
|
|
|
|
|
if (clickedButton.IsChecked.GetValueOrDefault(false)) |
|
|
|
if (clickedButton.IsChecked.GetValueOrDefault(false)) { |
|
|
|
{ |
|
|
|
|
|
|
|
CloseChildPopups(); |
|
|
|
CloseChildPopups(); |
|
|
|
this.expandedButton = clickedButton; |
|
|
|
this.expandedButton = clickedButton; |
|
|
|
|
|
|
|
|
|
|
|
// open child Popup
|
|
|
|
// open child Popup
|
|
|
|
if (this.childPopup == null) |
|
|
|
if (this.childPopup == null) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.childPopup = new DebuggerPopup(this); |
|
|
|
this.childPopup = new DebuggerPopup(this); |
|
|
|
this.childPopup.Placement = PlacementMode.Absolute; |
|
|
|
this.childPopup.Placement = PlacementMode.Absolute; |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.containingPopup != null) |
|
|
|
if (this.containingPopup != null) { |
|
|
|
{ |
|
|
|
|
|
|
|
this.containingPopup.IsLeaf = false; |
|
|
|
this.containingPopup.IsLeaf = false; |
|
|
|
} |
|
|
|
} |
|
|
|
this.childPopup.IsLeaf = true; |
|
|
|
this.childPopup.IsLeaf = true; |
|
|
|
@ -188,24 +175,22 @@ namespace ICSharpCode.SharpDevelop.Debugging |
|
|
|
this.childPopup.VerticalOffset = buttonPos.Y + ChildPopupOpenYOffet; |
|
|
|
this.childPopup.VerticalOffset = buttonPos.Y + ChildPopupOpenYOffet; |
|
|
|
this.childPopup.ItemsSource = clickedNode.ChildNodes; |
|
|
|
this.childPopup.ItemsSource = clickedNode.ChildNodes; |
|
|
|
this.childPopup.Open(); |
|
|
|
this.childPopup.Open(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CloseChildPopups(); |
|
|
|
CloseChildPopups(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void handleScroll(object sender, ScrollChangedEventArgs e) |
|
|
|
private void handleScroll(object sender, ScrollChangedEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
btnUp.IsEnabled = !this.lazyGrid.IsScrolledToStart; |
|
|
|
btnUp.IsEnabled = !this.lazyGrid.IsScrolledToStart; |
|
|
|
btnDown.IsEnabled = !this.lazyGrid.IsScrolledToEnd; |
|
|
|
btnDown.IsEnabled = !this.lazyGrid.IsScrolledToEnd; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BtnUp_Click(object sender, RoutedEventArgs e) |
|
|
|
void BtnUp_Click(object sender, RoutedEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.lazyGrid.ScrollViewer.ScrollUp(1); |
|
|
|
this.lazyGrid.ScrollViewer.ScrollUp(1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BtnDown_Click(object sender, RoutedEventArgs e) |
|
|
|
void BtnDown_Click(object sender, RoutedEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
this.lazyGrid.ScrollViewer.ScrollDown(1); |
|
|
|
this.lazyGrid.ScrollViewer.ScrollDown(1); |
|
|
|
|