Skip to content

Commit

Permalink
Merge pull request #3295 from tig/v2_3273_FOUND_finddeepestview
Browse files Browse the repository at this point in the history
Fixes #3273 (Again).  Updates `FindDeepestView` etc... to finish `Adornment`
  • Loading branch information
tig authored Mar 14, 2024
2 parents e4e3ffe + df4f479 commit a5b1d68
Show file tree
Hide file tree
Showing 52 changed files with 2,734 additions and 2,135 deletions.
210 changes: 75 additions & 135 deletions Terminal.Gui/Application.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Text.Json.Serialization;
Expand Down Expand Up @@ -489,6 +490,8 @@ public static RunState Begin (Toplevel Toplevel)
Toplevel.SetRelativeLayout (Driver.Bounds);

//}

// BUGBUG: This call is likley not needed.
Toplevel.LayoutSubviews ();
Toplevel.PositionToplevels ();
Toplevel.FocusFirst ();
Expand Down Expand Up @@ -532,7 +535,7 @@ public static RunState Begin (Toplevel Toplevel)
/// <see langword="null"/> if <see cref="Init"/> has already been called.
/// </param>
public static void Run<T> (Func<Exception, bool> errorHandler = null, ConsoleDriver driver = null)
where T : Toplevel, new ()
where T : Toplevel, new()
{
if (_initialized)
{
Expand Down Expand Up @@ -1028,6 +1031,8 @@ public static void End (RunState runState)
runState.Toplevel?.Dispose ();
runState.Toplevel = null;
runState.Dispose ();

// BUGBUG: Application.Top is now invalid?!?!
}

#endregion Run (Begin, Run, End)
Expand Down Expand Up @@ -1078,7 +1083,7 @@ private static void EnsureModalOrVisibleAlwaysOnTop (Toplevel Toplevel)
}
}

#nullable enable
#nullable enable
private static Toplevel? FindDeepestTop (Toplevel start, int x, int y)
{
if (!start.Frame.Contains (x, y))
Expand Down Expand Up @@ -1107,7 +1112,7 @@ private static void EnsureModalOrVisibleAlwaysOnTop (Toplevel Toplevel)

return start;
}
#nullable restore
#nullable restore

private static View FindTopFromView (View view)
{
Expand All @@ -1123,7 +1128,8 @@ private static View FindTopFromView (View view)
return top;
}

#nullable enable
#nullable enable

// Only return true if the Current has changed.
private static bool MoveCurrent (Toplevel? top)
{
Expand Down Expand Up @@ -1204,7 +1210,7 @@ private static bool MoveCurrent (Toplevel? top)

return true;
}
#nullable restore
#nullable restore

/// <summary>Invoked when the terminal's size changed. The new size of the terminal is provided.</summary>
/// <remarks>
Expand Down Expand Up @@ -1350,14 +1356,15 @@ private static void OnUnGrabbedMouse (View view)
UnGrabbedMouse?.Invoke (view, new ViewEventArgs (view));
}

#nullable enable
#nullable enable

// Used by OnMouseEvent to track the last view that was clicked on.
internal static View? _mouseEnteredView;

/// <summary>Event fired when a mouse move or click occurs. Coordinates are screen relative.</summary>
/// <remarks>
/// <para>
/// Use this event to receive mouse events in screen coordinates. Use <see cref="Responder.MouseEvent"/> to
/// Use this event to receive mouse events in screen coordinates. Use <see cref="MouseEvent"/> to
/// receive mouse events relative to a <see cref="View"/>'s bounds.
/// </para>
/// <para>The <see cref="MouseEvent.View"/> will contain the <see cref="View"/> that contains the mouse coordinates.</para>
Expand Down Expand Up @@ -1402,47 +1409,50 @@ internal static void OnMouseEvent (MouseEventEventArgs a)
{
// If the mouse is grabbed, send the event to the view that grabbed it.
// The coordinates are relative to the Bounds of the view that grabbed the mouse.
Point newxy = MouseGrabView.ScreenToFrame (a.MouseEvent.X, a.MouseEvent.Y);
Point frameLoc = MouseGrabView.ScreenToFrame (a.MouseEvent.X, a.MouseEvent.Y);

var nme = new MouseEvent
var viewRelativeMouseEvent = new MouseEvent
{
X = newxy.X,
Y = newxy.Y,
X = frameLoc.X,
Y = frameLoc.Y,
Flags = a.MouseEvent.Flags,
OfX = a.MouseEvent.X - newxy.X,
OfY = a.MouseEvent.Y - newxy.Y,
ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y),
View = view
};

