-
Notifications
You must be signed in to change notification settings - Fork 726
Description
(Very drafty for now... just some thoughts).
This Issue is a proposal for how to build into TG v2 a consistent way for a View to have a UI element show itself outside of the View's Viewport.
Popover - A View that that is displayed outside of the View that owns it's Viewport.
There are at least these use-cases of Popovers:
Autocomplete Popup
TextView would like a list of autocomplete items to be displayed below the view, at the cursor position as the user types. The user can use mouse/keyboard to select an autocomplete item and the pop over disappears.
Current Implementation
- Adds
_popup(aListView) tothis.SuperView - Uses
Visibleto show/hide - (In Partially Adresses #2491. Refactors how
Focusworks #3627 I've had to change the implementation so_popuponly gets removed/disposed when the host is removed/disposed).
Drop-down Combobox
Current Implementation
- Does not support pop-over; The
ComboBoxneeds to be sized to allow the drop-down to show if HideDropdownListOnClick is true. _listview(of typeComboListView) is a subview ofComboboxComboListViewoverridesOnMouseEvent(which isinternal!) with a bunch of hackery to deal with when it should be displayed
Menus (from MenuBar)
Current Implementation
MenuBaris a "special" subview ofApplication.Top(Toplevel has knowledge of it).- When
MenuBaris activated (via keyboard/mouse/api) it creates instances ofMenuand adds them toTop - Both
MenuBarandMenuhave convoluted logic for sensing when the menus should close (via mouse & keyboard). - When an open
Menucloses, it is removed fromTop
Context Menus
Current Implementation
- Uses a "fake"
MenuBarthat is created whenShowis called. _menuBaris never actually added to any views;BeginInit/EndInitare called manually.
Tooltip
As a user, when I hover the mouse over a View, I'd like a temporary popup to appear providing a "tip" regarding the View's purpose.
Current Implementation
- Not currently implemented
Proposal
Tenets (Unless you know better ones...)
- There can only be one - Just like in Highlander, there can only be one Popover visible and active to the user at a time. None of the use-cases above lead to needing to have more than one, thus this is a simplifier. 1
- Its Rude to Mess With Someone Elses' Subviews - Asking View developers to have to code defensively around the fact that some Subview they add, or some other agent, is adding/removing subviews is just bad juju. It leads to bugs in object lifecycles and requires skill to get right (e.g. adding a Subview during draw can result in
Subviewsbeing changed during aforeachiteration). In this design we will ensure there's no need to mess with another View'sSubviews. - Any View can be a Popover - The design should not require a View that "Pops Over" be coded specially for that purpose.
Design
At the Application level we'll add a peer of Application.Top named Application.Popover:
- In the run loop, after
Top.Draw()is called, ifPopover.Visiblewe'll callPopover.Draw(). This will ensure the Popover is always drawn over everything else. - In keyboard handling, if
Popover.Visible && Popover.HasFocuswe'll givePopovera chance to handle key events. - In mouse handling, if
Popover.VIsibleandPopover == Applicaiton.MouseGrabViewwe'll let it have mouse events. If a click happens outside ofPopover.Framewe setPopover.Visible = false. - In focus/navigation handling, if
Popover.HasFocus, if any other View gets focus, we'll setPopover.Visible = false. - For layout, whenever
Top.LayoutSubviewsis called, we'll then callPopover.SetRelativeLayout - Two APIs:
Applicaton.ShowPopover (View popoverView)
public static bool ShowPopover (View popoverView)
{
if (Popover is {})
{
Popover.Visible = false;
}
if (!popoverView.IsInitialized)
{
popoverView.BeginInit();
popoverView.EndInit();
}
Popover = popoverView;
Popover.Visible = true;
Popover.SetRelativeLayout(screen);
}Application.HidePopover ()
public static void HidePopover ()
{
if (Popover is {})
{
Popover.Visible = false;
}
}View will have no knowledge of the popover concept.
Any View subclass that wants a Popover, will:
_myPopover = new MyPopoverView();- Note,
_myPopoverwill always havethis.SuperView is null. - Any time the popover should be displayed:
- Set
_myPopover.X/Y/Width/Heightto ??? (NEED TO FIGURE THIS OUT) - Call
Application.ShowPopover(_myPopover)
- Set
- If the view wants to explicitly hide the popover,
- Call
Application.HidePopover()
- Call
Footnotes
-
I've considered "As a user, when press a special key, I'd like all visible Views to show temporary popup providing a "tip" regarding the View's purpose." This could be implemented by having the container view showing a Popover who's job it was to show "tips" for each subview. ↩
Metadata
Metadata
Assignees
Labels
Type
Projects
Status