controls - ryzom/ryzomcore GitHub Wiki
title: Interactive Widgets (Controls) description: Buttons, sliders and scrollbars, edit boxes, combo boxes, spinners and the color picker published: true editor: markdown
Controls take input. They inherit the common element attributes plus a shared tooltip set, and each family adds its own. Event wiring is by action handler name + params attribute pairs; note the params attribute name varies by widget (params_l on buttons, plain params on sliders and edit boxes).
Every <ctrl> accepts: tooltip (literal text, or a translation key when it starts with ui), tooltip_i18n (forced translation key, wins over tooltip), on_tooltip/on_tooltip_params (action handler producing a dynamic tooltip), tooltip_parent (ctrl default, mouse, win, special + tooltip_special_parent), tooltip_posref/tooltip_posref_alt (hotspot pairs or auto), and instant_help (default true, meaning no hover delay).

Two widget types share the button machinery:
-
button: a bitmap button.tx_normal,tx_pushed,tx_overtextures (over is blended on top),scale,align. -
text_button: a three-piece skinned button with a label. Each oftx_normal/tx_pushed/tx_overis a base name expanded to<base>_l.tga,<base>_m.tga,<base>_r.tga(caps + stretched middle). Label viahardtext; sizing viawmargin,wmin,hmin; label placementtext_posref(default centered),text_x/text_y; per-state text colorstext_color_normal/pushed/over(+ shadow and global-color variants). All CViewText attributes also apply to the label (fontsize,shadow,case_mode, …).
Shared button attributes:
| attribute | default | meaning |
|---|---|---|
button_type |
toggle_button |
push_button (momentary), toggle_button (sticky), radio_button (exclusive per parent group) |
pushed |
false |
initial state |
onclick_l / params_l
|
— | left-click action handler; also onclick_r, ondblclick_l, onlongclick_l, onover, onclock_tick with matching params_*
|
menu_l / menu_r / menu_b
|
— | menu group opened on left/right/both clicks |
color, col_pushed, col_over
|
white | per-state modulation colors; global_color_normal/pushed/over per-state overrides |
over_when_pushed |
true |
show the over layer while pushed |
frozen |
false |
ignore events but keep drawing (grayed unless frozen_half_tone="false"); distinct from active="false" which hides |
Radio grouping is by parent group: all radio buttons directly inside the same group form one exclusive set; there is no group-name attribute. A pushed="true" on a radio button at parse time sets the visual only; select the initial state at runtime (action handler, database or Lua) if the group must start coherent.
One widget type, two roles.
<!-- slider: value + range, no target -->
<ctrl type="scroll" id="sh" vertical="false" align="L" value="UI:TEMP:SLIDERH" min="0" max="255" w="200" h="8" tracksize="24"
tx_bottomleft="w_scroll_l.tga" tx_middle="w_scroll_m.tga" tx_topright="w_scroll_r.tga" />
<!-- scrollbar: target group, engine computes the rest -->
<ctrl type="scroll" id="scroll_bar" target="text_list" ... />| attribute | default | meaning |
|---|---|---|
vertical |
true |
orientation |
tx_bottomleft / tx_middle / tx_topright
|
w_scroll_l0_* |
track cap/middle/cap textures |
value |
0 |
literal, or a database leaf (in which case the slider both writes and follows it) |
min / max
|
0 / 100 | slider range |
step_value |
0 |
snap values to multiples |
onscroll / params
|
— | handler while moving; onscrollend/end_params on release; onscrollcancel/cancel_params with cancelable="true" (right-click aborts a drag) |
target |
— | id of a group to scroll (switches the ctrl to scrollbar mode); target_stepx/target_stepy set the scroll quantum (e.g. line height) |
keyboard |
false |
PageUp/PageDown support when focused |
tracksize |
8 |
thumb length (minimum, in scrollbar mode) |
The showcase's sliders drive gauges purely through the database: slider writes UI:TEMP:SLIDERH, the bar/text_number views read it, and a <link> pops a warning icon above a threshold, with no code anywhere. Mouse wheel over a vertical scrollbar scrolls its target 12 px per notch.

edit_box is a group: it needs a child text view with id edit_text (auto-created with a warning if missing) which carries the visual attributes; multi-line editing = multi_line="true" on that child plus want_return="true" on the box.
| attribute | default | meaning |
|---|---|---|
onenter / params
|
— | Enter handler |
onchange / onchange_params
|
— | text-change handler |
on_focus / on_focus_lost (+_params) |
— | focus handlers |
entry_type |
text |
input filter: text, integer, positive_integer, float, positive_float, alpha, alpha_num, alpha_num_space, password, filename, playername
|
max_num_chars / max_num_bytes
|
unlimited | length caps |
prompt |
> |
prompt string |
enter_loose_focus |
true |
Enter drops keyboard focus |
enter_recover_focus |
true |
Enter anywhere refocuses the last edit box |
max_historic |
0 |
up-arrow history depth (entries pushed on Enter) |
clear_on_escape |
false |
Escape wipes the content |
want_return |
false |
Enter inserts a newline instead of validating |
negative_filter |
— | characters banned from input |
menu_r |
— | right-click context menu id |
savable |
true |
content persisted with the interface config |
enter_loose_focusdefaults to true. A console/chat-style box that should accept the next line immediately must setenter_loose_focus="false"; otherwise every second command silently goes nowhere while the box regains focus. {.is-warning}
The current content is the reflected property input_string, readable and writable from Lua and <link> targets; it is not an XML attribute. edit_box_decor is the same widget with eight built-in border textures (tx_tl … tx_r).

combo_box stores its selected index in a database leaf (value, required) and lists its entries as children:
<group type="combo_box" id="race" value="UI:TEMP:COMBO" w="120" h="18" ...>
<combo_text name="Fyros" />
<combo_text name="Matis" />
...
</group>It needs a child text view text and a child button select (usually supplied by an instance template), and the application must point the static combo menu ids at a menu group in your XML (see embedding). on_change/on_change_params fires on selection; entries can be added at runtime.
select_number is the spinner sibling: value (leaf, required), min/max/delta, loop; needs children slot_number, number, arrow_up, arrow_down. Mouse wheel steps it too.

colpick samples a palette texture under the mouse (click or drag) and writes the picked channels to up to four database leaves:
<ctrl type="colpick" id="cp" texture="color_picker.tga"
dbcolr="UI:TEMP:COLOR:R" dbcolg="UI:TEMP:COLOR:G" dbcolb="UI:TEMP:COLOR:B"
onchange="set" onchange_params="..." />onchange fires continuously during a drag. Because it reads texture pixels, the palette must be a loose file, not an atlas entry (see Skinning).
-
tab_button: a text_button whose click is hijacked to tab selection;group=names the content group it shows. Covered with tab groups in Windows and containers. -
group_wheel: an invisible group withon_wheel_up/on_wheel_down(+_params) handlers. -
button_link: the hyperlink button used inside HTML/paragraph flows. - Drag and drop has no library widget: the draggable control in the library is a stub (the client implements its own item sheets on top). Gesture-driven UI is done in Lua with the embedder's mouse hooks; see the inventory demo pattern.