if (MouseGrabView.Bounds.Contains (nme.X, nme.Y) is false)
if (MouseGrabView.Bounds.Contains (viewRelativeMouseEvent.X, viewRelativeMouseEvent.Y) is false)
{
// The mouse has moved outside the bounds of the view that
// grabbed the mouse, so we tell the view that last got
// OnMouseEnter the mouse is leaving
// BUGBUG: That sentence makes no sense. Either I'm missing something
// or this logic is flawed.
// BUGBUG: That sentence makes no sense. Either I'm missing something or this logic is flawed.
_mouseEnteredView?.OnMouseLeave (a.MouseEvent);
}

//System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}");
if (MouseGrabView?.OnMouseEvent (nme) == true)
if (MouseGrabView?.OnMouseEvent (viewRelativeMouseEvent) == true)
{
return;
}
}

if ((view is null || view == OverlappedTop)
&& Current is { Modal: false }
&& OverlappedTop != null
&& a.MouseEvent.Flags != MouseFlags.ReportMousePosition
&& a.MouseEvent.Flags != 0)
if (view is not Adornment)
{
View? top = FindDeepestTop (Top, a.MouseEvent.X, a.MouseEvent.Y);
view = View.FindDeepestView (top, a.MouseEvent.X, a.MouseEvent.Y);

if (view is { } && view != OverlappedTop && top != Current)
if ((view is null || view == OverlappedTop)
&& Current is { Modal: false }
&& OverlappedTop != null
&& a.MouseEvent.Flags != MouseFlags.ReportMousePosition
&& a.MouseEvent.Flags != 0)
{
MoveCurrent ((Toplevel)top);
// This occurs when there are multiple overlapped "tops"
// E.g. "Mdi" - in the Background Worker Scenario
View? top = FindDeepestTop (Top, a.MouseEvent.X, a.MouseEvent.Y);
view = View.FindDeepestView (top, a.MouseEvent.X, a.MouseEvent.Y);

if (view is { } && view != OverlappedTop && top != Current)
{
MoveCurrent ((Toplevel)top);

Check warning on line 1454 in Terminal.Gui/Application.cs

View workflow job for this annotation

GitHub Actions / Build and Publish to Nuget.org

Converting null literal or possible null value to non-nullable type.

Check warning on line 1454 in Terminal.Gui/Application.cs

View workflow job for this annotation

GitHub Actions / build_and_test

Converting null literal or possible null value to non-nullable type.
}
}
}

Expand All @@ -1451,140 +1461,70 @@ internal static void OnMouseEvent (MouseEventEventArgs a)
return;
}

var screen = view.FrameToScreen ();

// Work inside-out (Padding, Border, Margin)
// TODO: Debate whether inside-out or outside-in is the right strategy
if (AdornmentHandledMouseEvent (view.Padding, a))
{
return;
}
MouseEvent? me = null;

if (AdornmentHandledMouseEvent (view.Border, a))
if (view is Adornment adornment)
{
if (view is not Toplevel)
{
return;
}

// TODO: This is a temporary hack to work around the fact that
// drag handling is handled in Toplevel (See Issue #2537)
var frameLoc = adornment.ScreenToFrame (a.MouseEvent.X, a.MouseEvent.Y);

var me = new MouseEvent
me = new MouseEvent
{
X = a.MouseEvent.X - screen.X,
Y = a.MouseEvent.Y - screen.Y,
X = frameLoc.X,
Y = frameLoc.Y,
Flags = a.MouseEvent.Flags,
OfX = a.MouseEvent.X - screen.X,
OfY = a.MouseEvent.Y - screen.Y,
ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y),
View = view
};

if (_mouseEnteredView is null)
{
_mouseEnteredView = view;
view.OnMouseEnter (me);
}
else if (_mouseEnteredView != view)
{
_mouseEnteredView.OnMouseLeave (me);
view.OnMouseEnter (me);
_mouseEnteredView = view;
}

if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition)
{
return;
}

WantContinuousButtonPressedView = view.WantContinuousButtonPressed ? view : null;

if (view.OnMouseEvent (me))
{
// Should we bubble up the event, if it is not handled?
//return;
}

BringOverlappedTopToFront ();

return;
}

if (AdornmentHandledMouseEvent (view?.Margin, a))
{
return;
}

Rectangle bounds = view.BoundsToScreen (view.Bounds);

if (bounds.Contains (a.MouseEvent.X, a.MouseEvent.Y))
else if (view.BoundsToScreen (view.Bounds).Contains (a.MouseEvent.X, a.MouseEvent.Y))
{
Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);

var me = new MouseEvent
me = new MouseEvent
{
X = boundsPoint.X,
Y = boundsPoint.Y,
Flags = a.MouseEvent.Flags,
OfX = boundsPoint.X,
OfY = boundsPoint.Y,
ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y),
View = view
};
}

