bauiv1lib.docui package¶
Functionality for using doc-ui on top of bauiv1.
Threading design¶
Doc-ui deliberately offloads as much processing as possible to
background threads, keeping logic-thread work to the bare minimum
(instantiating widgets and running actions/effects). A request’s whole
journey — controller fulfillment (including cloud/web round-trips),
response validation, asset-package resolution (marshalled to the logic
thread only for the async resolve await itself), l-string decode, and
full page prep — runs via DocUIController._process_request_in_bg on a
capped, self-retiring background thread (see _bgrunner), kept off the
shared threadpool because this prep is long and
blocking (an asset-package construct/download can tie a thread up for
seconds). Only the final prepped page is pushed back to the logic thread
for widget instantiation.
Code called from that flow (controller fulfill_request overrides
especially) should preserve this: do the heavy lifting where you are
called (the bg thread) rather than pushing work to the logic thread,
and never assume logic-thread context without checking.
- class bauiv1lib.docui.DebugDrawKind(*values)[source]¶
Bases:
EnumKinds of doc-ui element whose debug drawing can be forced on.
Each element of a page can ask for its own debug drawing (its
debugflag); switching a kind on here draws it for every such element on every page, whatever the page says.LAYOUTis windows’ and popups’ own (no page asks for it): the rects a page is laid out against – where its scroll area reaches out to, the content rect its layout gives it, and where its content starts within that by its insets – plus where the scroll area’s edge fades end, and any viewer pane.SHOW_AREASshows, for whichever row is selected, what selecting it must bring into view: its titles and footnote, plus any section heading or note attached to it. Selection brings that to the page’s inset rect at least, and nudges it further toward the middle (unless the “DocUI No Selection Centering” toggle is on).- BUTTONS = 'buttons'¶
- DECORATIONS = 'decorations'¶
- LAYOUT = 'layout'¶
- ROWS = 'rows'¶
- SECTIONS = 'sections'¶
- SHOW_AREAS = 'show_areas'¶
- class bauiv1lib.docui.DocUIController[source]¶
Bases:
objectManages interactions between DocUI clients and servers.
Can include logic to handle all requests locally or can submit them to be handled by some server or can do some combination thereof.
- class ErrorType(*values)[source]¶
Bases:
EnumTypes of errors that can occur in request processing.
- COMMUNICATION_ERROR = 'communication'¶
- GENERIC = 'generic'¶
- NEED_UPDATE = 'need_update'¶
- NOT_SIGNED_IN = 'not_signed_in'¶
- UNDER_CONSTRUCTION = 'under_construction'¶
- create_window(request: DocUIRequest | DocUIRoute, *, transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, auxiliary_style: bool = True, uiopenstateid: str | None = None, suppress_win_extra_type_warning: bool = False, options: WindowOptions | None = None) DocUIWindow[source]¶
Create a new window to handle a request.
The window opens as
optionssay; anything they leave unset comes from a route’s own defaults (itsget_window_layout()and such), or else the general defaults (seeWindowOptions).
- error_response(request: DocUIRequest, error_type: ErrorType = ErrorType.GENERIC, custom_message: str | None = None) DocUIResponse[source]¶
Build a simple error message page.
A message is included based on
error_type. Passcustom_messageto override this.Messages are language-agnostic (bundled-package strings), so error pages localize like any other doc-ui content; a
custom_messageshows verbatim (untranslated).
- fulfill_request(request: DocUIRequest) DocUIResponse[source]¶
Handle request fulfillment.
Expected to be overridden by child classes.
Be aware that this will always be called in a background thread.
This method is expected to always return a response, even in the case of errors. Use
error_response()to translate error conditions to responses.The one exception to this rule (no pun intended) is the
efro.error.CleanErrorexception. This can be raised as a quick and dirty way to show custom error messages. The coderaise CleanError('Something broke.')will have the same effect asreturn self.error_response(custom_message='Something broke.').
- fulfill_request_web(request: DocUIRequest | DocUIRoute, url: str) DocUIResponse[source]¶
Fulfill a request by sending it to a webserver.
- get_cache_key_extra() str | None[source]¶
Extra identity for response caching.
Cached responses are keyed by controller class, request, account and locale. A controller whose instance state changes what it returns for a given request must declare that state here; otherwise two instances differing in it share one cache entry and briefly show each other’s pages.
Return
Noneto opt out of caching entirely, which is the right answer when a response depends on state that cannot be summarized as a string.
- get_local_action_press_sound(name: str) PressSound[source]¶
What a button plays when pressed to run a local-action.
Given the local-action’s name. The default clicks; typed controllers answer per local-action type (see
bacommon.docui.routes.DocUILocalActionBase.get_press_sound()).
- get_page_state_poll_interval() float | None[source]¶
How often to call
poll_page_state()(None = never).For client-local pages mirroring values that can change behind their back (fullscreen toggled by a hotkey, say). Polling runs while a window shows a page that has state and isn’t waiting on a request.
- classmethod get_window_extra_type_id() str[source]¶
Return a string suitable for the
window_extra_type_idarg toauxiliary_window_activate().This ensures your doc-ui window is identified distinctly from other doc-ui windows for navigation purposes.
- get_window_toolbar_visibility() Literal['menu_full', 'menu_minimal'][source]¶
Which toolbar our windows show.
Everything by default. Settings-style pages reachable mid-game typically return
'menu_minimal'unlessbauiv1.in_main_menu(), as the classic settings windows do.
- local_action(action: DocUILocalAction) None[source]¶
Do something locally on behalf of the doc-ui.
Controller classes can override this to expose named actions that can be triggered by doc-ui button presses, responses, etc.
Of course controllers can also perform arbitrary local actions alongside their normal request fulfillment; this is simply a way to do so without needing to provide actual ui pages alongside.
Be very careful and focused with what you expose here, especially if your doc-ui pages are coming from untrusted sources. Generally things like launching or joining games are good candidates for local actions.
- poll_page_state(window: DocUIWindow) dict[source]¶
Current values for (some of) a window’s page state.
Called every
get_page_state_poll_interval()seconds. Return wire-form values keyed as in the state (seebacommon.docui.routes.DocUIState.key()); any differing from what the page holds are pushed into it, updating the controls showing them without rebuilding anything.
- replace(win: DocUIPageHost, request: DocUIRequest, *, origin_widget: bui.Widget | None = None, is_refresh: bool = False) None[source]¶
Kick off a request to replace existing window contents.
A refresh (
is_refresh) saves the window’s shared state first, as a replace action does, so the rebuilt page comes back with the same selection. Without it, a refresh kicked off directly (a local action re-rendering its page, say) restores whatever was saved last – often from when the window opened.
- restore(win: DocUIWindow, *, last_response: DocUIResponse | None, has_had_response: bool) DocUIWindow[source]¶
Restore a window from previous state.
May immediately display old results or may kick off a new request.
Called when a window shared state is being restored.
- run_action(window: DocUIPageHost, widgetid: str | None, action: bacommon.docui.v2.Action | None, is_timed: bool = False, trigger: str | None = None) None[source]¶
Called when a button is pressed in a doc-ui.
(Or when a timed action fires, or when an input row with an on-change action changes;
triggeris its state key then.)
Called when a window shared state is being saved.
- class bauiv1lib.docui.DocUILocalAction(name: str, args: dict, widget: bui.Widget | None, window: DocUIWindow, trigger: str | None = None)[source]¶
Bases:
objectContext for a local-action.
- state(statetype: type[T]) T | None[source]¶
The page’s current state, as a given state type.
None if the page has no state or its state is of some other type. Input rows write their values here as they change, so this is the live value for an action fired mid-interaction (a slider’s
on_drag, say).
- window: DocUIWindow¶
The window the action belongs to. For one pressed in a popup, that is the window the popup is over (see
popup).
- class bauiv1lib.docui.DocUIPageHost(controller: DocUIController, request: DocUIRequest)[source]¶
Bases:
objectSomething showing a doc-ui page: a window, or a popup over one.
Holds what any page needs wherever it is shown: the request that fetched it, its live page state, the lock held while a request is out, and its animatable widgets. Controllers and page prep work against this; what differs between the two kinds of host (their chrome and geometry, how they close, whether they keep a place in the back stack) lives in
DocUIWindowandDocUIPopupWindow.A mixin listed after a
bauiv1.Windowsubclass, whose constructor calls ours first (explicitly; ours is not in the window’ssuper()chain).- anim_targets¶
Our page’s client-effect-animatable widgets.
- lock_ui(origin_widget: Widget | None = None) None[source]¶
Stop UI interactions during some operation.
- property page_state: dict | None¶
Current state values for the page we are showing, if any.
This is the wire form; things knowing the type of state they expect can decode it via that type.
- property request: DocUIRequest¶
The current request.
Should only be accessed from the logic thread while the ui is unlocked.
- request_for_action(request: bacommon.docui.v2.Request, *, sets: dict | None, state: dict | None, trigger: str | None = None) bacommon.docui.v2.Request[source]¶
Return an action’s request as it should actually go out.
Requests fired from a page carry that page’s current state: what the action explicitly provides if anything, or otherwise ours with the action’s
setsapplied. Those fired from a popup carry the parent page’s state too.
- row_bounds: list[tuple[list[bui.Widget], float, float]]¶
Our page’s navigable rows, each as its selectable widgets with its vertical extent (top, bottom) in the page, as doc-ui lays it out. Selection should keep that extent inside our content rect (see DebugDrawKind.LAYOUT); for checks.
- set_last_response(response: DocUIResponse, success: bool, *, redisplay: bool = False) None[source]¶
Set a response to a request.
Pass
redisplaywhen this is an old response being shown again (pending a refresh) rather than a new arrival.
- class bauiv1lib.docui.DocUIWindow(controller: DocUIController, request: DocUIRequest, *, transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, auxiliary_style: bool = True, uiopenstateid: str | None = None, suppress_win_extra_type_warning: bool = False, has_had_response: bool = False, options: WindowOptions | None = None, pane: PaneMode | None = None)[source]¶
Bases:
MainWindow,DocUIPageHostWindow showing doc-ui content.
Provide a custom id for window shared state.
Unlike
MainWindowState, which is used to save and restore a single main-window instance, shared-state is intended to hold values that can apply to multiple instances of a window.By default, shared state uses the window class as an index (so is shared by all windows of the same class), but this method can be overridden to provide more distinct states. For example, a store-page main-window class might want to keep distinct states for different sub-pages it can display instead of having a single state for the whole class.
Note that shared state only persists for the current run of the app.
- get_main_window_state() MainWindowState[source]¶
Return a WindowState to recreate this specific window.
Used to gracefully return to a window from another window or ui system.
Restore state from the provided shared state dict.
Can be overridden by subclasses to restore custom data.
Save state into the provided shared state dict.
Can be overridden by subclasses to save custom data.
- main_window_should_preserve_selection() bool[source]¶
Whether this window should auto-save/restore selection.
If enabled, selection will be stored in the window’s shared state. See
get_main_window_shared_state_id()for more info about main-window shared-state.The default value of None results in a warning to explicitly override this (as the implicit default will change from False to True after api 9 support ends).
- main_window_should_scroll_to_restored_selection(widget: Widget) bool[source]¶
Whether restoring selection to
widgetshould scroll to it.By default a restored selection is scrolled into view (show buffers and all). Windows that restore their scroll positions exactly can return False when the widget is already back where it was, so the restore doesn’t nudge it toward the center.
- on_main_window_close() None[source]¶
Called before transitioning out a main window.
A good opportunity to save window state/etc.
- window_describe() str[source]¶
Describe this window in a line, for diagnostics.
Used by the ui cleanup check to say where a leaked object lived (a window’s own leak report, and that of any widget-owning object created inside it). Subclasses can add what identifies them: a doc-ui window names its controller and page.
- class bauiv1lib.docui.PaneMode(side: ViewerSide, frame_style: ViewerFrameStyle)[source]¶
Bases:
objectThe viewer pane a page gets: which side it sits on, whether it’s framed.
(Its background isn’t part of this; a pane takes a new one in place.)
- frame_style: ViewerFrameStyle¶
- side: ViewerSide¶
- class bauiv1lib.docui.TypedDocUIController[source]¶
Bases:
DocUIController,GenericA controller working in type-safe routes and local-actions.
Where a plain
DocUIControllerdeals in request paths, arg dicts, and local-action names, this deals purely in the dataclasses a domain defines for such things (seebacommon.docui.routes). Pass the domain’s route and local-action unions as type args, pointget_route_type()andget_local_action_type()at the matching family classes, and implementfulfill_route()andrun_local_action().- browse_from(context: DocUILocalAction, route: RouteT, *, options: WindowOptions | None = None) None[source]¶
Open one of our pages on top of another domain’s window.
The cross-domain equivalent of a
Browse: call it on the target controller from the source controller’srun_local_action()(StoreUIController().browse_from( context, sroutes.Root())). The page opens in a new window pushed onto the source’s back stack, so backing out returns to the page the press came from (which then refreshes).Pages can’t name other domains themselves. The source domain declares one local-action per place its pages may go, and the client code handling it picks the target controller and route, so a page only ever chooses among those, passing nothing but the local-action’s own typed fields. Accordingly:
The route is the target’s own route type, so mypy rejects a route from any other domain.
Only presses can do this; a local-action run by an input row’s change or attached to a response is ignored, as is a
Browsefrom either.The route must be a GET: the press lands on a page of the target domain, never directly runs one of its POSTs.
No page state travels: the request is built from the route alone, even for a route decoded from an incoming request (which otherwise carries that request’s state along).
- final fulfill_request(request: DocUIRequest) DocUIResponse[source]¶
Handle request fulfillment.
Expected to be overridden by child classes.
Be aware that this will always be called in a background thread.
This method is expected to always return a response, even in the case of errors. Use
error_response()to translate error conditions to responses.The one exception to this rule (no pun intended) is the
efro.error.CleanErrorexception. This can be raised as a quick and dirty way to show custom error messages. The coderaise CleanError('Something broke.')will have the same effect asreturn self.error_response(custom_message='Something broke.').
- fulfill_route(route: RouteT) DocUIResponse[source]¶
Handle fulfillment for a route.
The type-safe equivalent of
fulfill_request(); the same rules apply (called in a background thread; should always return a response).
- fulfill_unrouted_request(request: bacommon.docui.v2.Request, error: str) DocUIResponse[source]¶
Handle a request that maps to none of our routes.
The default shows
error. Controllers fronting a server should generally forward the request as-is here instead; a server is free to grow pages (or arg values) that older clients have no routes for, and those should keep working.
- get_local_action_press_sound(name: str) PressSound[source]¶
What a button plays when pressed to run a local-action.
Given the local-action’s name. The default clicks; typed controllers answer per local-action type (see
bacommon.docui.routes.DocUILocalActionBase.get_press_sound()).
- classmethod get_local_action_type() type[DocUILocalActionBase][source]¶
Return the family class for the local-actions we handle.
Domains with no local-actions can leave this as is and pass
typing.Neveras their local-action type arg.
- classmethod get_route_type() type[DocUIRoute][source]¶
Return the family class for the routes we handle.
- get_window_route(window: DocUIWindow) RouteT | None[source]¶
Return the route a window is showing, if it maps to one.
- final local_action(action: DocUILocalAction) None[source]¶
Do something locally on behalf of the doc-ui.
Controller classes can override this to expose named actions that can be triggered by doc-ui button presses, responses, etc.
Of course controllers can also perform arbitrary local actions alongside their normal request fulfillment; this is simply a way to do so without needing to provide actual ui pages alongside.
Be very careful and focused with what you expose here, especially if your doc-ui pages are coming from untrusted sources. Generally things like launching or joining games are good candidates for local actions.
- run_local_action(action: ActionT, context: DocUILocalAction) None[source]¶
Do something locally on behalf of the doc-ui.
The type-safe equivalent of
local_action(); the same cautions apply. The original action is passed ascontextfor access to the originating widget and window.
- class bauiv1lib.docui.WindowOptions(layout: bacommon.docui.v2.WindowLayout | None = None, scroll_edge_style: bacommon.docui.v2.ScrollEdgeStyle | None = None, background_color: tuple[float, float, float] | None = None, cancel_button_color: tuple[float, float, float] | None = None)[source]¶
Bases:
objectHow a doc-ui window opens: its shape and look.
All of it is chosen by whatever opens the window (a
Browseaction’s fields, or a route’s defaults), since the window is built before any page arrives; pages replacing each other within a window share it. None for any of them means the default (see each). (A viewer pane, if any, is up to each page instead; seebacommon.docui.v2.Page.viewer.)On the wire these stay separate flat fields of the browse action (clients ignore ones they don’t know); here they travel together, so a new one is added in one place rather than at every hop.
- background_color: tuple[float, float, float] | None = None¶
The window’s backing color (rgb), or None for the usual (see
bacommon.docui.v2.Browse.background_color).
- cancel_button_color: tuple[float, float, float] | None = None¶
The window’s close/back button color (rgb), or None for the usual (see
bacommon.docui.v2.Browse.cancel_button_color).
- classmethod from_browse(action: bacommon.docui.v2.Browse) WindowOptions[source]¶
The options a browse action asks for.
(Its legacy
viewer_styleis ignored; pages pick their own.)
- layout: bacommon.docui.v2.WindowLayout | None = None¶
The window’s layout, or None for the route’s own (or the wide-tall layout for a request that isn’t a route).
- scroll_edge_style: bacommon.docui.v2.ScrollEdgeStyle | None = None¶
How its scroll area meets the window, or None to let the layout decide.
- with_route_defaults(request: DocUIRequest | DocUIRoute) WindowOptions[source]¶
These, with anything not chosen filled in from a route.
A route’s own defaults (its
get_window_layout()) apply to whatever wasn’t chosen; anything else is left as is.
- bauiv1lib.docui.debug_draw_enabled(kind: DebugDrawKind) bool[source]¶
Whether debug drawing is forced on for a kind of element.
- bauiv1lib.docui.get_debug_draw_toggles() list[DevConsoleToggleDef][source]¶
Dev-console toggles for our kinds, for an app-mode to offer.
Plus one that turns off selection centering, so show areas land exactly on their target. See
babase.AppMode.get_dev_console_ui_debug_draw_toggles().
- bauiv1lib.docui.set_debug_draw_enabled(kind: DebugDrawKind, enabled: bool) None[source]¶
Force debug drawing on (or stop forcing it) for a kind of element.
Pages draw these as they are laid out, so the main window is rebuilt in place to show the change; anything else showing doc-ui picks it up the next time it lays out. Not saved; off at launch.