# ui.h ## Overview
Controls and IDs For tracking state, UI controls need unique IDs. You can specify an ID for a control in the `.id` field. If you don't specify an ID, the control will get the ID of the last control created + 1. Note that if you dynamically create and destroy controls, or change the order in which you draw them, the IDs of subsequent controls will change, which can affect interaction. You can prevent this by using fixed IDs for top-level controls (i.e. each graph node gets a unique fixed ID).
## Index
Skinning options
`enum tm_ui_color`
`enum tm_ui_metric`

The Truth settings for editing the Theme (color and other UI settings).
`TM_TT_TYPE__UI_THEME`
`enum TM_TT_PROP__UI_THEME`
`TM_TT_TYPE__UI_THEME_COLOR`
`enum TM_TT_PROP__UI_THEME_COLOR`

Enums for default themes.
`enum tm_ui_default_theme`
`struct tm_ui_theme_t`

Basic controls
`enum tm_ui_buffer`
`struct tm_ui_style_t`
`struct tm_ui_scrollbar_t`
`enum tm_ui_scrollbar_visibility`
`struct tm_ui_scrollview_t`
`struct tm_ui_label_t`
`enum tm_ui_align`
`struct tm_ui_text_t`
`struct tm_ui_link_t`
`struct tm_ui_button_t`
`struct tm_ui_checkbox_t`
`struct tm_ui_radio_t`
`struct tm_ui_progress_t`
`struct tm_ui_slider_t`
`enum TM_UI_SPINNER__DECIMALS`
`struct tm_ui_spinner_t`
`struct tm_ui_dropdown_t`
`struct tm_ui_textedit_t`
`TM_UI_ACTIVE_DATA__TEXTEDIT`
`TM_UI_MENU_DEFAULT_ID_BASE`
`struct tm_ui_menu_item_t`
`struct tm_ui_menubar_t`
`struct tm_ui_menu_t`
`TM_UI_ACTIVE_DATA__MENU`
`struct tm_ui_menu_result_t`
`struct tm_ui_treeitem_t`
`enum tm_ui_tab_pin_type`
`struct tm_ui_tabbar_item_t`
`struct tm_ui_tabbar_t`
`enum tm_ui_tabbar_event`
`struct tm_ui_tabbar_result_t`
`struct tm_ui_draggedtab_t`
`struct tm_ui_splitter_t`
`struct tm_ui_titlebar_t`
`struct tm_ui_titlebar_result_t`

Main interface
`enum tm_ui_cursor`
`struct tm_ui_buffers_t`
`enum tm_ui_interaction_result_t`
`struct tm_ui_mouse_help_texts_t`
`struct tm_ui_font_t`
`TM_UI_API_NAME`
`tm_ui_o`

`struct tm_ui_api`
`create()`
`destroy()`
`clear()`
`release_held_state()`
`set_window_status()`
`window_rect()`
`window_has_focus()`
`window_is_under_cursor()`
`set_feather_width()`
`feather_width()`
`set_scroll_wheel_lines()`
`feed_events()`
`feed_external_edit_key()`
`merge_overlay()`
`begin_overlay_draw_scope()`
`end_overlay_draw_scope()`
`drawing_in_overlay()`
`cursor()`

Standard controls
`pane()`
`scrollbar_x()`
`scrollbar_y()`
`begin_scrollview()`
`end_scrollview()`
`label()`
`text()`
`text_metrics()`
`wrapped_text()`
`link()`
`tooltip()`
`button()`
`pushbutton()`
`checkbox()`
`radio()`
`progress()`
`slider()`
`spinner()`
`dropdown()`
`textedit()`
`menubar()`
`menu()`
`sort_menu_items()`
`tabbar()`
`draggedtab()`
`splitter_x()`
`splitter_x_rects()`
`splitter_y()`
`splitter_y_rects()`
`titlebar()`

Interface for custom controls
`buffers()`
`reserve_draw_memory()`
`reserve_draw_memory_detailed()`
`make_id()`
`last_id()`
`create_fixed_id_range()`
`set_id()`
`set_cursor()`
`is_hovering()`
`set_responder_chain_root()`
`begin_responder_scope()`
`end_responder_scope()`
`in_responder_chain()`
`is_first_responder()`
`set_responder_chain()`
`responder_chain()`
`is_responder_chain_empty()`
`focus_on_mouse_press()`
`consume_key()`
`begin_tab_scope()`
`end_tab_scope()`
`focus_on_tab()`
`suppress_next_tab_focus()`
`clear_active()`
`set_active()`
`is_active()`
`lost_active()`
`clear_lost_active()`
`to_draw_style()`
`set_cache()`
`lookup_cache()`
`get_cache()`
`left_mouse_pressed()`
`middle_mouse_pressed()`
`right_mouse_pressed()`
`left_mouse_released()`
`middle_mouse_released()`
`right_mouse_released()`
`double_click()`
`triple_click()`
`get_mouse_help_texts()`
`theme()`
`set_theme()`
`create_custom_theme()`
`set_parent_ui()`

Multi-threading
`fork()`
`join()`
`merge_render_buffers()`
`main_ui()`

Fonts
`add_font()`
`font()`
`default_style()`

## API

Skinning options

