Browse Source

Debugger tooltips - expanding, partially working collapsing using StaysOpen = false for leaf Popup

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4615 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Martin Koníček 16 years ago
parent
commit
1a9088a801
  1. 83
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  2. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  3. 15
      src/Main/Base/Project/Src/Editor/ITooltip.cs
  4. 53
      src/Main/Base/Project/Src/Services/Debugger/DebuggerPopup.cs
  5. 9
      src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml
  6. 96
      src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml.cs

83
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -298,9 +298,11 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -298,9 +298,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
ToolTip toolTip;
Popup popup;
bool settingFocus = false;
void textEditor_MouseHover(object sender, MouseEventArgs e)
{
LoggingService.Debug("textEditor_MouseHover");
TextEditor textEditor = (TextEditor)sender;
ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(GetAdapter(textEditor));
var pos = textEditor.GetPositionFromPoint(e.GetPosition(textEditor));
@ -319,14 +321,26 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -319,14 +321,26 @@ namespace ICSharpCode.AvalonEdit.AddIn
throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow);
}
if (popup == null) {
popup = createPopup();
popup = createPopup(true);
}
if (tryCloseExistingPopup(false)) {
popup.Child = (UIElement)args.ContentToShow;
setPopupPosition(popup, textEditor, e);
LoggingService.Debug("opening new popup");
popup.IsOpen = true;
/*popup.Child.Focusable = true;
popup.Child.PreviewLostKeyboardFocus += (senderChild, _e) => {
LoggingService.Debug(string.Format("popup focus lost, source {0}, old {1}, new {2}", _e.Source, _e.OldFocus, _e.NewFocus));
//if (_e.OriginalSource == popup.Child) {
tryCloseExistingPopup(true);
//}
};
popup.IsOpen = true;
//settingFocus = true;
textEditor.Focus(); // needed so that popup.Child.Focus() succeds
popup.Child.Focus();
//settingFocus = false;*/
}
// close old popup
popup.IsOpen = false;
popup.Child = (UIElement)args.ContentToShow;
setPopupPosition(popup, textEditor, e);
// open popup at new location
popup.IsOpen = true;
e.Handled = true;
}
else {
@ -342,12 +356,59 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -342,12 +356,59 @@ namespace ICSharpCode.AvalonEdit.AddIn
else {
// close popup if mouse hovered over empty area
if (popup != null) {
popup.IsOpen = false;
e.Handled = true;
}
tryCloseExistingPopup(false);
}
}
ITooltip getExistingITooltipPopupContent()
{
if (popup == null) {
return null;
}
return popup.Child as ITooltip;
}
bool tryCloseExistingPopup(bool mouseClick)
{
bool canClose = true;
var popupContentITooltip = getExistingITooltipPopupContent();
if (popupContentITooltip != null) {
canClose = popupContentITooltip.Close(mouseClick);
}
if (popup != null && canClose) {
popup.IsOpen = false;
}
return canClose;
}
/*bool tryCloseExistingPopup(bool mouseClick)
{
bool canClose = true;
var popupContentITooltip = getExistingITooltipPopupContent();
if (popupContentITooltip != null) {
canClose = popupContentITooltip.AllowsClose;
}
if (popup != null && canClose) {
LoggingService.Debug("popup.IsOpen = false");
// popup.IsOpen = false + closing ITooltip in Closed handler
// does not work, because Closed is called asynchronously
closeITooltipContent(popup);
popup.IsOpen = false;
}
return canClose;
}
void closeITooltipContent(Popup popup)
{
var popupContentITooltip = getExistingITooltipPopupContent();
if (popupContentITooltip != null) {
LoggingService.Debug("Closing popup children");
popupContentITooltip.Close();
}
}*/
void setPopupPosition(Popup popup, TextEditor textEditor, MouseEventArgs mouseArgs)
{
var popupPosition = getPopupPosition(textEditor, mouseArgs);
@ -369,12 +430,12 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -369,12 +430,12 @@ namespace ICSharpCode.AvalonEdit.AddIn
}*/
}
Popup createPopup()
Popup createPopup(bool staysOpenOnFocusLost)
{
popup = new Popup();
popup.Closed += popup_Closed;
popup.Placement = PlacementMode.Absolute;
popup.StaysOpen = true;
popup.StaysOpen = staysOpenOnFocusLost;
return popup;
}
@ -391,7 +452,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -391,7 +452,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (popup != null) {
// do not close popup if mouse moved from editor to popup
if (!popup.IsMouseOver) {
popup.IsOpen = false;
tryCloseExistingPopup(false);
}
}
}

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

