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; //} }