### `enum tm_ui_color`
Color identifiers for UI skinning. ~~~c enum tm_ui_color { // Windows // Background color for window chrome. This is the color used for the menu bar, // splitters, tab bar background, etc. TM_UI_COLOR_CHROME_BACKGROUND, // Background color for windows. This is the default color for window panes. TM_UI_COLOR_WINDOW_BACKGROUND, // Color of title bar of a free-floating window. TM_UI_COLOR_WINDOW_TITLE, // Color that indicates if a window is selected TM_UI_COLOR_WINDOW_SELECTION, // Background Color for the status bar TM_UI_COLOR_WINDOW_STATUS_BAR, // Background Color for the status bar text TM_UI_COLOR_WINDOW_STATUS_BAR_TEXT, // General selection color. TM_UI_COLOR_SELECTION, // Selection color when item does not have focus. TM_UI_COLOR_SELECTION_NO_FOCUS, // Color when hovering to select an item. TM_UI_COLOR_SELECTION_HOVER, // Text // Color of UI text. TM_UI_COLOR_TEXT, // Color of disabled text. TM_UI_COLOR_DISABLED_TEXT, // Color for selected text. TM_UI_COLOR_SELECTED_TEXT, // Color for error text messages. TM_UI_COLOR_ERROR_TEXT, // Color of filtered text. TM_UI_COLOR_FILTERED_TEXT, // Objects and prototypes // Colors used to indicate prototype relations. These colors are set up to match the // TM_TT_PROTOTYPE_RELATION_* enums. I.e. the text color to use for inherited objects is // // TM_UI_COLOR_PROTOTYPE_RELATION_BASE + TM_TT_PROTOTYPE_RELATION_INHERITED TM_UI_COLOR_PROTOTYPE_RELATION_BASE, TM_UI_COLOR_PROTOTYPE_RELATION_ADDED = TM_UI_COLOR_PROTOTYPE_RELATION_BASE, TM_UI_COLOR_PROTOTYPE_RELATION_ASSET, TM_UI_COLOR_PROTOTYPE_RELATION_INHERITED, TM_UI_COLOR_PROTOTYPE_RELATION_INSTANTIATED, TM_UI_COLOR_PROTOTYPE_RELATION_REMOVED, // Control elements // Color of thin highlight lines, such as the line around buttons, etc. TM_UI_COLOR_THIN_LINES, TM_UI_COLOR_THIN_LINES_HOVER, // Color of interactive icons, such as checkboxes, arrows, etc. TM_UI_COLOR_ICONS, TM_UI_COLOR_ICONS_HOVER, TM_UI_COLOR_ICONS_ACTIVE, TM_UI_COLOR_ICON_DIRECTORY, TM_UI_COLOR_ICON_ASSET, TM_UI_COLOR_ICON_ENTITY, TM_UI_COLOR_ICON_IMAGE, TM_UI_COLOR_ICON_MATERIAL, // Background color for controls (buttons, text fields, etc). TM_UI_COLOR_CONTROL_BACKGROUND, TM_UI_COLOR_CONTROL_BACKGROUND_HOVER, TM_UI_COLOR_CONTROL_BACKGROUND_ACTIVE, // Background color for menu. TM_UI_COLOR_MENU_BACKGROUND, // Color for selected menu items. TM_UI_COLOR_MENU_SELECTED, // Color for menu bar hovering. TM_UI_COLOR_MENU_MENUBAR_HOVER, // Color for tooltips TM_UI_COLOR_TOOLTIP_BACKGROUND, TM_UI_COLOR_TOOLTIP_BORDER, TM_UI_COLOR_TOOLTIP_TEXT, // Color for viewport TM_UI_COLOR_VIEWPORT_BACKGROUND, TM_UI_COLOR_VIEWPORT_SELECTION, // Color for links. TM_UI_COLOR_LINK, TM_UI_COLOR_LINK_HOVER, //Node background colors TM_UI_COLOR_NODE_BACKGROUND, TM_UI_COLOR_NODE_GPU_BACKGROUND, TM_UI_COLOR_NODE_GPU_BACKGROUND_WATERMARK_TEXT, TM_UI_COLOR_NODE_EXECUTION_COLOR, //Grid color for thin and thick lines in the graphs TM_UI_COLOR_GRAPH_GRID_THIN_LINES, TM_UI_COLOR_GRAPH_GRID_THICK_LINES, // Color of scrollbars TM_UI_COLOR_SCROLLBAR_BACKGROUND, TM_UI_COLOR_SCROLLBAR, TM_UI_COLOR_SCROLLBAR_HOVER, TM_UI_COLOR_SCROLLBAR_ACTIVE, // Toolbar colors TM_UI_COLOR_TOOLBAR_DRAG_HANDLE, TM_UI_COLOR_TOOLBAR_DROP_ZONE, TM_UI_COLOR_TOOLBAR_THIN_LINES, TM_UI_COLOR_TOOLBAR_THIN_LINES_HOVER, TM_UI_COLOR_TOOLBAR_CONTROL_BACKGROUND, TM_UI_COLOR_TOOLBAR_CONTROL_BACKGROUND_HOVER, TM_UI_COLOR_TOOLBAR_CONTROL_BACKGROUND_ACTIVE, // Total number of colors. TM_UI_COLOR_COUNT, }; ~~~
### `enum tm_ui_metric`
Metric identifiers for UI skinning ~~~c enum tm_ui_metric { // Line width when drawing buttons, etc. TM_UI_METRIC_LINE_WIDTH, // Height of window title. TM_UI_METRIC_WINDOW_TITLE_HEIGHT, // Minimum size of windows. TM_UI_METRIC_WINDOW_MIN_SIZE, // Height of menu bar. TM_UI_METRIC_MENUBAR_HEIGHT, // Height of menu item. TM_UI_METRIC_MENU_ITEM_HEIGHT, // Width of scrollbars. TM_UI_METRIC_SCROLLBAR_WIDTH, // Padding of scrollbars. TM_UI_METRIC_SCROLLBAR_PADDING, // General margin of UI. TM_UI_METRIC_MARGIN, // Text margin for textedit and dropdown boxes TM_UI_METRIC_TEXT_MARGIN, // Size of splitter. TM_UI_METRIC_SPLITTER_SIZE, // Time to hover before tooltip is shown. TM_UI_METRIC_TOOLTIP_HOVER_TIME, // Width of tooltip box. TM_UI_METRIC_TOOLTIP_WIDTH, TM_UI_METRIC_TREE_ARROW_SCALE, TM_UI_METRIC_TREE_ICON_WIDTH, // The height of a toolbar TM_UI_METRIC_TOOLBAR_HEIGHT, // The margin between a toolbars edge and the items within TM_UI_METRIC_TOOLBAR_OUTER_MARGIN, // The margin between toolbar items TM_UI_METRIC_TOOLBAR_INNER_MARGIN, // The margin of a toolbar in Widget drawing mode. TM_UI_METRIC_TOOLBAR_WIDGET_MARGIN, // Total number of metrics. TM_UI_METRIC_COUNT, }; ~~~

The Truth settings for editing the Theme (color and other UI settings).

### `TM_TT_TYPE__UI_THEME`
~~~c #define TM_TT_TYPE__UI_THEME "tm_ui_theme" #define TM_TT_TYPE_HASH__UI_THEME TM_STATIC_HASH("tm_ui_theme", 0x2068b64b38668594ULL) ~~~
### `enum TM_TT_PROP__UI_THEME`
~~~c enum { // Name of the theme. TM_TT_PROP__UI_THEME__NAME, // string // Default theme that this theme is based on. TM_TT_PROP__UI_THEME__BASED_ON, // uint32_t // Colors for this theme. TM_TT_PROP__UI_THEME__COLORS, // subobject_set [[TM_TT_TYPE__UI_THEME_COLOR]] }; ~~~
### `TM_TT_TYPE__UI_THEME_COLOR`
~~~c #define TM_TT_TYPE__UI_THEME_COLOR "tm_ui_theme_color" #define TM_TT_TYPE_HASH__UI_THEME_COLOR TM_STATIC_HASH("tm_ui_theme_color", 0xf6bf12b10fe9b075ULL) ~~~
### `enum TM_TT_PROP__UI_THEME_COLOR`
~~~c enum { TM_TT_PROP__UI_THEME_COLOR__NAME, // string TM_TT_PROP__UI_THEME_COLOR__COLOR, // subobject [[TM_TT_TYPE__COLOR_RGBA]] }; ~~~

Enums for default themes.

### `enum tm_ui_default_theme`
~~~c enum tm_ui_default_theme { TM_UI__DEFAULT_THEME__DARK, TM_UI__DEFAULT_THEME__LIGHT, }; ~~~
### `struct tm_ui_theme_t`
Theme settings for the UI. ~~~c typedef struct tm_ui_theme_t { // Default theme that the theme is based on. enum tm_ui_default_theme based_on; TM_PAD(4); // Theme object in The Truth. This will be 0 if we are just using the default theme. struct tm_the_truth_o *tt; tm_tt_id_t id; } tm_ui_theme_t; ~~~

Basic controls

### `enum tm_ui_buffer`
Identifies the different buffers we can draw into. ~~~c enum tm_ui_buffer { TM_UI_BUFFER_MAIN, TM_UI_BUFFER_OVERLAY, }; ~~~
### `struct tm_ui_style_t`
Style settings for UI elements. ~~~c typedef struct tm_ui_style_t { // Clip rect for drawing the element. (Added with [[tm_draw2d_api->add_clip_rect()]].) uint32_t clip; TM_PAD(4); // Font to use for text drawing. const struct tm_draw2d_font_t *font; // Scale of text. float font_scale; // Buffer to draw into. enum tm_ui_buffer buffer; // Width of feathering float feather_width; TM_PAD(4); } tm_ui_style_t; ~~~
### `struct tm_ui_scrollbar_t`
Defines a scrollbar ~~~c typedef struct tm_ui_scrollbar_t { uint64_t id; tm_rect_t rect; // Range of scrollbar (min, max) float min, max; // Size of content that is scrolled. This is in the same unit as (min, max) and // determines the size of the "thumb". float size; TM_PAD(4); } tm_ui_scrollbar_t; ~~~
### `enum tm_ui_scrollbar_visibility`
Controls when a scrollbar will be shown. ~~~c enum tm_ui_scrollbar_visibility { // The scrollbar will be shown only when the content is too big to fit the view. TM_UI_SCROLLBAR_VISIBILITY_WHEN_NEEDED, // The scrollbar will never be shown. TM_UI_SCROLLBAR_VISIBILITY_NEVER, // The scrollbar will always be shown. TM_UI_SCROLLBAR_VISIBILITY_ALWAYS, }; ~~~
### `struct tm_ui_scrollview_t`
Defines a scrollable view of a (potentially) larger canvas. ~~~c typedef struct tm_ui_scrollview_t { uint64_t id; // Rect for the view -- both the content and the scrollbars will fit in this rect. tm_rect_t rect; // Rect for the underlying canvas that we are viewing. Note that this rect is in abstract // rather than screen coordinates. Typically it will be positioned at (0,0), but you can use // another base position if it fits your use case better. tm_rect_t canvas; // Visibility of the vertical and horizontal scrollbars. enum tm_ui_scrollbar_visibility visibility_x, visibility_y; } tm_ui_scrollview_t; ~~~
### `struct tm_ui_label_t`
Defines a label. ~~~c typedef struct tm_ui_label_t { // Optional. If 0, no a id will be generated and used uint64_t id; tm_rect_t rect; uint32_t icon; TM_PAD(4); const char *text; // Optional. If NULL, no tooltip will be shown const char *tooltip; } tm_ui_label_t; ~~~
### `enum tm_ui_align`
~~~c enum tm_ui_align { TM_UI_ALIGN_LEFT, TM_UI_ALIGN_CENTER, TM_UI_ALIGN_RIGHT, }; ~~~
### `struct tm_ui_text_t`
Defines a text. ~~~c typedef struct tm_ui_text_t { // Optional. If 0, no a id will be generated and used uint64_t id; tm_rect_t rect; const char *text; // Optional. If NULL, no tooltip will be shown const char *tooltip; // Optional. If NULL, TM_UI_COLOR_TEXT will be used. const struct tm_color_srgb_t *color; enum tm_ui_align align; TM_PAD(4); } tm_ui_text_t; ~~~
### `struct tm_ui_link_t`
Defines a link. ~~~c typedef struct tm_ui_link_t { // Optional. If 0, no a id will be generated and used uint64_t id; tm_rect_t rect; const char *text; // Optional. If NULL, no tooltip will be shown const char *tooltip; // Optional. If NULL, TM_UI_COLOR_LINK will be used. const struct tm_color_srgb_t *color; enum tm_ui_align align; TM_PAD(4); } tm_ui_link_t; ~~~
### `struct tm_ui_button_t`
Defines a button. ~~~c typedef struct tm_ui_button_t { // Optional. If 0, no a id will be generated and used uint64_t id; tm_rect_t rect; tm_rect_t visible_rect; // Optional. [[enum tm_ui_icon]] to draw before the text. uint32_t icon; TM_PAD(4); const char *text; // Optional. If NULL, TM_UI_COLOR_LINK will be used. const struct tm_color_srgb_t *text_color; // Optional. If NULL, no tooltip will be shown const char *tooltip; float text_offset_y; bool is_disabled; bool hide_background; bool hide_margins; TM_PAD(1); } tm_ui_button_t; ~~~
### `struct tm_ui_checkbox_t`
Define a checkbox. ~~~c typedef struct tm_ui_checkbox_t { uint64_t id; tm_rect_t rect; bool is_disabled; TM_PAD(7); const char *text; // Optional. If NULL, no tooltip will be shown const char *tooltip; } tm_ui_checkbox_t; ~~~
### `struct tm_ui_radio_t`
Defines a radio button. ~~~c typedef struct tm_ui_radio_t { uint64_t id; tm_rect_t rect; bool is_disabled; TM_PAD(7); const char *text; const char *tooltip; } tm_ui_radio_t; ~~~
### `struct tm_ui_progress_t`
Defines a progress bar. ~~~c typedef struct tm_ui_progress_t { uint64_t id; tm_rect_t rect; // Optional text on progress bar. const char *text; } tm_ui_progress_t; ~~~
### `struct tm_ui_slider_t`
Defines a slider. ~~~c typedef struct tm_ui_slider_t { uint64_t id; tm_rect_t rect; bool is_disabled; TM_PAD(3); // Range of slider. float min, max; // Step of slider. If non-zero, slider changes will be rounded to an integral number of steps. // I.e. with `{min = 0, max = 0.5, step = 0.1}`, the slider can take on the values 0, 0.1, 0.2, // 0.3, 0.4 and 0.5. float step; } tm_ui_slider_t; ~~~
### `enum TM_UI_SPINNER__DECIMALS`
Enumerator specifying how many decimals to show when dragging the spinner. ~~~c enum { // The number of decimals is based on the current value. I.e. if the value is 2.01, two decimals // will be used. If it is 2.1, one decimal will be used. The number of decimals will always be // at least one when this method is used. TM_UI_SPINNER__DECIMALS__DEFAULT, // Use the explicitly specified number of decimals. TM_UI_SPINNER__DECIMALS__0, TM_UI_SPINNER__DECIMALS__1, TM_UI_SPINNER__DECIMALS__2, TM_UI_SPINNER__DECIMALS__3, TM_UI_SPINNER__DECIMALS__4, TM_UI_SPINNER__DECIMALS__5, }; ~~~
### `struct tm_ui_spinner_t`
Defines a spinner. A spinner is a textbox that accepts a number value, that also allows you to modify that value by alt-dragging in the textbox. ~~~c typedef struct tm_ui_spinner_t { uint64_t id; tm_rect_t rect; bool is_disabled; TM_PAD(7); // Range of spinner. If these are both zero, range is considered infinite. double min, max; // Amount the value is changed per pixel of "spinning" (alt-dragging). If zero, the value is // set automatically based on the original value. double value_per_pixel; // Specifies how many decimals to use for the value, using one of the TM_UI_SPINNER__DECIMALS__* // enums. uint32_t decimals; TM_PAD(4); const char *tooltip; } tm_ui_spinner_t; ~~~
### `struct tm_ui_dropdown_t`
Defines a drop down value. ~~~c typedef struct tm_ui_dropdown_t { uint64_t id; tm_rect_t rect; bool is_disabled; TM_PAD(7); // Texts of items in the dropdown menu. const char **items; // Tooltips for items in the dropdown menu. This can be NULL if items don't have tooltips. const char **tooltips; // Number of items in the dropdown menu. uint32_t num_items; TM_PAD(4); } tm_ui_dropdown_t; ~~~
### `struct tm_ui_textedit_t`
Defines an edit text box. ~~~c typedef struct tm_ui_textedit_t { uint64_t id; tm_rect_t rect; bool is_disabled; bool is_password; TM_PAD(6); // Default text to display (grayed out) if the box is empty. const char *default_text; // If true, all of the text will be selected when the text box is activated with a mouse click. // If false, the caret will be put where the mouse is clicked. bool select_all_on_mouse_activate; // If true, the text edit control will be scrolled to the end of the string when it's not // active. This is useful when the end of the string is more important than the beginning (for // example for file paths). bool scroll_to_end; // If true, all the text will be selected and the caret will be placed at the end of it whenever the user passes a preexisting string // the first time the text_edit function is called. bool select_all_on_startup; TM_PAD(1); // Can be used to force text selection in the edit box. If .all is true, selects the entire // range. If .range is true, selects the (start, end) range. Setting .all or .range to true will // also force activation of the text box if it is not currently active (since only active text // boxes have a selection state). struct { bool all; bool range; TM_PAD(2); uint32_t start; uint32_t end; } select; } tm_ui_textedit_t; ~~~
### `TM_UI_ACTIVE_DATA__TEXTEDIT`
~~~c #define TM_UI_ACTIVE_DATA__TEXTEDIT ~~~ Active data format for textedit item. Use this if you use `set_active()` to activate a text edit item.
### `TM_UI_MENU_DEFAULT_ID_BASE`
~~~c enum { TM_UI_MENU_DEFAULT_ID_BASE = 0xf0000000 }; ~~~
### `struct tm_ui_menu_item_t`
Defines an item in a menu. Menu items can be regular menu items, toggle items (with a checkmark) and submenus. ~~~c typedef struct tm_ui_menu_item_t { // Text of the menu item. const char *text; // Accelerator keys to display. Note that the UI doesn't automatically react // to accelerator key presses. That has to be implemented by the caller. const char *accelerator; // Tooltip to display when item is hovered. const char *tooltip; // ID identifying this item. If ID is 0, the item will be assigned a default ID. // The default ID for a menu item is [[TM_UI_MENU_DEFAULT_ID_BASE]] + index. // Note that menu item IDs live in a separate space and do not collide with control IDs. uint64_t item_id; // If non-NULL, this menu item is a toggle item, and `*toggle` determines if it // has a checkmark or not. The UI system will change the value of `*toggle` // when the item is selected. bool *toggle; // This can be used to set a checkmark for items that do not use the toggle variable. bool is_checked; // True if there is a submenu associated with this item. bool has_submenu; // True if this menu item is disabled and can't be selected. bool is_disabled; // True if this menu item should be hidden (i.e. not shown in the menu). bool is_hidden; // [[enum tm_ui_icon]] to show before the menu item text. uint32_t icon; } tm_ui_menu_item_t; ~~~
### `struct tm_ui_menubar_t`
Defines a menubar. ~~~c typedef struct tm_ui_menubar_t { uint64_t id; // Position where menu should be displayed. tm_vec2_t pos; // Width of menu bar. float width; // Padding to account for. float padding_left_right; // Items in the menu/menubar. const tm_ui_menu_item_t *items; // Number of items in the menu/menubar. uint32_t num_items; TM_PAD(4); } tm_ui_menubar_t; ~~~
### `struct tm_ui_menu_t`
Defines a menu. ~~~c typedef struct tm_ui_menu_t { // Position where menu should be displayed. tm_vec2_t pos; // Items in the menu/menubar. const tm_ui_menu_item_t *items; // Number of items in the menu/menubar. uint32_t num_items; TM_PAD(4); } tm_ui_menu_t; ~~~
### `TM_UI_ACTIVE_DATA__MENU`
~~~c #define TM_UI_ACTIVE_DATA__MENU ~~~ Active data format for menus. Use this when you use `set_active()` to activate a context menu.
### `struct tm_ui_menu_result_t`
The result of a menu or menubar operation. ~~~c typedef struct tm_ui_menu_result_t { // `item_id` of selected item or `0` if no item was selected. // Regular and toggle items are considered selected when they are picked. // Submenus are considered selected when the submenu is open. uint64_t selected_item_id; // Text of the selected item, or `NULL` if no item is selected. const char *selected_text; // ID of the item currently being hovered using the mouse or highlighted using the keyboard, // otherwise 0. uint64_t highlighted_item_id; // If a submenu item is selected -- the position where the submenu should be displayed. tm_vec2_t submenu_pos; } tm_ui_menu_result_t; ~~~
### `struct tm_ui_treeitem_t`
Defines a tree item. ~~~c typedef struct tm_ui_treeitem_t { uint64_t id; tm_rect_t rect; const char *text; } tm_ui_treeitem_t; ~~~
### `enum tm_ui_tab_pin_type`
~~~c enum tm_ui_tab_pin_type { // Tab is not pinned. TM_UI_TAB_PIN_TYPE__NONE, // Tab is pinned to the specified object. TM_UI_TAB_PIN_TYPE__OBJECT, // Tab is pinned to a set of other tabs. TM_UI_TAB_PIN_TYPE__TABS, // Tab is pinned to a set of windows (other than the one its currently in). TM_UI_TAB_PIN_TYPE__WINDOWS, }; ~~~
### `struct tm_ui_tabbar_item_t`
~~~c typedef struct tm_ui_tabbar_item_t { const char *text; uint64_t id; // Controls if the item should have a close box. bool has_close_box; // Controls if the item has a pin. bool has_pin; TM_PAD(2); enum tm_ui_tab_pin_type pin_type; } tm_ui_tabbar_item_t; ~~~
### `struct tm_ui_tabbar_t`
Defines a tab bar. ~~~c typedef struct tm_ui_tabbar_t { uint64_t id; tm_rect_t rect; // Texts and IDs of tab items. tm_ui_tabbar_item_t *items; uint32_t num_items; // If true, the tabs can be reordered by dragging. bool can_drag; // If true, the tabs can be "dragged off" the tab bar into separate windows. // Note that the UI doesn't handle this event (it can't possibly, since it // doesn't have any concept of system windows). It just notifies the higher // layer so that it can take appropriate action. bool can_drag_off; // If true, the user is dragging an external tab (i.e., a tab that has been dragged off its // tab bar). bool is_dragging_external_tab; TM_PAD(1); // This parameter should be NULL if the user is not dragging an external item, or if that item // is not from this tab bar. If the user is dragging an item from this tab bar, this should be // set to that item. This will prevent drawing of the dragged tab in the tab bar. const char **dragged_external_item; } tm_ui_tabbar_t; ~~~
### `enum tm_ui_tabbar_event`
Specifies events that happen in a tab bar. ~~~c enum tm_ui_tabbar_event { // Nothing happened. TM_UI_TABBAR_EVENT_NONE, // The selected/displayed tab changed. TM_UI_TABBAR_EVENT_SELECT, // A tab was closed. TM_UI_TABBAR_EVENT_CLOSE, // The tab bar was reordered by dragging. TM_UI_TABBAR_EVENT_REORDER, // A tab was dragged off the tab bar completely. TM_UI_TABBAR_EVENT_DRAG_OFF, // An externally dragged tab was dropped on the tab bar. TM_UI_TABBAR_EVENT_EXTERNAL_DROP, // Open context menu for tab. The item is set to the tab the context menu was opened for, or // to `num_items` if pressed in the end area. TM_UI_TABBAR_EVENT_CONTEXT_MENU, // Tab pin was clicked. TM_UI_TABBAR_EVENT_PIN, }; ~~~
### `struct tm_ui_tabbar_result_t`
The result of a tab bar operation. ~~~c typedef struct tm_ui_tabbar_result_t { // Event that occurred in the tab bar. enum tm_ui_tabbar_event event; // Item that was affected by the event. uint32_t item; // In the case of a [[TM_UI_TABBAR_EVENT_REORDER]] -- specifies the new position of the item. uint32_t new_position; // In the case of a [[TM_UI_TABBAR_EVENT_DRAG_OFF]] -- the offset from the mouse position where // the dragged tab should be drawn. tm_vec2_t drag_offset; } tm_ui_tabbar_result_t; ~~~
### `struct tm_ui_draggedtab_t`
Defines a dragged tab from a tab bar. ~~~c typedef struct tm_ui_draggedtab_t { uint64_t id; tm_rect_t rect; const char *text; // Controls if the dragged tab should be drawn with a close buttons. bool has_close_box; // Controls if the dragged tab has a pin. bool has_pin; TM_PAD(2); enum tm_ui_tab_pin_type pin_type; } tm_ui_draggedtab_t; ~~~
### `struct tm_ui_splitter_t`
Defines a splitter. ~~~c typedef struct tm_ui_splitter_t { uint64_t id; tm_rect_t rect; // Minimum size of split panel. float min_size; TM_PAD(4); } tm_ui_splitter_t; ~~~
### `struct tm_ui_titlebar_t`
Defines a title bar. ~~~c typedef struct tm_ui_titlebar_t { uint64_t id; // The rect of the window. tm_rect_t rect; // Should be set to true if the window has focus. bool has_focus; // Should be set to true if the window is maximized. bool is_maximized; TM_PAD(6); // The caption of the window. const char *caption; float border_width; float caption_height; float caption_padding; TM_PAD(4); // The texture for the window icon. uint32_t icon_texture; TM_PAD(4); } tm_ui_titlebar_t; ~~~
### `struct tm_ui_titlebar_result_t`
Result of a title bar interaction. ~~~c typedef struct tm_ui_titlebar_result_t { // *true* if the window should be closed. bool close_window; // *true* if the window should be normalized. bool restore_window; // *true* if the window should be maximized. bool maximize_window; // *true* if the window should be minimized. bool minimize_window; // Returns the rect where the content of the window should be drawn. tm_rect_t content_r; } tm_ui_titlebar_result_t; ~~~

Main interface

### `enum tm_ui_cursor`
Enumeration for the different kinds of cursors that the UI wants to display. Cursor names are borrowed from CSS, see <https://developer.mozilla.org/en/docs/Web/CSS/cursor>. ~~~c enum tm_ui_cursor { // Default cursor (arrow). TM_UI_CURSOR_DEFAULT, // Hovering over a link (hand). TM_UI_CURSOR_POINTER, // Text selection cursor (I-beam). TM_UI_CURSOR_TEXT, // Move cursor (4-way arrow). TM_UI_CURSOR_MOVE, // Scroll in any direction. TM_UI_CURSOR_ALL_SCROLL, // Resize column. TM_UI_CURSOR_COL_RESIZE, // Resize row. TM_UI_CURSOR_ROW_RESIZE, // Bidirectional resize. TM_UI_CURSOR_EW_RESIZE, TM_UI_CURSOR_NS_RESIZE, TM_UI_CURSOR_NESW_RESIZE, TM_UI_CURSOR_NWSE_RESIZE, // Drag target cursor TM_UI_CURSOR_DRAG_AND_DROP, // Hide the cursor. TM_UI_CURSOR_NONE, }; ~~~
### `struct tm_ui_buffers_t`
State for custom drawing and manipulation of the UI. ~~~c typedef struct tm_ui_buffers_t { // Vbuffers and ibuffers for drawing. struct tm_draw2d_vbuffer_t *vbuffer; struct tm_draw2d_ibuffer_t **ibuffers; // Returns the current input state. You can poke into the returned struct to // manipulate the input state, though usually it is preferable to use [[feed_events()]] // for this. struct tm_ui_input_state_t *input; // Returns the current activation state. You can poke into the returned struct // to manipulate the activation state. struct tm_ui_activation_t *activation; // Returns the metric table for the UI. The metric table can be indexed by // [[enum tm_ui_metric]]. You can use this table to both query and set the metrics. float *metrics; // Returns the color table for the UI. The color table can be indexed by [[enum tm_ui_color]]. // You can use this table to both query and set the colors. struct tm_color_srgb_t *colors; // Memory allocator. struct tm_allocator_i *allocator; } tm_ui_buffers_t; ~~~
### `enum tm_ui_interaction_result_t`
Some controls (such as sliders and sizers) allow "live interaction" with a value. For such controls we often want to distinguish between "transient" changes (dragging the slider around with the mouse) and committed changes (when the mouse is released after dragging). "Transient" changes are often reflected in the UI in various ways, providing a "preview" of the new value, but they do not create undo events. (If they did, the undo queue would quickly be filled up with transient events.) This enum is used as a return value by these controls to indicate what kind of "change" the user made -- a transient or a committed one. Note that controls that support transient changes also typically return both the "current" and the "initial" value of the parameter. The "initial" value is the value before the current interaction started. ~~~c enum tm_ui_interaction_result_t { // The value did not change or the user did not interact with the control. TM_UI_INTERACTION_RESULT_NO_CHANGE, // The value changed as a result of active interaction with the control (dragging a slider, // resizing a window). The interaction is still ongoing and no undo event should be created. TM_UI_INTERACTION_RESULT_TRANSIENT_CHANGE, // The value changed and the active interaction with the control ended. The current value (if // different from the initial one) should be committed. At this point it is appropriate to create // an undo step (for systems that support it). TM_UI_INTERACTION_RESULT_COMMIT, // The change was aborted. As a result, the current value of the control will be reset to the // initial value. Aborted interactions mean that no change was made, so no undo step should be // created. TM_UI_INTERACTION_RESULT_ABORT, }; ~~~
### `struct tm_ui_mouse_help_texts_t`
Help texts for mouse actions. ~~~c typedef struct tm_ui_mouse_help_texts_t { const char *left_mouse_pressed; const char *middle_mouse_pressed; const char *right_mouse_pressed; const char *double_click; const char *triple_click; } tm_ui_mouse_help_texts_t; ~~~
### `struct tm_ui_font_t`
Defines the return values of `font()`. ~~~c typedef struct tm_ui_font_t { // ID of the font when registered with [[add_font()]]. tm_strhash_t id; // Size of the font when registered with [[add_font()]]. uint32_t size; TM_PAD(4); // Font pointer. struct tm_draw2d_font_t *font; } tm_ui_font_t; ~~~
### `TM_UI_API_NAME`
~~~c #define TM_UI_API_NAME "tm_ui_api" ~~~
### `tm_ui_o`
~~~c typedef struct tm_ui_o tm_ui_o; ~~~
### `struct tm_ui_api`
#### `create()` ~~~c tm_ui_o *(*create)(struct tm_allocator_i *a); ~~~ Creates a new UI. #### `destroy()` ~~~c void (*destroy)(tm_ui_o *i); ~~~ Destroys a UI created by `create()`. #### `clear()` ~~~c void (*clear)(tm_ui_o *ui); ~~~ Removes all the controls from the UI and resets input state (used to begin a new frame). #### `release_held_state()` ~~~c void (*release_held_state)(tm_ui_o *ui); ~~~ Clears held modifier key state and active control state. This should be used if the UI window gains or loses focus so that the UI is not left with `alt_is_down` when you tab out of it. #### `set_window_status()` ~~~c void (*set_window_status)(tm_ui_o *ui, tm_rect_t rect, bool has_focus, bool is_under_cursor); ~~~ Sets the window status for the purpose of drawing the UI. * `rect` -- specifies the rect of the window. This is used to position pop-up items, such as menus, so that they stay within screen bounds. If this is not called, pop-up items will not be moved, but opened at the set position. * `has_focus` -- specifies whether the window that the UI lives in has focus or not in the UI. * `is_under_cursor` -- specifies whether the window that the UI lives in is under the current cursor position. If *false*, the cursor is either outside the window, or another window is covering the part of the window where the cursor is at. This is used to control hovering. We only allow "hovering" when there is no external window between the mouse and the control. #### `window_rect()` ~~~c tm_rect_t (*window_rect)(tm_ui_o *ui); ~~~ Returns the window rect set by `set_window_status()`. If the window rect hasn't been set, a zeroed `tm_rect_t` struct will be returned. #### `window_has_focus()` ~~~c bool (*window_has_focus)(tm_ui_o *ui); ~~~ Returns true if the window in which this UI is drawn has focus. #### `window_is_under_cursor()` ~~~c bool (*window_is_under_cursor)(tm_ui_o *ui); ~~~ Returns true if the window in which this UI is drawn is under the cursor. #### `set_feather_width()` ~~~c void (*set_feather_width)(tm_ui_o *ui, float feather_width); ~~~ Sets width of feathering in pixels. Defaults to 1.f. #### `feather_width()` ~~~c float (*feather_width)(const tm_ui_o *ui); ~~~ Returns the feather width set by `set_feather_width()`. #### `set_scroll_wheel_lines()` ~~~c void (*set_scroll_wheel_lines)(tm_ui_o *ui, float scroll_speed); ~~~ Set wheel scroll speed multiplier (in `lines`). Defaults to 1.f. #### `feed_events()` ~~~c void (*feed_events)(tm_ui_o *ui, const struct tm_input_event_t *events, uint32_t count, tm_vec2_t offset, tm_vec2_t scale); ~~~ Feeds events from the input system into the UI input state. This is used to make the UI interact with mouse movement, button and key presses, etc. `offset` and `scale` are used to convert from event coordinates to UI coordinates, using the equation: ui.pos = e.pos * scale + offset This should typically be called immediately after `clear()` at the beginning of a new frame. #### `feed_external_edit_key()` ~~~c void (*feed_external_edit_key)(tm_ui_o *ui, uint32_t key); ~~~ Feed an edit key such as TM_EDIT_KEY_CUT outside the regular event stream. This can be used to feed edit key corresponding to menu events (when the user selects Cut) in the menu. #### `merge_overlay()` ~~~c void (*merge_overlay)(tm_ui_o *ui); ~~~ Merges things that have been drawn into the overlay buffer into the main draw buffer. Popup windows, etc, are drawn to a separate buffer, since they are drawn *before* other controls, but should appear *on top* of those controls. Calling `merge_overlay()` will merge these items into the main draw buffer. Typically you do this just before drawing the data. #### `begin_overlay_draw_scope()` ~~~c void (*begin_overlay_draw_scope)(tm_ui_o *ui, uint64_t id); ~~~ When drawing in the overlay, wrap the UI code in these scopes. This allows the UI controls to make decisions based on whether they are drawn in the overlay or not. #### `end_overlay_draw_scope()` ~~~c void (*end_overlay_draw_scope)(tm_ui_o *ui, uint64_t id); ~~~ When drawing in the overlay, wrap the UI code in these scopes. This allows the UI controls to make decisions based on whether they are drawn in the overlay or not. #### `drawing_in_overlay()` ~~~c bool (*drawing_in_overlay)(tm_ui_o *ui); ~~~ True we are currently inside an overlay draw scope (see `begin_overlay_draw_scope`). #### `cursor()` ~~~c enum tm_ui_cursor (*cursor)(tm_ui_o *ui); ~~~ Returns the cursor that the UI wants to display. This is typically determined by the hovered element.

Standard controls

#### `pane()` ~~~c void (*pane)(tm_ui_o *ui, const tm_ui_style_t *style, tm_rect_t rect); ~~~ Draws a "background pane" in the default background color, upon which controls can be drawn. #### `scrollbar_x()` ~~~c bool (*scrollbar_x)(tm_ui_o *ui, const tm_ui_style_t *uistyle, const tm_ui_scrollbar_t *c, float *scroll); ~~~ Draws a horizontal scrollbar. Returns `true` if the scroll position changed. #### `scrollbar_y()` ~~~c bool (*scrollbar_y)(tm_ui_o *ui, const tm_ui_style_t *uistyle, const tm_ui_scrollbar_t *c, float *scroll); ~~~ Draws a vertical scrollbar. Returns `true` if the scroll position changed. #### `begin_scrollview()` ~~~c bool (*begin_scrollview)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_scrollview_t *c, float *scroll_x, float *scroll_y, tm_rect_t *content_rect); ~~~ Draws a scrollview. This is a scrollable view into a larger canvas with scrollbars that the user can interact with. `scroll_x` and `scroll_y` specify the horizontal and vertical scrolling respectively. The unit is an offset in canvas coordinates. I.e. a `scroll_x` of 10 means that the canvas has been scrolled 10 pixels to the right. A canvas item at canvas coordinates `(x, y)` should be drawn at absolute coordinates `(content_rect->x, content_rect->y) + (x, y) - (scroll_x, scroll_y)`. `content_rect` returns the rectangle where the canvas should be drawn. Note that `content_rect` might be smaller than `c->rect` to prevent the canvas content from overdrawing the scrollview's scrollbars. Note that it is the callers responsibility for offsetting the contents of the scrollview when drawing it, and also for clipping it to the `content_rect`. Also note that the scrollview does not draw any border or background for the view. That is again the responsibility of the caller. Returns `true` if the scroll position changed and `false` otherwise. The calls to begin_scrollview() and end_scrollview() should wrap the calls for drawing the scrollview content. #### `end_scrollview()` ~~~c bool (*end_scrollview)(tm_ui_o *ui, float *scroll_x, float *scroll_y, bool can_respond_to_keyboard); ~~~ #### `label()` ~~~c tm_rect_t (*label)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_label_t *c); ~~~ Draws a label. Returns a rect encompassing the drawn text. Note, the rect includes the full ascent and descent of the font, not of the individual characters drawn. I.e. if you draw a period `.` the height will still include the full ascent of an `A` and descent of a `g`. #### `text()` ~~~c tm_rect_t (*text)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_text_t *c); ~~~ Draws generic text (not just a label). Returns a rect encompassing the drawn text. #### `text_metrics()` ~~~c tm_rect_t (*text_metrics)(const tm_ui_style_t *style, const char *text); ~~~ Computes the rect surrounding the text when drawn at (0,0). Note that in contrast to `label()` this function returns the rect of the actual glyphs drawn, so when called with `.` it will return a rect surrounding just that period. #### `wrapped_text()` ~~~c tm_rect_t (*wrapped_text)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_text_t *c); ~~~ Draws line-wrapped text. Note that the height of `c->rect` is ignored, the text will flow to use as much height as need to fill all the lines and return the actual height used. #### `link()` ~~~c bool (*link)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_link_t *c); ~~~ Draws a clickable link. Returns *true* if the link was clicked. #### `tooltip()` ~~~c void (*tooltip)(tm_ui_o *ui, const tm_ui_style_t *style, const char *text); ~~~ Draws a tooltip with text `text`. Will be drawn under the mouse cursor. Check `tooltip` in `tm_ui_activation_t` against the ID of the control for which the tooltip should be drawn before calling this function. #### `button()` ~~~c bool (*button)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_button_t *c); ~~~ Draws a button. Returns true if the button was clicked. #### `pushbutton()` ~~~c bool (*pushbutton)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_button_t *c, bool *pressed); ~~~ Draws a button that toggles between on and off states. Returns true if the button was clicked. #### `checkbox()` ~~~c bool (*checkbox)(tm_ui_o *ui, const tm_ui_style_t *style, const struct tm_ui_checkbox_t *c, bool *checked); ~~~ Draws a checkbox. Returns true if `checked` status changed. #### `radio()` ~~~c bool (*radio)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_radio_t *c, bool checked); ~~~ Draws a radio button. Returns true if the radio button was checked. #### `progress()` ~~~c void (*progress)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_progress_t *c, float fraction); ~~~ Draws a progress bar. #### `slider()` ~~~c enum tm_ui_interaction_result_t (*slider)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_slider_t *c, float *val, float *initial); ~~~ Draws a slider. Returns the result of the interaction. `initial` is an optional output parameter that returns the value before the start of the current interaction. #### `spinner()` ~~~c enum tm_ui_interaction_result_t (*spinner)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_spinner_t *c, double *val, double *initial); ~~~ Draws a spinner. Returns the result of the interaction. `initial` is an optional output parameter that returns the value before the start of the current interaction. #### `dropdown()` ~~~c bool (*dropdown)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_dropdown_t *c, uint32_t *selected); ~~~ Draws a dropdown item picker. Returns true if a new item was selected. #### `textedit()` ~~~c bool (*textedit)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_textedit_t *c, char *buffer, uint32_t buffer_bytes); ~~~ Draws a text edit box for editing a single line of text. `buffer` is used to hold the UTF-8 encoded edited text. `buffer_bytes` is the size (in bytes) of this buffer. The buffer size determines how many characters the text edit box can hold. When the buffer is full, no more text can be entered into the text edit box. #### `menubar()` ~~~c tm_ui_menu_result_t (*menubar)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_menubar_t *c); ~~~ Draws a menu bar. Returns the result of menu selection. The menu bar is always drawn in in the overlay layer. The menu bar can only have submenu-type items. #### `menu()` ~~~c tm_ui_menu_result_t (*menu)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_menu_t *c); ~~~ Draws a menu. Returns the result of menu selection. The menu is always drawn in in the overlay layer. #### `sort_menu_items()` ~~~c void (*sort_menu_items)(tm_ui_menu_item_t *items, uint32_t count); ~~~ Sort the menu items alphabetically by the .text field. #### `tabbar()` ~~~c tm_ui_tabbar_result_t (*tabbar)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_tabbar_t *c, uint32_t *selected); ~~~ Draws a row of tabs with one tab selected. Clicking on a tab selects it. #### `draggedtab()` ~~~c void (*draggedtab)(tm_ui_o *ui, const tm_ui_style_t *style, const tm_ui_draggedtab_t *c); ~~~ Draws a single dragged tab from the tab bar. #### `splitter_x()` ~~~c bool (*splitter_x)(tm_ui_o *ui, const tm_ui_style_t *uistyle, const tm_ui_splitter_t *c, float *bias, tm_rect_t *content_left, tm_rect_t *content_right); ~~~ Draws a horizontal splitter. If `bias` is zero, the splitter is drawn in the center of the rectangle. A negative value offsets it to the left and a positive value to the right by the specified fraction. I.e. -1 will completely hide the left pane and +1 will completely hide the right pane. `content_left` and `content_right` returns the rects for drawing the left side and the right side of the content. #### `splitter_x_rects()` ~~~c void (*splitter_x_rects)(const tm_ui_splitter_t *c, float bias, tm_rect_t *content_left, tm_rect_t *content_right); ~~~ As `splitter_x()`, but just computes the rects without drawing anything. #### `splitter_y()` ~~~c bool (*splitter_y)(tm_ui_o *ui, const tm_ui_style_t *uistyle, const tm_ui_splitter_t *c, float *bias, tm_rect_t *content_top, tm_rect_t *content_bottom); ~~~ Draws a vertical splitter. If `bias` is zero, the splitter is drawn in the center of the rectangle. A negative value offsets it to the top and a positive value to the bottom by the specified fraction. I.e. -1 will completely hide the top pane and +1 will completely hide the bottom pane. `content_top` and `content_bottom` returns the rects for drawing the top side and the bottom side of the content. #### `splitter_y_rects()` ~~~c void (*splitter_y_rects)(const tm_ui_splitter_t *c, float bias, tm_rect_t *content_top, tm_rect_t *content_bottom); ~~~ As `splitter_y()`, but just computes the rects without drawing anything. #### `titlebar()` ~~~c tm_ui_titlebar_result_t (*titlebar)(tm_ui_o *ui, const tm_ui_style_t *uistyle, const tm_ui_titlebar_t *c); ~~~ Draws a window titlebar and border.

Interface for custom controls

Use these functions if you want to implement your own custom controls. See `ui_custom.h` for definitions of the structs used here. #### `buffers()` ~~~c tm_ui_buffers_t (*buffers)(tm_ui_o *ui); ~~~ Returns the internal UI buffers for implementing custom controls. In addition, this function will also reserve a fixed amount of memory in the UI's drawing buffers. As long as you are not looping and drawing, this reserved memory will typically be enough for all your drawing needs. If you draw in a loop, you may want to call `reserve_draw_memory()` in each iteration of the loop. #### `reserve_draw_memory()` ~~~c void (*reserve_draw_memory)(tm_ui_o *ui); ~~~ Reserves a fixed amount of memory in the UI's draw buffers. Call this in each iteration of a loop that uses the `tm_draw2d_api` to grow the buffer. #### `reserve_draw_memory_detailed()` ~~~c void (*reserve_draw_memory_detailed)(tm_ui_o *ui, uint32_t primitive_bytes, uint32_t main_index_bytes, uint32_t overlay_index_bytes); ~~~ Reserves the specified amount of memory in the draw buffers. Call this if you are drawing something big and you know in advance how much memory it will need. #### `make_id()` ~~~c uint64_t (*make_id)(tm_ui_o *ui); ~~~ Creates and returns a unique ID for a control. IDs are assigned as sequential numbers. #### `last_id()` ~~~c uint64_t (*last_id)(tm_ui_o *ui); ~~~ Returns the ID of the last control created. #### `create_fixed_id_range()` ~~~c uint64_t (*create_fixed_id_range)(tm_ui_o *ui, uint64_t size); ~~~ These ranges are fixed, i.e. not cleared every frame, they are counter form UINT64_MAX and downward. #### `set_id()` ~~~c uint64_t (*set_id)(tm_ui_o *ui, uint64_t id); ~~~ Resets the ID generation to start at `id` (and returns `id`). This can be used to assign known sequences of IDs to ranges of controls, to keep id numbers stable. #### `set_cursor()` ~~~c void (*set_cursor)(tm_ui_o *ui, enum tm_ui_cursor cursor); ~~~ Sets the UI cursor. #### `is_hovering()` ~~~c bool (*is_hovering)(tm_ui_o *ui, tm_rect_t r, uint32_t clip); ~~~ Returns true if the mouse is hovering over the specified rect in the main layer. #### `set_responder_chain_root()` ~~~c void (*set_responder_chain_root)(tm_ui_o *ui, uint64_t id); ~~~ Sets the item as the root as the responder chain (clears any existing responder chain). #### `begin_responder_scope()` ~~~c void (*begin_responder_scope)(tm_ui_o *ui, uint64_t id); ~~~ Starts a scope for an object that can be a keyboard responder. The open scopes form a responder chain for keyboard events. Each `begin_responder_scope()` scope must be matched by a corresponding `end_responder_scope()`. #### `end_responder_scope()` ~~~c void (*end_responder_scope)(tm_ui_o *ui, uint64_t id); ~~~ Ends a scope started by `begin_responder_scope()`. #### `in_responder_chain()` ~~~c bool (*in_responder_chain)(tm_ui_o *ui, uint64_t id); ~~~ Returns true if the item with the specified ID is in the current responder chain. #### `is_first_responder()` ~~~c bool (*is_first_responder)(tm_ui_o *ui, uint64_t id); ~~~ Returns true if the control with the specified ID is the first responder #### `set_responder_chain()` ~~~c void (*set_responder_chain)(tm_ui_o *ui, uint64_t id); ~~~ Sets the responder chain to the current set of responder scopes with the item `id` as first responder. If id is 0 or already in the scopes, the responder chain will just be the current set of scopes. #### `responder_chain()` ~~~c uint64_t *(*responder_chain)(tm_ui_o *ui, uint32_t *count); ~~~ Returns the responder chain #### `is_responder_chain_empty()` ~~~c bool (*is_responder_chain_empty)(tm_ui_o *ui); ~~~ Returns true if the responder chain is empty -- i.e. if no window is currently receiving focus. #### `focus_on_mouse_press()` ~~~c bool (*focus_on_mouse_press)(tm_ui_o *ui, tm_rect_t r, uint64_t id); ~~~ Helper function for giving controls focus based on mouse presses. If the mouse was pressed in the rect `r` and `id` is not already in the responder chain, it will become first responder. Returns true if the item became first responder. #### `consume_key()` ~~~c void (*consume_key)(tm_ui_o *ui, uint32_t keyboard_item); ~~~ Consumes a key event, will set the pressed, down and released state to false for the key `keyboard_item` (see `enum tm_input_keyboard_item`). If the key is currently held down, then the next released event will be suppressed. #### `begin_tab_scope()` ~~~c bool (*begin_tab_scope)(tm_ui_o *ui, uint64_t id); ~~~ Used to bracket a scope in which tabs will move between the controls. Pressing `Tab` at the end of the scope will move focus back to the first control in the scope that can take tab focus. Pressing `Ctrl-Tab` moves the focus between tab scopes, i.e. the `id` passed to `begin_tab_scope()`. Returns *true* if the scope received focus and *false* otherwise. #### `end_tab_scope()` ~~~c void (*end_tab_scope)(tm_ui_o *ui); ~~~ #### `focus_on_tab()` ~~~c bool (*focus_on_tab)(tm_ui_o *ui, uint64_t id); ~~~ Should be called by each item that can receive tab focus. Returns *true* if the item received focus and *false* otherwise. #### `suppress_next_tab_focus()` ~~~c void (*suppress_next_tab_focus)(tm_ui_o *ui); ~~~ This will suppress all tab key focus event for a single frame for the UI `ui`. Useful when you want to override the tab key behavior in special circumstances, even though there are tab key focusable controls within the UI-tab. #### `clear_active()` ~~~c void (*clear_active)(tm_ui_o *ui); ~~~ Clears the active UI object. #### `set_active()` ~~~c void *(*set_active)(tm_ui_o *ui, uint64_t id, tm_strhash_t active_data_format); ~~~ Sets the active item of the `ui` to `id` and sets the format of the active data buffer to `active_data_format`. `active_data_format` should be a hash value that uniquely identifies the format of the active data used by the control. For the standard controls, this will be one of the `TM_UI_ACTIVE_DATA__*` values, such as `TM_UI_ACTIVE_DATA__TEXTEDIT` or `TM_UI_ACTIVE_DATA__MENU`. If you are creating your own control with its own active data format, you should use a unique string for that control. If the current active item is not `id` or the current format is not `active_data_format`, the active data buffer will be cleared (zeroed). Returns a pointer to the active data buffer. !!! TODO: API-REVIEW Should `set_active()` also automatically set the responder chain? #### `is_active()` ~~~c void *(*is_active)(tm_ui_o *ui, uint64_t id, tm_strhash_t active_data_format); ~~~ If the current active item is `id` and the current active data buffer format matches `active_data_format`, returns a pointer to the active data buffer, otherwise returns NULL. #### `lost_active()` ~~~c void *(*lost_active)(tm_ui_o *ui, uint64_t id, tm_strhash_t active_data_format); ~~~ If the item `id` lost it's active status in the last frame (i.e. it used to be the active item, but no longer is), this function will return its last `active_data`. This can be used to save the result of an operation when the UI item is no longer interacted with which is useful for things like sliders. (You don't want to create undo steps for every single move of the slider, only when the user stops interacting with the slider.) #### `clear_lost_active()` ~~~c void (*clear_lost_active)(tm_ui_o *ui); ~~~ Clears the `lost_active()` record. This can be done once you've processed `lost_active()` to avoid processing it again. #### `to_draw_style()` ~~~c struct tm_draw2d_style_t *(*to_draw_style)(tm_ui_o *ui, struct tm_draw2d_style_t *style, const tm_ui_style_t *uistyle); ~~~ Initializes the `tm_draw2d_style_t` from the UI style. The line width of the `style` is set to 1.0f and the color is set to white. Returns a pointer to the passed in `style`. You can allocate and set a draw style in one line with: ~~~c tm_draw2d_style_t *style = tm_ui_api->to_draw_style(ui, (tm_draw2d_style_t[1]){ 0 }, uistyle); ~~~ #### `set_cache()` ~~~c void (*set_cache)(tm_ui_o *ui, uint64_t key, char *carray); ~~~ Sometimes UI elements need to use data that is expensive to generate. Rather than generate it every frame, we want to do it once and then reuse it. The `set_cache()` and `lookup_cache()` functions in the UI can be used for this. `set_cache()` stores a carray in the UI under they key `key`. This carray can contain arbitrary data. It is up to the caller to determine what to put in there. `key` should be a unique ID identifying this item. Typically it is created as a hash of all relevant input data. The data stored with `set_cache()` can be later retrieved by calling `lookup_cache()` with a matching hash key. If no data is stored under the hash key, 0 will be returned. Cache data that hasn't been either set or looked up during the frame will be freed automatically when `clear()` is called. Note that the cache data must be a carray, allocated with the UI allocator `tm_ui_buffers_t::allocator`. Otherwise, the UI cannot free it properly. #### `lookup_cache()` ~~~c char *(*lookup_cache)(tm_ui_o *ui, uint64_t key); ~~~ Looks up the cache value for `key`. Returns NULL if no cache value has been set for `key`. #### `get_cache()` ~~~c void *(*get_cache)(tm_ui_o *ui, uint64_t key, uint32_t size); ~~~ If a cache key exists for `key` and has `size` bytes, returns it. Otherwise, a new cache value for the key of the specified will be created, initialized to zero and returned. #### `left_mouse_pressed()` ~~~c bool (*left_mouse_pressed)(tm_ui_o *ui, const char *help_text); ~~~ Tests if the specified mouse button is pressed and also sets the help text for the button. The text can be retrieved with `get_mouse_help_texts()`. The `released` variants only trigger once the button is released, but otherwise function identically. Each of these functions should only be called at *one* place in the UI -- at the point that would handle the mouse press if there was one. Otherwise, the wrong help text will be shown. Note that this means that if you are doing multiple tests to determine if the mouse is pressed, this function should be the last test. Wrong, because the help text will be shown even if ALT is not down: ~~~c if (tm_ui_api->left_mouse_pressed(ui, help) && alt_down) ~~~ Correct: ~~~c if (alt_down && tm_ui_api->Left_mouse_pressed(ui, help)) ~~~ If you pass dynamic strings to these functions, they should use the frame allocator. The UI will not copy them and the texts will be reset every frame. #### `middle_mouse_pressed()` ~~~c bool (*middle_mouse_pressed)(tm_ui_o *ui, const char *help_text); ~~~ #### `right_mouse_pressed()` ~~~c bool (*right_mouse_pressed)(tm_ui_o *ui, const char *help_text); ~~~ #### `left_mouse_released()` ~~~c bool (*left_mouse_released)(tm_ui_o *ui, const char *help_text); ~~~ #### `middle_mouse_released()` ~~~c bool (*middle_mouse_released)(tm_ui_o *ui, const char *help_text); ~~~ #### `right_mouse_released()` ~~~c bool (*right_mouse_released)(tm_ui_o *ui, const char *help_text); ~~~ #### `double_click()` ~~~c bool (*double_click)(tm_ui_o *ui, const char *help_text); ~~~ #### `triple_click()` ~~~c bool (*triple_click)(tm_ui_o *ui, const char *help_text); ~~~ #### `get_mouse_help_texts()` ~~~c tm_ui_mouse_help_texts_t (*get_mouse_help_texts)(tm_ui_o *ui); ~~~ Retrieve the mouse help texts set by the `left_mouse_pressed()`, etc functions. #### `theme()` ~~~c tm_ui_theme_t (*theme)(tm_ui_o *ui); ~~~ Returns the current theme of the UI. #### `set_theme()` ~~~c void (*set_theme)(tm_ui_o *ui, tm_ui_theme_t theme); ~~~ Sets the theme of the UI. #### `create_custom_theme()` ~~~c tm_ui_theme_t (*create_custom_theme)(tm_ui_o *ui, struct tm_the_truth_o *tt); ~~~ Creates a new `tm_ui_theme_t` based on the current theme settings and returns it. #### `set_parent_ui()` ~~~c void (*set_parent_ui)(tm_ui_o *ui, tm_ui_o *parent_ui); ~~~ Sets `parent_ui` as a parent to `ui`. The `parent_ui` may for example be an editor which the gameplay UI (`ui`) lives inside.

Multi-threading

#### `fork()` ~~~c tm_ui_o *(*fork)(tm_ui_o *main); ~~~ `fork()` is u sed to implement multi-threading of UIs. It creates a new copy of the UI `main` that can be used by a background job and returns it. `tm_ui_api` is not thread-safe. I.e., you cannot modify the same `ui` from two different threads. But since `fork()` creates a completely new copy of the `tm_ui_o` struct, it is safe to use it in a background job while the main thread keeps working on the `main` ui. If you want to use multiple background threads -- fork of a new UI for each UI thread. Once the background job has finished rendering the forked UI, the changes made in the fork can be brought back to the `main` UI by calling `join()`. !!! WARNING: Warning The `fork()` system is still under heavy development, and right now there are several UI features that don't work in the forked UIs. #### `join()` ~~~c void (*join)(tm_ui_o *main, tm_ui_o *fork); ~~~ Merges the changes made in the UI `fork` back into the `main` UI. Draw calls will be merged, as will activation, hover state, etc. After merging, `join()` destroys the `fork` UI. (You shouldn't call `destroy()` on the fork, `join()` will take care of any necessary destruction.) #### `merge_render_buffers()` ~~~c void (*merge_render_buffers)(tm_ui_o *main, tm_ui_o *fork); ~~~ Merges the Draw calls made in the UI `fork` back into the `main` UI. This doesn't merge anything else, nor destroys the `fork` UI. #### `main_ui()` ~~~c tm_ui_o *(*main_ui)(const tm_ui_o *ui); ~~~ If `ui` is a forked UI, returns the corresponding main UI, otherwise, returns `ui`.

Fonts

#### `add_font()` ~~~c const struct tm_draw2d_font_t *(*add_font)(tm_ui_o *ui, tm_strhash_t font_id, uint32_t size, const struct tm_font_t *font); ~~~ Adds a font to the UI's font registry. You must add a font in order to use it in the UI. `font_id` is a uinque ID identifying the font (typically a hash of the font name). Use `0` for the default font. `size` is the font size that was generated for `tm_font_t`. Fonts must be added to the UI at the start of every frame (fonts are added to the vbuffer which gets reset at the start of the frame). The default font should be the first font added. !!! TODO: API-REVIEW Should we "remember" this data in the vbuffer so that we don't have to call `add_font()` every frame? #### `font()` ~~~c tm_ui_font_t (*font)(tm_ui_o *ui, tm_strhash_t font_id, uint32_t size); ~~~ Looks up the specified `font_id` and `size` among the fonts that have been added to the UI with `add_font()` and returns the closest match. If one or more matching `font_id` are found, the one with the closest size is returned. If no matching `font_id` is found, the default font is returned. #### `default_style()` ~~~c tm_ui_style_t (*default_style)(const tm_ui_o *ui); ~~~ Returns the default style of the UI. The default style uses the default font and feather width, no clip rect and draws in to the `TM_UI_BUFFER_MAIN` buffer.