@ -218,6 +218,7 @@ @@ -218,6 +218,7 @@
<Compile Include="Src\Project\Solution\ProjectTypeGuids.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmarkEventArgs.cs" />
<Compile Include="Src\Services\Debugger\DebuggerPopup.cs" />
<Compile Include="Src\Services\Debugger\DebuggerTooltipControl.xaml.cs">
<DependentUpon>DebuggerTooltipControl.xaml</DependentUpon>
<SubType>Code</SubType>

15
src/Main/Base/Project/Src/Editor/ITooltip.cs

@ -9,7 +9,7 @@ using System; @@ -9,7 +9,7 @@ using System;
namespace ICSharpCode.SharpDevelop.Editor
{
/// <summary>
/// Content of text editor tooltip (<see cref="ToolTipRequestEventArgs.ContentToShow"/>),
/// Content of text editor tooltip (used as <see cref="ToolTipRequestEventArgs.ContentToShow"/>),
/// specifying whether it should be displayed in a WPF Popup.
/// </summary>
public interface ITooltip
@ -22,9 +22,16 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -22,9 +22,16 @@ namespace ICSharpCode.SharpDevelop.Editor
bool ShowAsPopup { get; }
/// <summary>
/// Closes this debugger tooltip.
/// Indicates whether this tooltip allows to be closed.
/// </summary>
/// <returns>True if Close succeeded, false otherwise.</returns>
bool Close();
bool AllowsClose { get; }
/// <summary>
/// Closes this tooltip.
/// </summary>
/// <param name="mouseClick">True if close request is raised
/// because of mouse click on some SharpDevelop GUI element.</param>
/// <returns>True if Close succeeded (that is, can close). False otherwise.</returns>
bool Close(bool mouseClick);
}
}

53
src/Main/Base/Project/Src/Services/Debugger/DebuggerPopup.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.Core;
using System;
using System.Collections.Generic;
using System.Windows.Controls.Primitives;
namespace ICSharpCode.SharpDevelop.Debugging
{
/// <summary>
/// Popup containing <see cref="DebuggerTooltipControl"></see>.
/// </summary>
public class DebuggerPopup : Popup
{
private DebuggerTooltipControl contentControl;
//private DebuggerPopup parentPopup;
public DebuggerPopup()
{
this.contentControl = new DebuggerTooltipControl();
this.contentControl.containingPopup = this;
this.Child = this.contentControl;
// to handle closed by lost focus
this.Closed += DebuggerPopup_Closed;
}
void DebuggerPopup_Closed(object sender, EventArgs e)
{
LoggingService.Debug("DebuggerPopup_Closed");
}
public IEnumerable<ITreeNode> ItemsSource
{
get { return this.contentControl.ItemsSource; }
set { this.contentControl.ItemsSource = value; }
}
public void Open()
{
this.IsOpen = true;
}
public void Close()
{
this.contentControl.CloseChildPopup();
this.IsOpen = false;
}
}
}

9
src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml

@ -57,6 +57,7 @@ @@ -57,6 +57,7 @@
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0" />
<Setter Property="Background" Value="#FFECF7FC" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False">
<Setter Property="Background" Value="#FFE0E0E0"></Setter>
@ -122,6 +123,12 @@ @@ -122,6 +123,12 @@
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Focusable" Value="false" />
<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>
@ -134,7 +141,7 @@ @@ -134,7 +141,7 @@
</StackPanel>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=HasChildren}" Value="False">
<DataTrigger Binding="{Binding Path=HasChildNodes}" Value="False">
<Setter TargetName="btnExpander"
Property="Visibility" Value="Hidden"/>
</DataTrigger>

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

@ -28,12 +28,12 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -28,12 +28,12 @@ namespace ICSharpCode.SharpDevelop.Debugging
InitializeComponent();
}
public DebuggerTooltipControl(ITreeNode node)
public DebuggerTooltipControl(ITreeNode node)
: this(new ITreeNode[] { node })
{
}
public DebuggerTooltipControl(IEnumerable<ITreeNode> nodes)
public DebuggerTooltipControl(IEnumerable<ITreeNode> nodes)
: this()
{
this.ItemsSource = nodes;
@ -41,24 +41,6 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -41,24 +41,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
private LazyItemsControl<ITreeNode> lazyGrid;
/// <summary>
/// Determines whether DebuggerTooltipControl should be displayed in WPF Popup.
/// </summary>
public bool ShowAsPopup {
get {
return true;
}
}
/// <summary>
/// Closes the debugger Popup containing this control. Also closes all child Popups.
/// </summary>
/// <returns></returns>
public bool Close()
{
throw new NotImplementedException();
}
private IEnumerable<ITreeNode> itemsSource;
public IEnumerable<ITreeNode> ItemsSource
{
@ -71,6 +53,7 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -71,6 +53,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
if (this.lazyGrid.ItemsSourceTotalCount != null)
{
// hide up, down buttons if too few items
btnUp.Visibility = btnDown.Visibility =
this.lazyGrid.ItemsSourceTotalCount.Value <= 10 ? Visibility.Collapsed : Visibility.Visible;
}
@ -81,18 +64,89 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -81,18 +64,89 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
}
/// <inheritdoc/>
public bool ShowAsPopup {
get {
return true;
}
}
/// <summary>
/// When child popup is expanded, returns false. Otherwise true.
/// </summary>
public bool AllowsClose {
get {
return !isChildExpanded;
}
}
/// <inheritdoc/>
public bool Close(bool mouseClick)
{
if (mouseClick || (!mouseClick && !isChildExpanded))
{
CloseChildPopup();
return true;
}
else
{
return false;
}
}
DebuggerPopup childPopup;
bool isChildExpanded
{
get {
return this.childPopup != null && this.childPopup.IsOpen;
}
}
/// <summary>
/// Closes the child popup of this control, if it exists.
/// </summary>
public void CloseChildPopup()
{
if (this.childPopup != null)
{
this.childPopup.Close();
}
}
internal Popup containingPopup;
private void btnExpander_Click(object sender, RoutedEventArgs e)
{
var clickedButton = (ToggleButton)e.OriginalSource;
var clickedNode = (ITreeNode)clickedButton.DataContext;
Point buttonPos = clickedButton.PointToScreen(new Point(0, 0));
if (clickedButton.IsChecked.GetValueOrDefault(false))
{
CloseChildPopup();
// open child Popup
if (this.childPopup == null)
{
this.childPopup = new DebuggerPopup();
this.childPopup.Placement = PlacementMode.Absolute;
this.childPopup.StaysOpen = true;
}
if (this.containingPopup != null)
{
this.containingPopup.StaysOpen = true;
}
// last popup is always StaysOpen = false, therefore focused
this.childPopup.StaysOpen = false;
this.childPopup.HorizontalOffset = buttonPos.X + 15;
this.childPopup.VerticalOffset = buttonPos.Y + 15;
this.childPopup.ItemsSource = clickedNode.ChildNodes;
this.childPopup.UpdateLayout();
this.childPopup.Open();
}
else
{
// close child Popups
CloseChildPopup();
}
}

Loading…
Cancel
Save