Package com.ultikits.ultitools.abstracts.gui.declarative


@Experimental package com.ultikits.ultitools.abstracts.gui.declarative
Declarative Inventory GUI framework.

Built on Flutter's design philosophy, this framework provides a declarative way to build UI. Core idea: UI = f(state)

Status (6.3.0)

This package and its subpackages are still marked @ApiStatus.Experimental; the API may change incompatibly in a future release.

Three rendering seams were fixed in 6.3.0 — UI = f(state) now holds: GuiRenderer re-derives the Widget tree from a Supplier<Widget> on every performBuild() call, not just once from onOpen; Element.update() marks itself dirty unconditionally; and State.setState() — including a call on a nested StatefulWidget — now reliably reaches a scheduled repaint. The setState triggers a partial rebuild bullet below now holds, and the navigation subsystem that depends on it (Navigator.push / pop) is usable. Click dispatch was also tightened: GuiRenderer bounds-checks event.getRawSlot() before any handler lookup, so a numerically-colliding slot in the player's own inventory can no longer trigger a GUI handler. GridView now writes its computed slot onto any widget type's render node(s) at render time (previously only ItemDisplay positioned correctly).

Why the marker stays. As of this release, none of these three changes has real-server feedback from a downstream module — zero adoption is no more grounds for declaring the API stable than it would be for deleting it. The marker is retained for at least one more release pending that feedback.

The three seams are tracked by issue #200.

Main Features:

  • Widget tree describes the UI structure
  • Element tree manages Widget instances and their lifecycle
  • RenderNode tree performs efficient diff-based updates
  • Supports both StatelessWidget and StatefulWidget
  • setState triggers a partial rebuild
  • All updates run on the main thread automatically
  • Compatible with obliviate-invs' Gui lifecycle

Quick Start:


 // 1. Create your GUI page
 public class ShopPage extends DeclarativeGui {
     private final List<ItemStack> items;

     public ShopPage(Player player, List<ItemStack> items) {
         super(player, "shop", "Item Shop", 6);
         this.items = items;
     }

     @Override
     public Widget build(BuildContext context) {
         return Container.builder()
             .children(
                 // Title
                 TextButton.builder()
                     .text("§6§lItem Shop")
                     .slot(4)
                     .build(),

                 // Item grid
                 GridView.<ItemStack>builder()
                     .startSlot(10)
                     .columns(7)
                     .items(items, item -> ItemDisplay.builder(item)
                         .onClick(() -> buyItem(item))
                         .build())
                     .build(),

                 // Close button
                 TextButton.builder()
                     .text("§cClose")
                     .color("RED")
                     .slot(49)
                     .onClick(player::closeInventory)
                     .build()
             )
             .build();
     }

     private void buyItem(ItemStack item) {
         // Handle purchase logic
     }
 }

 // 2. Open the GUI
 new ShopPage(player, items).open();
 

StatefulWidget Example:


 public class CounterPage extends DeclarativeGui {
     private int count = 0;

     public CounterPage(Player player) {
         super(player, "counter", "Counter", 3);
     }

     @Override
     public Widget build(BuildContext context) {
         return Container.builder()
             .child(TextButton.builder()
                 .text("Count: " + count)
                 .slot(13)
                 .onClick(() -> {
                     // Mutate state and trigger a rebuild
                     count++;
                     markNeedsBuild();
                 })
                 .build())
             .build();
     }
 }
 

Package Structure:

Since:
6.2.0
Version:
1.0.0
Author:
qianmo
See Also: