Skip to content

Extending

ssbaxys edited this page Oct 26, 2026 · 1 revision

Your own widgets, properties, events, layouts and tags.

Everything is extended with plain code, without reflection or annotations.

Your own widget

public class StripeBar extends Widget<StripeBar> {
    public static final StyleKey<Integer> STRIPE = StyleKey.builder("stripe-color", Integer.class)
            .defaultValue(0xFFFFFFFF).animated(Interpolator.COLOR).register();

    private float value;

    public StripeBar() {
        super("stripe-bar");                     // theme class
        setFocusable(true);
    }

    public StripeBar value(float v) {
        value = v;
        return this;
    }

    @Override
    protected void measureContent(float maxWidth, float maxHeight) {
        setContentSize(120, 8);                  // natural size without padding
    }

    @Override
    protected void paintContent(Canvas canvas, float partialTick) {
        canvas.fillRoundRect(0, 0, width() * value, height(), Radii.all(4),
                Brush.solid(style.get(STRIPE)));
    }

    @Override
    protected void handleEvent(UiEvent event) {
        if (event.type() == PointerEvent.CLICK) {
            value(((PointerEvent) event).localX() / width());
            event.consume();
        }
    }
}

Useful UiElement hooks: onAttach / onDetach (signal subscriptions and animations), onLayout (after a size change), onStateChanged, paintBackground, paintForeground, paintOverlay. Custom states use bits starting at State.FIRST_CUSTOM.

Everything else

What How
Style property StyleKey.builder(name, type).defaultValue(...).inherited().affectsLayout().animated(...).register()
Theme token ThemeVar.of("brand", Integer.class, 0xFF00FF00)
Event EventType.create("name", bubbles)
Layout implements Layout
Markup tag Markup.tag("card", (node, ctx) -> ...)
CSS property CssProperties.register(...)
Effect FxRegistry.register("mymod:effect", ...)
Translation source I18n.addSource((lang, key) -> ...)

Platform hooks

Platform method Default Purpose
dataDirectory() config/luminaui folder for theme files
readFile/writeFile/listFiles via java.nio files inside dataDirectory()
dayTime() -1 (no world) world time in ticks 0–24000
biomeId() null biome id under the player
narrate(text) nothing narration for the screen reader
isShiftDown() false Shift+click on a slot (quick move)
playSound(id, volume, pitch) nothing UI sounds
pollGameData(GameState out) false (no world) player snapshot for GameData, every client tick
hudState() 0 F1 / F3 / chat / screen flags for HUD visibility rules, every frame
createTexture(key, w, h, argb) null a texture from pixels (GIF frames, minimap)
sampleMap(radius) null map colors around the player for MiniMap
worldBlocks() null client world blocks one by one for StructurePreview and WorldCapture
captureWorld(x0, y0, z0, x1, y1, z1) via worldBlocks() a world box at once as one structure
pollGamepad() null gamepad state for navigation

An example of all of it together is the ThemesPage page in the test mod.


← Accessibility and Sounds · English home · Debugging and Tips →

Clone this wiki locally