namespace Terminal.Gui.App;
///
/// Abstract base class for popover views in Terminal.Gui. Implements .
///
///
///
/// IMPORTANT: Popovers must be registered with using
/// before they can be shown.
///
///
/// Requirements:
/// Derived classes must:
///
///
/// - Set to include and .
/// - Add a key binding for (typically bound to ).
///
///
/// Default Behavior:
/// This base class provides:
///
///
/// - Fills the screen by default ( = , = ).
/// - Transparent viewport settings for proper mouse event handling.
/// - Automatic layout when becoming visible.
/// - Focus restoration when hidden.
/// - Default implementation that hides the popover.
///
///
/// Lifecycle:
/// Use to display and or
/// set to to hide.
///
///
public abstract class PopoverBaseImpl : View, IPopover
{
///
/// Initializes a new instance of the class.
///
///
///
/// Sets up default popover behavior:
///
///
/// - Fills the screen ( = , = ).
/// - Sets to .
/// - Configures with and .
/// - Adds bound to which hides the popover when invoked.
///
///
protected PopoverBaseImpl ()
{
Id = "popoverBaseImpl";
CanFocus = true;
Width = Dim.Fill ();
Height = Dim.Fill ();
ViewportSettings = ViewportSettingsFlags.Transparent | ViewportSettingsFlags.TransparentMouse;
// TODO: Add a diagnostic setting for this?
//TextFormatter.VerticalAlignment = Alignment.End;
//TextFormatter.Alignment = Alignment.End;
//base.Text = "popover";
AddCommand (Command.Quit, Quit);
KeyBindings.Add (Application.QuitKey, Command.Quit);
return;
bool? Quit (ICommandContext? ctx)
{
if (!Visible)
{
return false;
}
Visible = false;
return true;
}
}
private IRunnable? _current;
///
public IRunnable? Current
{
get => _current;
set
{
_current = value;
App ??= (_current as View)?.App;
}
}
///
/// Called when the property is changing. Handles layout and focus management.
///
///
/// to cancel the visibility change; otherwise, .
///
///
///
/// When becoming visible: Lays out the popover to fit the screen.
///
///
/// When becoming hidden: Restores focus to the previously focused view in the view hierarchy.
///
///
protected override bool OnVisibleChanging ()
{
bool ret = base.OnVisibleChanging ();
if (ret)
{
return ret;
}
if (!Visible)
{
// Whenever visible is changing to true, we need to resize;
// it's our only chance because we don't get laid out until we're visible
if (App is { })
{
Layout (App.Screen.Size);
}
}
else
{
// Whenever visible is changing to false, we need to reset the focus
if (ApplicationNavigation.IsInHierarchy (this, App?.Navigation?.GetFocused ()))
{
App?.Navigation?.SetFocused (App?.TopRunnableView?.MostFocused);
}
App?.TopRunnableView?.SetNeedsDraw ();
}
return ret;
}
/////
///// Locates the popover menu at . The actual position of the menu will be
///// adjusted to
///// ensure the menu fully fits on the screen, and the mouse cursor is over the first cell of the
///// first MenuItem (if possible).
/////
///// If , the current mouse position will be used.
//public void SetPosition (Point? idealScreenPosition = null)
//{
// idealScreenPosition ??= App?.Mouse.LastMousePosition;
// if (idealScreenPosition is null)
// {
// return;
// }
// Point pos = idealScreenPosition.Value;
// if (!Root.IsInitialized)
// {
// Root.App ??= App;
// Root.BeginInit ();
// Root.EndInit ();
// Root.Layout ();
// }
// pos = GetMostVisibleLocationForSubMenu (Root, pos);
// Root.X = pos.X;
// Root.Y = pos.Y;
//}
}