functui.nav

Tools to make layouts responsive to keyboard and mouse input

functui.nav.DEFAULT_NAV_BINDINGS = {' ': NavAction.SELECT_VIA_KEYBOARD, 'ctrl+d': NavAction.PAGE_DOWN, 'ctrl+u': NavAction.PAGE_UP, 'down': NavAction.NAV_DOWN, 'enter': NavAction.SELECT_VIA_KEYBOARD, 'h': NavAction.NAV_LEFT, 'j': NavAction.NAV_DOWN, 'k': NavAction.NAV_UP, 'l': NavAction.NAV_RIGHT, 'left': NavAction.NAV_LEFT, 'left mouse': NavAction.SELECT_VIA_MOUSE_START, 'left mouse released': NavAction.SELECT_VIA_MOUSE_END, 'mouse wheel down': NavAction.SCROLL_DOWN, 'mouse wheel up': NavAction.SCROLL_UP, 'page down': NavAction.PAGE_DOWN, 'page up': NavAction.PAGE_UP, 'right': NavAction.NAV_RIGHT, 'up': NavAction.NAV_UP}

A dictinary that maps the string representation of keycodes to a NavAction

class functui.nav.Direction(*values)[source]

Used to specify navigation direction for a container defined by a InteractibleID.

VERTICAL
HORIZONTAL
class functui.nav.InteractibleID(data: tuple[InteractibleIDPart, ...])[source]

Used to create keyboard navigable tree. May be used either as a container or an item.

If an id is created with the InteractibleID.child method (which is the preffered way of creating new InteractibleID’s), the parent will be saved in the child as an InteractibleIDPart part.

child(local_id: int, direction: None | Direction = None, persistent: bool = False) Self[source]

Create a new InteractibleID with specified attributes.

The newly created child will remeber this ID as its parent. (as well as all of this ID’s ancestors if there are any)

Parameters:
  • local_id – Child’s local id relative to its parent (the InteractibleID on which this method is being called on). Used to distinguish this child from other children of same parent.

  • direction – If child is used as a container, navigate it’s children by specified direction. If no direction is provided, it will be inherited from child’s parent. (the InteractibleID on which this method is being called on).

  • persistent – If child is used as a container, remember which child was active and make it active insted of just the first elemnt if this container becomes active again.

data: tuple[InteractibleIDPart, ...]

Every intercatible id stores its own part at the end of the data tuple, and its ancestors parts before it.

mutual_ancestor(b: Self) Self[source]

Get the closest ID to which both self, and a are descendants.

property parent

may error

class functui.nav.InteractibleIDPart(direction: functui.nav.Direction, local_id: int, persistent: bool, first_child_default: bool)[source]
class functui.nav.NavAction(*values)[source]

An action that is meant to be sent to NavData.update.

SELECT_VIA_KEYBOARD
SELECT_VIA_MOUSE_START

For example, if user presses down left click.

SELECT_VIA_MOUSE_END

For example, if user releases left click.

PAGE_DOWN
PAGE_UP
SCROLL_UP
SCROLL_DOWN
NAV_UP
NAV_RIGHT
NAV_DOWN
NAV_LEFT
class functui.nav.NavState(mouse_position: Coordinate = (-1, -1), last_mouse_position: Coordinate = (-1, -1), action: NavAction | None = None, last_action: NavAction | None = None, areas: MappingProxyType = mappingproxy({}), _active_id: InteractibleID = InteractibleID(data=()), _hovered_data: _HoveredData = (InteractibleID(data=()), False), _held_down: InteractibleID = InteractibleID(data=()), _held_down_is_being_dragged: bool = False, _just_held_down: InteractibleID = InteractibleID(data=()), _last_active_or_hovered_id: InteractibleID = InteractibleID(data=()), _persistent_state: MappingProxyType = mappingproxy({}), _persistent_selected_id: MappingProxyType = mappingproxy({}))[source]

A data structure storing and managing keyboard navigation and mouse data.

property active_id

The interactible that is active through keyboard navigation.

Returns:

EMPTY_INTERACTIBLE if no interactible is active

areas: MappingProxyType = mappingproxy({})

All areas that were marked by an interaction_area wrapper node.

is_active(key: InteractibleID) bool[source]

Whether an interactible or one of its descendants is active via keyboard navigation

is_held_down(key: InteractibleID) bool[source]

Whether SELECT_VIA_MOUSE_START was triggered while hovering over interactive or its descendant, but before SELECT_VIA_MOUSE_END is triggered.

is_hover(key: InteractibleID) bool[source]

Whether the mouse is hovering above an interactible or one of its descendants.

Note

Only one interactible at a time can be hovered, so if there is an overlap between interactible areas, only one of them will return true.

is_selected(key: InteractibleID) bool[source]

Whether an interactible was selected by keyboard or mouse.

This condition if often triggered by pressing enter while an interactible is active through keyboard navigation, or by releasing left click on an interactible with a mouse.

More specifically, this returns whether an interactible is active and SELECT_VIA_KEYBOARD was triggered OR an interactible is hovered and SELECT_VIA_MOUSE_END was triggered

update(res: Result | None = None, action: NavAction | None = None, nav_tree: list[InteractibleID] | None = None, mouse_position: Coordinate | None = None)[source]

Create a new NavState based on data and user input.

Parameters:
  • res – Result created from a Layout being renedered.

  • action – User input parsed as an action.

  • nav_data – The keyboard navigation tree that is used to perform keyboard navigation based on the action. InteractibleID’s must be defined in order.

  • mouse_position – Mouse position.

Returns:

A new NavState with keyboard navigation and mouse interactivity performed.

functui.nav.ROOT_HORIZONTAL = InteractibleID(data=(InteractibleIDPart(direction=<Direction.HORIZONTAL: 2>, local_id=0, persistent=False, first_child_default=False),))

A Root for a keyboard navigation tree who’s children are navigated horizontaly.

functui.nav.ROOT_VERTICAL = InteractibleID(data=(InteractibleIDPart(direction=<Direction.VERTICAL: 1>, local_id=0, persistent=False, first_child_default=False),))

A Root for a keyboard navigation tree who’s children are navigated vertically.

functui.nav.interaction_area(interactible_id: InteractibleID, dragable=False)[source]

A wrapper node that marks its child layout as interactive.

Meant to be used along with NavState.

This wrapper node also retrieves at which size and position child layout was rendered at. This allows mouse hover detection, and in a scrollable container, automatically scrolling to a child that became active through keyboard navigation.

functui.nav.v_scroll(container_id: InteractibleID, nav: NavState)[source]

Allow vertical scrolling if child does not fit into available space.