-
Notifications
You must be signed in to change notification settings - Fork 0
07 2 inventory default buttons
The KLibrary GUI framework uses a layered button system designed to decouple static interaction logic (like closing menus or turning pages) from dynamic content rendering.
Default buttons are pre-built, localized, and reusable Button implementations that dispatch predefined actions when clicked. Because buttons in KLibrary act as action dispatchers rather than data stores, using built-in buttons eliminates boilerplate logic across different menus.
KLibrary provides the following built-in buttons in io.github.kaivian.klibrary.inventory.button.impl:
-
CloseButton: Instantly closes the inventory for the player. -
BackButton: Safely pops the navigation stack, returning the player to their previous menu. -
BackOrCloseButton: Intelligently checks the manager's back stack. It acts as a Back button if history exists, or a Close button if the stack is empty. -
NavigationButton.Next/Previous: Automatically increments or decrements the current page and handles pagination updates.
KLibrary rendering occurs in a strict hierarchy:
-
View-Level Buttons: Highest priority. Added directly to the
InventoryViewinstance viaview.setButton(). -
Provider-Level Rendering: Lowest priority. Rendered globally by the
InventoryProviderinside theupdate()loop.
By injecting UI controls (like Back or Next buttons) directly into the InventoryView during the provider's update() cycle, you guarantee that these controls cannot be overwritten by dynamic content generators (such as listing items from a database).
To securely place a default UI control, use the setButton method on the InventoryView.
import io.github.kaivian.klibrary.inventory.button.impl.BackOrCloseButton;
import io.github.kaivian.klibrary.inventory.button.impl.NavigationButton;
@Override
public void update(@NotNull InventoryView view) {
// 1. Establish the highest-priority View layer
view.setButton(45, new NavigationButton.Previous());
view.setButton(49, new BackOrCloseButton());
view.setButton(53, new NavigationButton.Next());
// 2. Render dynamic content (Provider layer)
Inventory inv = view.getInventory();
List<ItemStack> myDynamicItems = fetchItems();
for (int i = 0; i < myDynamicItems.size(); i++) {
// Even if we accidentally iterate over slots 45, 49, or 53,
// the click handler will intercept and prioritize the View-level buttons set above!
inv.setItem(i, myDynamicItems.get(i));
}
}While you technically could inject view-level buttons once during createView(), setting them in the update() cycle is the safest architectural practice.
Since update() acts as a complete re-render pipeline, redefining your view-level buttons here ensures that their visibility states (e.g., hiding the Previous button on page 0) are strictly recalculated on every frame based on the active InventoryContext.
-
Never hardcode close logic: Always use
CloseButtoninstead of manually intercepting clicks and callingplayer.closeInventory(). -
Prefer
BackOrCloseButtonoverBackButton: For general UI design, a combinedBackOrCloseButtonprevents players from getting stuck if they directly opened a sub-menu without navigating from a main menu first. -
Isolate Action Dispatchers: Treat buttons exclusively as action dispatchers. The
Buttonlogic should never calculate what to display—that is the responsibility of the Provider reading from the Context.