# docking.h ## Overview
Implements a tab docking system. The docking system is based on the concepts of: * Windows (top level application windows) * Tabwells (areas where a number of tabs can live, shown in the tabbar) * Tabs (parts of application UI that can live in tabwells) The docking system does not care about how windows are created, this is managed by the OS winodw layer. To the docking system, a Window is just a rectangular area with an associated `tm_ui_o *` pointer that can be used to draw into the area. The application needs to manually register the windows it wants to use for the docking system with the docking system. A window has a root tabwell. Tabwells can be split either horizontally or vertically to create two tabwells separated by a divider. These tabwells can in turn be split further. Except for the root well of the window a tabwell is either split, or it contains a set of tabs. The root tabwell is different, it can be split, but empty of tabs. If any tabwell than the root is empty of tabs, it will be automatically merged with its sibling. A tabwell consists of a tabbar area on top where the tabs are drawn, below the tabbar is a bigger rectangular area where the content of the focused tab is being drawn. The user can switch the focused tab by clicking on the tabs in the tab bar. A tab can be dragged in the tabbar to reorder it with respect to other tabs. It can also be dragged loose from the tabbar and either dropped into a tabwell to split it or dropped on the background area to create a new root UI window.
## Index
`tm_docking_tabwell_o`
`tm_tab_create_context_t`
`TM_TAB_VT_INTERFACE_NAME`
`tm_tab_o`
`enum tm_tab_focus_event`
`TM_TAB_HISTORY_ROOT_REMOVED`
`struct tm_tab_vt_root_t`
`struct tm_docking_feed_events_args_t`
`TM_TT_TYPE__DOCKING_SETTINGS`
`enum TM_TT_PROP__DOCKING_SETTINGS`

`struct tm_tab_vt`

Static functions
`name`
`name_hash`
`create_menu_name()`
`create_menu_category()`
`create()`
`destroy()`

Object methods
`ui()`
`ui_serial()`
`hidden_update()`
`title()`
`set_root()`
`root()`
`restore_root()`
`restore_settings()`
`save_settings()`
`can_close()`
`focus_event()`
`feed_events()`
`process_dropped_os_files()`
`toolbars()`
`custom_padding()`
`need_update()`
`hot_reload()`

Flags
`cant_be_pinned`
`run_as_job`
`always_update`
`dont_restore_at_startup`
`dont_restore_root_asset_at_startup`

`struct tm_tab_i`
`vt`
`inst`
`root_id`

`enum tm_docking_tabwell_split`
`struct tm_docking_tab_info_t`
`TM_DOCKING_MAX_TABS_IN_TABWELL`
`struct tm_docking_tabwell_info_t`
`struct tm_docking_find_tab_t`
`struct tm_docking_find_tab_opt_t`
`TM_DOCKING_API_NAME`

`struct tm_docking_api`
`create_truth_types()`
`add_ui()`
`remove_ui()`
`hot_reload()`
`root()`
`split_tabwell()`
`add_tab()`
`remove_tab()`
`move_tab()`
`clear()`
`feed_events()`
`ui()`
`is_dragging_tab()`
`should_create_new_ui_for_tab()`
`focused_tabwell()`
`focused_tab()`
`tab_has_focus()`
`tabwell_info()`
`tab_info()`
`root_history()`
`clear_root_history_with_greater_counter()`
`tab_ui()`
`can_remove_ui()`
`set_focus_tab()`
`close_focused_tab()`
`close_all_tabs()`
`send_focus_event()`
`destroy_truth()`
`find_tab()`
`find_tabs()`
`pin_type()`
`pin_object()`
`toolbars_state()`

## API
### `tm_docking_tabwell_o`
~~~c typedef struct tm_docking_tabwell_o tm_docking_tabwell_o; ~~~ Opaque structure representing a tabwell.
### `tm_tab_create_context_t`
~~~c typedef struct tm_tab_create_context_t tm_tab_create_context_t; ~~~ Application defined structure passed to `tm_tab_vt->create()`. It should contain whatever data the tabs need to be created.
### `TM_TAB_VT_INTERFACE_NAME`
~~~c #define TM_TAB_VT_INTERFACE_NAME "tm_tab_vt" ~~~ Interface name for the tab vtable. Any part of the UI that can act as a tab should implement this interface.
### `tm_tab_o`
~~~c typedef struct tm_tab_o tm_tab_o; ~~~ Represents the data of a tab. The docking system treats this data as opaque, so the tab can store whatever it wants in this data.
### `enum tm_tab_focus_event`
Describes a focus event that can propagate between tabs. ~~~c enum tm_tab_focus_event { // The object was selected (clicked). TM_TAB_FOCUS_EVENT__FOCUS, // THe user explicitly asked to open the object (double-click). TM_TAB_FOCUS_EVENT__OPEN, }; ~~~
### `TM_TAB_HISTORY_ROOT_REMOVED`
~~~c #define TM_TAB_HISTORY_ROOT_REMOVED ~~~ When a root is object is removed from history it gets this counter value (see `tm_tab_vt_root_t`). This is so it can stay in the recent objects list, but it should be ignore when going through the history.
### `struct tm_tab_vt_root_t`
~~~c typedef struct tm_tab_vt_root_t { struct tm_the_truth_o *tt; tm_tt_id_t root; // NOTE(Leonardo): this is here only because the scene_tab has a different "object" at it's root that is // special porpouse. tm_tt_id_t internal_root; // A number that should be higher for objects created at a later time. Makes sure objects can // be in the history multiple times. uint64_t counter; } tm_tab_vt_root_t; ~~~
### `struct tm_docking_feed_events_args_t`
~~~c typedef struct tm_docking_feed_events_args_t { struct tm_ui_o *window_ui; tm_rect_t window_rect; float window_dpi_scale_factor; bool window_has_focus; bool window_under_cursor; TM_PAD(2); } tm_docking_feed_events_args_t; ~~~
### `TM_TT_TYPE__DOCKING_SETTINGS`
~~~c #define TM_TT_TYPE__DOCKING_SETTINGS "tm_docking_settings" #define TM_TT_TYPE_HASH__DOCKING_SETTINGS TM_STATIC_HASH("tm_docking_settings", 0xbdd017ae48779b30ULL) ~~~
### `enum TM_TT_PROP__DOCKING_SETTINGS`
~~~c enum { TM_TT_PROP__DOCKING_SETTINGS__TOOLBARS_SETTINGS = 0, // subobject_set [[TM_TT_TYPE__TOOLBAR_SETTINGS]] }; ~~~
### `struct tm_tab_vt`
Vtable for tabs. Tabs should implement this interface. Tabs are represented as vtables, so that applications can add their own application specific functionality to the tabs. An application would do this by defining a new vtable as: ~~~c struct tm_application_tab_vt { struct tm_tab_vt; void (*my_special_function)(tm_tab_o *inst); ... } ~~~ This struct has a `tm_tab_vt` as its first member, so the docking system can query for the interface and cast it to a `tm_tab_vt *`. However, application systems can query for the same interface, but cast it to a `tm_application_tab_vt *`, since they now that it what it *actually* is. This allows applicaiton system to access the extra functionality. For an example of how to use this, see `the_machinery_tab.h`.

Static functions

#### `name` ~~~c const char *name; ~~~ Name uniquely identifying this tab type. #### `name_hash` ~~~c tm_strhash_t name_hash; ~~~ A hash of the `name`. #### `create_menu_name()` ~~~c const char *(*create_menu_name)(void); ~~~ Optional. Returns the (localized) name that should be shown for this tab type in menus that allow you to create new tabs. If this function returns `NULL`, the tab type won't appear in these menus. This can be used for tabs that should only be accessible when certain feature flags are set. #### `create_menu_category()` ~~~c const char *(*create_menu_category)(void); ~~~ Optional. Returns the (localized) category that should be shown for this tab type in menus that allow you to create new tabs. If this function returns `NULL` or is not set, the tab type will appear at the root level of the menu, uncategorize. #### `create()` ~~~c struct tm_tab_i *(*create)(struct tm_tab_create_context_t *context, struct tm_ui_o *ui); ~~~ Creates a new tab of this type and returns a pointer to it. `tm_tab_create_context_t` is an application defined type containing all the data a tab needs in order to be created. `ui` is the UI that the tab will be created in. #### `destroy()` ~~~c void (*destroy)(tm_tab_o *inst); ~~~ Destroys the tab.

Object methods

#### `ui()` ~~~c void (*ui)(tm_tab_o *inst, struct tm_ui_o *ui, const struct tm_ui_style_t *uistyle, tm_rect_t rect); ~~~ Callback for drawing the content of the tab into the specified rect. The `uistyle` is the `tm_ui_api->default_style()` with the clipping rect set to `rect`. #### `ui_serial()` ~~~c void (*ui_serial)(tm_tab_o *inst, struct tm_ui_o *ui, const struct tm_ui_style_t *uistyle, tm_rect_t rect); ~~~ Optional. If implemented, called from the main UI job once all parallel UI rendering (fork/join) has finished. This can be used for parts of the UI that needs to run serially, for example because they call out to non-thread-safe function. A common pattern is to delay the call of non-thread-safe functions in `ui()` by adding them to an array and then call all functions in that array in `ui_serial()`. #### `hidden_update()` ~~~c void (*hidden_update)(tm_tab_o *inst); ~~~ Optional. If the tab wants to do some processing when it is *not* the selected tab in its tabwell, it can implement this callback. This will be called for all created tabs whose content is currently *not* visible. Note that every frame, each tab will either get a call to `ui()` or `hidden_update()`, but never both. #### `title()` ~~~c const char *(*title)(tm_tab_o *inst, struct tm_ui_o *ui); ~~~ Returns the localized title to be displayed for the tab. This typically consists of the name of the tab together with the document that is being edited, such as "Scene: Kitchen*". #### `set_root()` ~~~c void (*set_root)(tm_tab_o *inst, struct tm_the_truth_o *tt, tm_tt_id_t root); ~~~ Optional. Sets the root object of the tab. If a new Truth is loaded, this is called with `set_root(inst, new_tt, 0)`. #### `root()` ~~~c tm_tab_vt_root_t (*root)(tm_tab_o *inst); ~~~ Optional. Returns the root object and The Truth that is being edited in the tab. This is used, among other things to determine the undo queue that should be used for Undo/Redo operations when the tab has focus. #### `restore_root()` ~~~c void (*restore_root)(tm_tab_o *inst, struct tm_the_truth_o *tt, tm_tt_id_t root); ~~~ Optional. Used to notify the tab at startup that it has been restored. If not provided, the tab won't be restored at startup. #### `restore_settings()` ~~~c void (*restore_settings)(tm_tab_o *inst, struct tm_the_truth_o *tt, tm_tt_id_t settings_id); ~~~ Optional. Allow the tab to save and restore it's own *state* to the settings. For example the Asset Browser will use this to save the view size of the assets. #### `save_settings()` ~~~c tm_tt_id_t (*save_settings)(tm_tab_o *inst, struct tm_the_truth_o *tt); ~~~ #### `can_close()` ~~~c bool (*can_close)(tm_tab_o *inst); ~~~ Optional. Returns *true* if the tab can be closed right now and *false* otherwise. A tab might not be able to close if it's in the middle of an important operation. Tabs that do not implement this method can be closed at any time. #### `focus_event()` ~~~c void (*focus_event)(tm_tab_o *inst, struct tm_tab_i *from, enum tm_tab_focus_event event, struct tm_the_truth_o *tt, tm_tt_id_t object, const tm_tt_id_t *selection, uint32_t selection_n); ~~~ Optional. Notifies the tab that the focus in the tab `from` has changed to the specified object. This typically happens when the user either clicks an event in the tab (to "select" it) or double clicks it (to "open" it). The `event` parameter tells whether this was a select or open event. If the object is of a type that the tab can display, the tab can choose to change its root object to the focused object. In addition to the focused object, if the originating `from` tab supports multiple selection, it will pass the entire list of selected items in the `selection` parameter. If the receiving tab is capable of displaying multiple objects, it can choose to display the whole selection rather than the single focused object. #### `feed_events()` ~~~c void (*feed_events)(tm_tab_o *inst, const struct tm_input_event_t *events, uint32_t count, tm_docking_feed_events_args_t *args); ~~~ Optional. For feeding events to the tab. Useful for feeding events to UIs that are internal to a tab. #### `process_dropped_os_files()` ~~~c void (*process_dropped_os_files)(tm_tab_o *inst, struct tm_ui_o *ui, char **files, uint32_t num_files); ~~~ Optional. If set, the tab will recieve the path to the files that were dropped from the OS since the previous frame. #### `toolbars()` ~~~c /* carray */ struct tm_toolbar_i *(*toolbars)(tm_tab_o *inst, struct tm_temp_allocator_i *ta); ~~~ Optional. Returns a carray of toolbars to be drawn in the tab, allocated using `ta`. #### `custom_padding()` ~~~c void (*custom_padding)(tm_tab_o *inst, struct tm_ui_o *ui, tm_rect_t *content_r, float safety_padding); ~~~ Optional. Allow the tab to decide if the content rect needs to be shrinked based on the safety_padding, to make sure that the content of the tab doesn't overlap the resize margin of the window. #### `need_update()` ~~~c bool (*need_update)(tm_tab_o *inst); ~~~ Optional. Allow the tab to decide whether it's UI needs an update. Tabs that have animated components like the pong tab will return always true, while other tab may decide to return true only under certain circumstances. If not provided, the assumed default value will be false, so the tab will _not_ be updated every frame, unless it it in focus or hovering. #### `hot_reload()` ~~~c void (*hot_reload)(tm_tab_o *inst); ~~~ Optional. Will be called after any code hot reload has happened.

Flags

#### `cant_be_pinned` ~~~c bool cant_be_pinned; ~~~ If set to *true*, the tab can't be pinned even though it has a *root* function. It is otherwise assumed that all tabs that implement `root()` can be pinned. #### `run_as_job` ~~~c bool run_as_job; ~~~ If set to *true*, the tab's UI will run as a background job, parallel to the rest of the UI rendering. !!! Note: Note Setting this to *true* indicates to the docking system that the `ui()` function is thread-safe. If the function is not actually thread-safe you will see threading errors. Also note that the multi-threading is currently hidden behind the `TM_FEATURE_FLAG__MULTITHREAD_UI` feature flag. You have to turn that flag on for any UIs to be multi-threaded. #### `always_update` ~~~c bool always_update; ~~~ If set to *true*, the tab UI will be updated every frame, always and the need_update function result will be ignored. #### `dont_restore_at_startup` ~~~c bool dont_restore_at_startup; ~~~ If set to *true*, the tab will be considered _volatile_, and it won't be restored when the last opened project is automatically opened at startup, even if the user had the tab opened when the project was closed. #### `dont_restore_root_asset_at_startup` ~~~c bool dont_restore_root_asset_at_startup; ~~~ If set to *true*, the tab will be restored at startup, but the root of the tab won't be set to the one that was set during application shutdown. Basically the project will be restored, but it will be always _empty_.
### `struct tm_tab_i`
Represents a tab object. A tab object is represented as a vtable that defines its function interface and an opaque pointer to the tab's internal data. This design is used so that the application layer can extend the vtable with its own interface. #### `vt` ~~~c tm_tab_vt *vt; ~~~ Vtable for function callbacks. #### `inst` ~~~c tm_tab_o *inst; ~~~ Internal data. #### `root_id` ~~~c uint64_t root_id; ~~~ Root ID of controls in this tab.
### `enum tm_docking_tabwell_split`
Enum specifying in which direction to split a tabwell. ~~~c enum tm_docking_tabwell_split { TM_DOCKING_TABWELL_SPLIT_NONE, TM_DOCKING_TABWELL_SPLIT_RIGHT, TM_DOCKING_TABWELL_SPLIT_LEFT, TM_DOCKING_TABWELL_SPLIT_TOP, TM_DOCKING_TABWELL_SPLIT_BOTTOM, }; ~~~
### `struct tm_docking_tab_info_t`
Information about a docking tab. ~~~c typedef struct tm_docking_tab_info_t { // Tab. tm_tab_i *tab; // UI that the tab is currently docked to. struct tm_ui_o *ui; // True if the tab content is currently visible, false otherwise. bool visible; TM_PAD(7); // The time this tab was last focused. tm_clock_o last_focused; // Whether tab is pinned or not. This corresponds to one of the [[enum tm_ui_tab_pin_type]] values. uint32_t pin_type; TM_PAD(4); } tm_docking_tab_info_t; ~~~
### `TM_DOCKING_MAX_TABS_IN_TABWELL`
Maximum number of tabs that a tabwell can host. ~~~c enum { TM_DOCKING_MAX_TABS_IN_TABWELL = 32 }; ~~~
### `struct tm_docking_tabwell_info_t`
Information about a docking tabwell. ~~~c typedef struct tm_docking_tabwell_info_t { // The tabwells that are docked left, right, top and bottom of this tabwell. These are NULL if // there is no tabwell docked at that location. tm_docking_tabwell_o *left, *right, *top, *bottom; // Bias for tabwell split. float bias; // List of tabs docked in this tabwell. uint32_t num_tabs; tm_tab_i *tabs[TM_DOCKING_MAX_TABS_IN_TABWELL]; tm_rect_t last_rect; } tm_docking_tabwell_info_t; ~~~
### `struct tm_docking_find_tab_t`
Return result of `find_tab()`. ~~~c typedef struct tm_docking_find_tab_t { // Found tab. tm_tab_i *tab; // The UI where the tab lives. struct tm_ui_o *ui; } tm_docking_find_tab_t; ~~~
### `struct tm_docking_find_tab_opt_t`
Options for `find_tab()`. ~~~c typedef struct tm_docking_find_tab_opt_t { // Optional. Find tabs pinned to this tab. tm_tab_i *from_tab; // Optional. Find tabs that the to-tab is pinned to. tm_tab_i *to_tab; // Optional. If specified, only tabs in the specified UI are searched. struct tm_ui_o *in_ui; // Optional. If specified -- the goal is to open the specified asset, so prioritize tabs that // are viewing the specified asset. struct tm_the_truth_o *find_asset_tt; tm_tt_id_t find_asset; // Exclude pinned tabs (unless the pinned asset matches the find_asset). bool exclude_pinned; TM_PAD(7); } tm_docking_find_tab_opt_t; ~~~
### `TM_DOCKING_API_NAME`
~~~c #define TM_DOCKING_API_NAME "tm_docking_api" ~~~
### `struct tm_docking_api`
API for the docking system. Note that the docking system is a singleton, it doesn't need to be explicitly created. The docking system is not thread-safe. Except where explicitly noted, all API functions must be called from the main job thread. #### `create_truth_types()` ~~~c void (*create_truth_types)(struct tm_the_truth_o *tt); ~~~ Creates the docking truth types in The Truth. #### `add_ui()` ~~~c void (*add_ui)(struct tm_ui_o *ui, tm_rect_t r); ~~~ Adds a new root window to be tracked by the docking system. The window will automatically be given a root tabwell. Note that the rect passed for the `ui` will be used to compute initial values for `last_rect`, but it will never actually be used for rendering the UI, because we update the rect in the `ui()` call. #### `remove_ui()` ~~~c void (*remove_ui)(struct tm_ui_o *ui); ~~~ Removes a root window from the docking system. This will close all the tabs hosted in the window. #### `hot_reload()` ~~~c void (*hot_reload)(void); ~~~ Run after a hot reload has happened. The docking system will inform all tabs so they can act if needed. #### `root()` ~~~c tm_docking_tabwell_o *(*root)(struct tm_ui_o *ui); ~~~ Returns the root tabwell for the window. #### `split_tabwell()` ~~~c tm_docking_tabwell_o *(*split_tabwell)(tm_docking_tabwell_o *parent, enum tm_docking_tabwell_split split, float bias, tm_docking_tabwell_o **sibling); ~~~ Splits the tabwell `parent`, creating a new empty one in the specified `split` direction (right, left, top, bottom). It's sibling in the opposite direction gets the tabs (if any) of the `parent`. The function returns the new tabwell. It's sibling is returned in the `sibling` parameter. `bias` specifies how the split should be biased. A value of `0` means the tabwell and its sibling is equally sized. A value of 1 means that the split tabwell is maximized and the sibling minimized and -1 does the opposite. #### `add_tab()` ~~~c void (*add_tab)(struct tm_ui_o *ui, struct tm_docking_tabwell_o *tabwell, tm_tab_i *tab); ~~~ Adds the tab to the specified tabwell of the specified UI. If `tabwell` is `NULL`, the tab is added to the currently focused tabwell of the UI. #### `remove_tab()` ~~~c void (*remove_tab)(tm_tab_i *tab); ~~~ Removes the specified tab from its tabwell. Removing the tab does not destroy it, you have to do that explicitly by calling `destroy()` if you want to destroy it. #### `move_tab()` ~~~c void (*move_tab)(tm_tab_i *tab, struct tm_ui_o *ui, struct tm_docking_tabwell_o *tabwell); ~~~ Moves the tab from its current position to the specified tabwell. #### `clear()` ~~~c void (*clear)(void); ~~~ Resets input state. This should be called at the beginning of each frame. #### `feed_events()` ~~~c void (*feed_events)(const struct tm_input_event_t *events, uint32_t count, tm_docking_feed_events_args_t *args); ~~~ Feeds events from the input system into the docking system. This is used to handle global dragging events as well as feeding events to the tabs. Feeding to the tabs is needed because tabs may have internal UIs that need to be fed events. This should typically be called immediately after `clear()` at the beginning of a new frame. #### `ui()` ~~~c void (*ui)(struct tm_ui_o *ui, const struct tm_ui_style_t *uistyle, struct tm_ui_renderer_o *ui_renderer, tm_rect_t rect, bool ui_has_focus, const struct tm_os_dropped_file_t *dropped_files, uint32_t num_dropped_files, struct tm_tab_create_context_t *context, struct tm_the_truth_o *settings_tt, tm_tt_id_t settings_obj, float default_padding); ~~~ Renders the specified `ui`. `ui_has_focus` should be set to *true* if the ui has focus. `context` specifies a creation context that will be passed to any new tabs created by the docking system. #### `is_dragging_tab()` ~~~c tm_tab_i *(*is_dragging_tab)(tm_vec2_t *pos); ~~~ If the user is currently dragging a tab, returns a pointer to that tab, otherwise NULL. `pos` returns the (global) position of the mouse dragging the tab. #### `should_create_new_ui_for_tab()` ~~~c tm_tab_i *(*should_create_new_ui_for_tab)(struct tm_tab_create_context_t *create_context, tm_rect_t *rect); ~~~ If this function returns non-NULL, the user has dropped the returned tab outside the existing tabwells, and a new UI root (system window) should be created for the tab. `rect` is the suggested rect for the new UI in global coordinates. (`x` and `y` are taken from input mouse position. `w` and `h` are the current size of the tab's window in UI coordinates, scaled by the scale provided to `feed_events`). This function should only be called after `ui()` has been called on all UIs. The reason is that all existing UIs must have a chance to respond to the dropped tab before we can conclude that it was dropped outside any existing UI. #### `focused_tabwell()` ~~~c tm_docking_tabwell_o *(*focused_tabwell)(struct tm_ui_o *ui); ~~~ The currently focused tabwell of the ui. #### `focused_tab()` ~~~c tm_tab_i *(*focused_tab)(struct tm_ui_o *ui); ~~~ The currently focused tab of the ui. #### `tab_has_focus()` ~~~c bool (*tab_has_focus)(tm_tab_i *tab); ~~~ Returns *true* if the specified tab has focus. Thread-safe. #### `tabwell_info()` ~~~c tm_docking_tabwell_info_t (*tabwell_info)(tm_docking_tabwell_o *tw); ~~~ Returns information about the specified tabwell. #### `tab_info()` ~~~c uint32_t (*tab_info)(tm_docking_tab_info_t *tabs, uint32_t n, struct tm_ui_o *filter_ui, bool filter_visible); ~~~ Returns information about the current set of tabs in the `tabs` array. Returns the total number of tabs. `n` should be set as the size of the `tabs` array. If it is smaller than the total number of tabs, only the first `n` tabs are returned. If `filter_ui` is set, only tabs in that UI will be returned. If `filter_visible` is `true`, only visible UIs will be returned. #### `root_history()` ~~~c tm_tab_vt_root_t *(*root_history)(tm_tab_i *tab, uint32_t *n); ~~~ Returns the history of root objects for the tab. `n` is set to the size of the return value. Thread-safe. #### `clear_root_history_with_greater_counter()` ~~~c void (*clear_root_history_with_greater_counter)(tm_tab_i *tab, uint64_t counter); ~~~ For the passed tab, all history of root items that have their counter set to a value greater than `counter` will be removed. #### `tab_ui()` ~~~c struct tm_ui_o *(*tab_ui)(tm_tab_i *tab); ~~~ Returns the UI that the tab currently resides in. #### `can_remove_ui()` ~~~c bool (*can_remove_ui)(struct tm_ui_o *ui); ~~~ Returns *true* if the UI can be removed. An UI can be removed if all the tabs' `can_close()` functions return true. #### `set_focus_tab()` ~~~c void (*set_focus_tab)(struct tm_ui_o *ui, tm_tab_i *tab); ~~~ Brings the specified tab to front in its tabwell and focuses on it. #### `close_focused_tab()` ~~~c bool (*close_focused_tab)(struct tm_ui_o *ui); ~~~ Destroys the currently focused tab in the UI. Returns false if the UI has no focused tab. #### `close_all_tabs()` ~~~c void (*close_all_tabs)(struct tm_ui_o *ui); ~~~ Destroys all the tabs in the UI. #### `send_focus_event()` ~~~c void (*send_focus_event)(struct tm_tab_i *from, enum tm_tab_focus_event event, struct tm_the_truth_o *tt, tm_tt_id_t object, const tm_tt_id_t *selection, uint32_t selection_n); ~~~ Send a focus event to all tabs. Thread-safe. To be thread-safe, focus events are not sent immediately, instead they are queued and sent at the start of the next frame. #### `destroy_truth()` ~~~c void (*destroy_truth)(struct tm_the_truth_o *tt); ~~~ Remove all references to the specified truth in the tab's document history. #### `find_tab()` ~~~c tm_docking_find_tab_t (*find_tab)(tm_strhash_t type_name_hash, const tm_docking_find_tab_opt_t *opt); ~~~ Finds the "best" tab of type `type_name_hash` in the docking system, based on the options, and returns it. Thread-safe, but note that the function cannot provide any guarantee that the tab isn't destroyed after the function returns. This must be safeguarded against using other methods, such as only closing tabs at "safe" synchronization points. #### `find_tabs()` ~~~c tm_docking_find_tab_t *(*find_tabs)(tm_strhash_t type_name_hash, struct tm_temp_allocator_i *ta); ~~~ Finds all tabs of type `type_name_hash` and returns them in a carray allocated using temporary allocator `ta`. #### `pin_type()` ~~~c uint32_t (*pin_type)(struct tm_tab_i *tab); ~~~ Returns the pin type of the specified tab, this is one of the `enum tm_ui_tab_pin_type` values. Thread-safe. #### `pin_object()` ~~~c void (*pin_object)(struct tm_tab_i *tab, struct tm_the_truth_o *tt, tm_tt_id_t root); ~~~ Pins the tab to the specified object. #### `toolbars_state()` ~~~c struct tm_toolbars_state_o *(*toolbars_state)(struct tm_tab_i *tab); ~~~ Returns the toolbars state for the tab, so that code outside of `docking.c` can use `tm_toolbar_api`. Creates the state if none exist. Returns NULL if the tab is invalid.