diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
index b75abc59dd..3bdcb78d05 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
@@ -176,6 +176,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
textEditor.MouseHover += textEditor_MouseHover;
textEditor.MouseHoverStopped += textEditor_MouseHoverStopped;
textEditor.MouseLeave += textEditor_MouseLeave;
+ textView.MouseDown += textEditor_MouseDown;
textEditor.TextArea.Caret.PositionChanged += caret_PositionChanged;
textEditor.TextArea.DefaultInputHandler.CommandBindings.Add(
new CommandBinding(CustomCommands.CtrlSpaceCompletion, OnCodeCompletion));
@@ -302,7 +303,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
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));
@@ -321,25 +321,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow);
}
if (popup == null) {
- popup = createPopup(true);
+ popup = createPopup();
}
if (tryCloseExistingPopup(false)) {
+ // when popup content decides to close, close the popup
+ contentToShowITooltip.Closed += (closedSender, closedArgs) => { popup.IsOpen = 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;*/
}
e.Handled = true;
}
@@ -362,53 +351,21 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
- 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;
+ if (popup != null) {
+ var popupContentITooltip = popup.Child as ITooltip;
+ if (popupContentITooltip != null) {
+ canClose = popupContentITooltip.Close(mouseClick);
+ }
+ if (canClose) {
+ 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);
@@ -430,12 +387,12 @@ namespace ICSharpCode.AvalonEdit.AddIn
}*/
}
- Popup createPopup(bool staysOpenOnFocusLost)
+ Popup createPopup()
{
popup = new Popup();
popup.Closed += popup_Closed;
popup.Placement = PlacementMode.Absolute;
- popup.StaysOpen = staysOpenOnFocusLost;
+ popup.StaysOpen = true;
return popup;
}
@@ -449,13 +406,17 @@ namespace ICSharpCode.AvalonEdit.AddIn
void textEditor_MouseLeave(object sender, MouseEventArgs e)
{
- if (popup != null) {
+ if (popup != null && !popup.IsMouseOver) {
// do not close popup if mouse moved from editor to popup
- if (!popup.IsMouseOver) {
- tryCloseExistingPopup(false);
- }
+ tryCloseExistingPopup(false);
}
}
+
+ void textEditor_MouseDown(object sender, MouseButtonEventArgs e)
+ {
+ // close existing popup on text editor mouse down
+ tryCloseExistingPopup(false);
+ }
void toolTip_Closed(object sender, RoutedEventArgs e)
{
diff --git a/src/Main/Base/Project/Src/Editor/ITooltip.cs b/src/Main/Base/Project/Src/Editor/ITooltip.cs
index 980af0ccf9..906d570e49 100644
--- a/src/Main/Base/Project/Src/Editor/ITooltip.cs
+++ b/src/Main/Base/Project/Src/Editor/ITooltip.cs
@@ -5,6 +5,7 @@
// $Revision$
//
using System;
+using System.Windows;
namespace ICSharpCode.SharpDevelop.Editor
{
@@ -21,11 +22,6 @@ namespace ICSharpCode.SharpDevelop.Editor
///
bool ShowAsPopup { get; }
- ///
- /// Indicates whether this tooltip allows to be closed.
- ///
- bool AllowsClose { get; }
-
///
/// Closes this tooltip.
///
@@ -33,5 +29,10 @@ namespace ICSharpCode.SharpDevelop.Editor
/// because of mouse click on some SharpDevelop GUI element.
/// True if Close succeeded (that is, can close). False otherwise.
bool Close(bool mouseClick);
+
+ ///
+ /// Occurs when this tooltip decides to close.
+ ///
+ event RoutedEventHandler Closed;
}
}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerPopup.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerPopup.cs
index 182d843f90..706bf88f18 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerPopup.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerPopup.cs
@@ -17,20 +17,13 @@ namespace ICSharpCode.SharpDevelop.Debugging
public class DebuggerPopup : Popup
{
private DebuggerTooltipControl contentControl;
- //private DebuggerPopup parentPopup;
- public DebuggerPopup()
+ public DebuggerPopup(DebuggerTooltipControl parentControl)
{
- this.contentControl = new DebuggerTooltipControl();
+ this.contentControl = new DebuggerTooltipControl(parentControl);
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");
+ this.IsLeaf = false;
}
public IEnumerable ItemsSource
@@ -39,14 +32,35 @@ namespace ICSharpCode.SharpDevelop.Debugging
set { this.contentControl.ItemsSource = value; }
}
+ private bool isLeaf;
+ public bool IsLeaf
+ {
+ get { return isLeaf; }
+ set
+ {
+ isLeaf = value;
+ // leaf popup closes on lost focus
+ this.StaysOpen = !isLeaf;
+ }
+ }
+
+ protected override void OnClosed(EventArgs e)
+ {
+ base.OnClosed(e);
+ if (isLeaf)
+ {
+ this.contentControl.CloseOnLostFocus();
+ }
+ }
+
public void Open()
{
this.IsOpen = true;
}
- public void Close()
+ public void CloseSelfAndChildren()
{
- this.contentControl.CloseChildPopup();
+ this.contentControl.CloseChildPopups();
this.IsOpen = false;
}
}
diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml b/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml
index 71f4a5a1c1..c87c4f8534 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml
+++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml
@@ -56,8 +56,9 @@
+
-
+
diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml.cs
index f05d27be5f..4f57f4782a 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerTooltipControl.xaml.cs
@@ -39,6 +39,21 @@ namespace ICSharpCode.SharpDevelop.Debugging
this.ItemsSource = nodes;
}
+ public DebuggerTooltipControl(DebuggerTooltipControl parentControl)
+ : this()
+ {
+ this.parentControl = parentControl;
+ }
+
+ public event RoutedEventHandler Closed;
+ protected void OnClosed()
+ {
+ if (this.Closed != null)
+ {
+ this.Closed(this, new RoutedEventArgs());
+ }
+ }
+
private LazyItemsControl lazyGrid;
private IEnumerable itemsSource;
@@ -53,7 +68,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
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 =
this.lazyGrid.ItemsSourceTotalCount.Value <= 10 ? Visibility.Collapsed : Visibility.Visible;
}
@@ -71,30 +86,24 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
}
- ///
- /// When child popup is expanded, returns false. Otherwise true.
- ///
- public bool AllowsClose {
- get {
- return !isChildExpanded;
- }
- }
-
///
public bool Close(bool mouseClick)
{
if (mouseClick || (!mouseClick && !isChildExpanded))
{
- CloseChildPopup();
+ CloseChildPopups();
return true;
- }
+ }
else
{
return false;
}
}
- DebuggerPopup childPopup;
+ DebuggerPopup childPopup { get; set; }
+ DebuggerTooltipControl parentControl { get; set; }
+ internal DebuggerPopup containingPopup { get; set; }
+
bool isChildExpanded
{
get {
@@ -102,18 +111,50 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
}
+ private ToggleButton expandedButton;
+
///
/// Closes the child popup of this control, if it exists.
///
- public void CloseChildPopup()
+ public void CloseChildPopups()
{
- if (this.childPopup != null)
+ if (this.expandedButton != null)
{
- this.childPopup.Close();
+ this.expandedButton.IsChecked = false;
+ this.expandedButton = null;
+ // nice simple example of indirect recursion
+ this.childPopup.CloseSelfAndChildren();
}
}
- internal Popup containingPopup;
+ public void CloseOnLostFocus()
+ {
+ // when leaf below us closes, we become the 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 chaing
+ if (this.expandedButton != null)
+ {
+ this.expandedButton.IsChecked = false;
+ this.expandedButton = null;
+ }
+ }
+ }
private void btnExpander_Click(object sender, RoutedEventArgs e)
{
@@ -123,30 +164,28 @@ namespace ICSharpCode.SharpDevelop.Debugging
if (clickedButton.IsChecked.GetValueOrDefault(false))
{
- CloseChildPopup();
+ CloseChildPopups();
+ this.expandedButton = clickedButton;
// open child Popup
if (this.childPopup == null)
{
- this.childPopup = new DebuggerPopup();
+ this.childPopup = new DebuggerPopup(this);
this.childPopup.Placement = PlacementMode.Absolute;
- this.childPopup.StaysOpen = true;
}
if (this.containingPopup != null)
{
- this.containingPopup.StaysOpen = true;
+ this.containingPopup.IsLeaf = false;
}
- // last popup is always StaysOpen = false, therefore focused
- this.childPopup.StaysOpen = false;
+ this.childPopup.IsLeaf = true;
this.childPopup.HorizontalOffset = buttonPos.X + 15;
this.childPopup.VerticalOffset = buttonPos.Y + 15;
this.childPopup.ItemsSource = clickedNode.ChildNodes;
- this.childPopup.UpdateLayout();
this.childPopup.Open();
}
else
{
- CloseChildPopup();
+ CloseChildPopups();
}
}