UI Builders
The builder classes are used together to manipulate UI and handle user interactions. See Markup for .ui file syntax.
UICommandBuilder
Section titled “UICommandBuilder”Builds commands that manipulate UI elements using CSS-like selectors.
Selectors
Section titled “Selectors”#ElementId - by ID#Parent #Child - nested (space-separated)#List[0] - indexed element#List[0] #Name - child of indexed element#Element.Property - property accessLoading UI Files
Section titled “Loading UI Files”// load a .ui file as rootcmd.append("Pages/MyPage.ui");
// load into a containercmd.append("#Container", "Pages/ListItem.ui");
// inline markupcmd.appendInline("#Container", "Label { Text: Hello; }");
// insert before a siblingcmd.insertBefore("#Sibling", "Pages/Item.ui");
// insert inline before a siblingcmd.insertBeforeInline("#Sibling", "Label { Text: New; }");Setting Values
Section titled “Setting Values”// textcmd.set("#Label.Text", "Hello World");
// numberscmd.set("#Slider.Value", 50);
// booleanscmd.set("#Button.Disabled", true);cmd.set("#Panel.Visible", false);
// nullcmd.setNull("#Optional.Value");
// arrays/listscmd.set("#Items", new String[]{"a", "b", "c"});cmd.set("#Items", List.of("a", "b", "c"));Setting Objects
Section titled “Setting Objects”For complex types, use setObject():
// stylingcmd.setObject("#Element.Style", new PatchStyle(...));cmd.setObject("#Element.Anchor", new Anchor(...));
// value referencescmd.set("#Element.Style", Value.ref("Pages/Styles.ui", "ButtonStyle"));Removing Elements
Section titled “Removing Elements”// clear children of a containercmd.clear("#Container");
// remove an element entirelycmd.remove("#Element");UIEventBuilder
Section titled “UIEventBuilder”Binds UI events to server handlers.
Event Types
Section titled “Event Types”| Type | Trigger |
|---|---|
Activating | Click/activate (buttons, list items) |
RightClicking | Right-click |
DoubleClicking | Double-click |
MouseEntered | Cursor enters element |
MouseExited | Cursor leaves element |
ValueChanged | Input value changed |
ElementReordered | Element reordered in list |
Validating | Validation event |
Dismissing | Page dismiss attempt |
FocusGained | Element gained focus |
FocusLost | Element lost focus |
KeyDown | Key pressed while focused |
MouseButtonReleased | Mouse button released (useful for sliders) |
SlotClicking | Inventory slot clicked |
SlotDoubleClicking | Inventory slot double-clicked |
SlotMouseEntered | Cursor entered slot |
SlotMouseExited | Cursor left slot |
DragCancelled | Drag operation cancelled |
Dropped | Drag-drop completed |
SlotMouseDragCompleted | Slot drag completed |
SlotMouseDragExited | Cursor left slot during drag |
SlotClickReleaseWhileDragging | Click released on slot while dragging |
SlotClickPressWhileDragging | Click pressed on slot while dragging |
SelectedTabChanged | Tab selection changed |
Basic Binding
Section titled “Basic Binding”events.addEventBinding( CustomUIEventBindingType.Activating, "#Button", EventData.of("Action", "submit"));Static vs Dynamic Data
Section titled “Static vs Dynamic Data”Static data - value is set at binding time:
// "ItemId" will always be "sword_01" when this button is clickedevents.addEventBinding( CustomUIEventBindingType.Activating, "#BuyButton", EventData.of("ItemId", "sword_01"));Dynamic data - value is read from UI at event time (use @ prefix):
// reads current value of #SearchInput when event firesevents.addEventBinding( CustomUIEventBindingType.ValueChanged, "#SearchInput", EventData.of("@Query", "#SearchInput.Value"));Multiple Values
Section titled “Multiple Values”events.addEventBinding( CustomUIEventBindingType.Activating, "#SaveButton", new EventData() .append("Action", "save") // static .append("@Name", "#NameInput.Value") // dynamic .append("@Count", "#CountSlider.Value") // dynamic);Interface Locking
Section titled “Interface Locking”By default, events lock the interface until the server responds (prevents spam clicks).
// locks interface (default)events.addEventBinding(type, selector, data, true);
// does NOT lock - good for sliders, search inputsevents.addEventBinding(type, selector, data, false);Use locksInterface: false for:
- Search inputs (instant feedback)
- Sliders (smooth updates)
- Any high-frequency interaction
Binding Without Data
Section titled “Binding Without Data”// just notify server, no data neededevents.addEventBinding(CustomUIEventBindingType.Activating, "#CloseBtn");Example: Search with List
Section titled “Example: Search with List”@Overridepublic void build(Ref<EntityStore> ref, UICommandBuilder cmd, UIEventBuilder events, Store<EntityStore> store) { cmd.append("Pages/ItemBrowser.ui");
// search input - dynamic value, no lock for instant feedback events.addEventBinding( CustomUIEventBindingType.ValueChanged, "#SearchInput", EventData.of("@Query", "#SearchInput.Value"), false );
// render list items for (int i = 0; i < items.size(); i++) { Item item = items.get(i); cmd.append("#ItemList", "Pages/ItemRow.ui"); cmd.set("#ItemList[" + i + "] #Name.Text", item.getName()); cmd.set("#ItemList[" + i + "] #Icon.Texture", item.getIcon());
// click handler with static item ID events.addEventBinding( CustomUIEventBindingType.Activating, "#ItemList[" + i + "]", EventData.of("ItemId", item.getId()) ); }}
@Overridepublic void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, EventData data) { if (data.query != null) { // search query changed this.filterItems(data.query); this.rebuild(); } else if (data.itemId != null) { // item selected this.selectItem(data.itemId); }}