if (_mouseEnteredView is null)
{
_mouseEnteredView = view;
view.OnMouseEnter (me);
}
else if (_mouseEnteredView != view)
{
_mouseEnteredView.OnMouseLeave (me);
view.OnMouseEnter (me);
_mouseEnteredView = view;
}

if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition)
{
return;
}

WantContinuousButtonPressedView = view.WantContinuousButtonPressed ? view : null;

if (view.OnMouseEvent (me))
{
// Should we bubble up the event, if it is not handled?
//return;
}

BringOverlappedTopToFront ();
if (me is null)
{
return;
}

return;
if (_mouseEnteredView is null)
{
_mouseEnteredView = view;
view.OnMouseEnter (me);
}
else if (_mouseEnteredView != view)
{
_mouseEnteredView.OnMouseLeave (me);
view.OnMouseEnter (me);
_mouseEnteredView = view;
}

static bool AdornmentHandledMouseEvent (Adornment? frame, MouseEventEventArgs args)
if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition)
{
if (frame?.Thickness.Contains (frame.FrameToScreen (), args.MouseEvent.X, args.MouseEvent.Y) is not true)
{
return false;
}
return;
}

Point boundsPoint = frame.ScreenToBounds (args.MouseEvent.X, args.MouseEvent.Y);
WantContinuousButtonPressedView = view.WantContinuousButtonPressed ? view : null;

var me = new MouseEvent
{
X = boundsPoint.X,
Y = boundsPoint.Y,
Flags = args.MouseEvent.Flags,
OfX = boundsPoint.X,
OfY = boundsPoint.Y,
View = frame
};
frame.OnMouseEvent (me);
//Debug.WriteLine ($"OnMouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags}");

return true;
if (view.OnMouseEvent (me))
{
// Should we bubble up the event, if it is not handled?
//return;
}

BringOverlappedTopToFront ();
}
#nullable restore
#nullable restore

#endregion Mouse handling

Expand Down Expand Up @@ -1799,4 +1739,4 @@ public static bool OnKeyUp (Key a)
}

#endregion Keyboard handling
}
}
6 changes: 3 additions & 3 deletions Terminal.Gui/Configuration/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ where type.GetProperties ()
classesWithConfigProps.Add (classWithConfig.Name, classWithConfig);
}

Debug.WriteLine ($"ConfigManager.getConfigProperties found {classesWithConfigProps.Count} classes:");
//Debug.WriteLine ($"ConfigManager.getConfigProperties found {classesWithConfigProps.Count} classes:");
classesWithConfigProps.ToList ().ForEach (x => Debug.WriteLine ($" Class: {x.Key}"));

foreach (PropertyInfo? p in from c in classesWithConfigProps
Expand Down Expand Up @@ -573,7 +573,7 @@ from p in enumerable
StringComparer.InvariantCultureIgnoreCase
);

Debug.WriteLine ($"ConfigManager.Initialize found {_allConfigProperties.Count} properties:");
//Debug.WriteLine ($"ConfigManager.Initialize found {_allConfigProperties.Count} properties:");

//_allConfigProperties.ToList ().ForEach (x => Debug.WriteLine ($" Property: {x.Key}"));

Expand All @@ -584,7 +584,7 @@ from p in enumerable
/// <returns></returns>
internal static string ToJson ()
{
Debug.WriteLine ("ConfigurationManager.ToJson()");
//Debug.WriteLine ("ConfigurationManager.ToJson()");

return JsonSerializer.Serialize (Settings!, _serializerOptions);
}
Expand Down
4 changes: 2 additions & 2 deletions Terminal.Gui/Configuration/ThemeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ internal static string SelectedTheme

internal static void GetHardCodedDefaults ()
{
Debug.WriteLine ("Themes.GetHardCodedDefaults()");
//Debug.WriteLine ("Themes.GetHardCodedDefaults()");
var theme = new ThemeScope ();
theme.RetrieveValues ();

Expand All @@ -125,7 +125,7 @@ internal static void GetHardCodedDefaults ()
/// <summary>Called when the selected theme has changed. Fires the <see cref="ThemeChanged"/> event.</summary>
internal void OnThemeChanged (string theme)
{
Debug.WriteLine ($"Themes.OnThemeChanged({theme}) -> {Theme}");
//Debug.WriteLine ($"Themes.OnThemeChanged({theme}) -> {Theme}");
ThemeChanged?.Invoke (this, new ThemeManagerEventArgs (theme));
}

Expand Down
Loading

0 comments on commit a5b1d68

Please sign in to comment.