-
Notifications
You must be signed in to change notification settings - Fork 25
GUI API Home
Note: this page will be split up later, I just don't have time tonight
- Components
- Handlers
- Mixins
- Templates
Components GuiComponent are individual objects on a GUI. You can add them to a GUI by extending GuiBase and adding them to the base components component.
Components can have any number of case insensitive strings as tags. You can use .addTag(tag) to add a tag if it doesn't exist yet, .removeTag(tag) to remove one if it exists, .hasTag(tag) to check if the component has a given tag, and .getTags() to get an unmodifiable set with all the component's tags.
Any component can have subcomponents. Subcomponents are other components nested within itself. You can add or remove subcomponents using the .add(component), .remove(component), and .remove(tag) methods. You can also process all children (does not search recursivly) that have a given tag by using .getByTag(tag, consumerLambda).
Components can be positioned by using .setPos(pos) method. The position is relative to the parent component and can be negative. You can retrieve the position by using .getPos().
Components can have their size changed using the .setSize(size) method. The use of the size is up to the component itself, though unless you set shouldCalculateOwnHover to false (get/setShouldCalculateOwnHover()) it will use the size variable to calculate whether the mouse is over the component.
Components also have a logical size. The logical size is a bounding box instead of just a width/height. The logical size is the size of the actual content (including children) instead of the size variable which really is just a suggestion. The logical size can't be set explicitly, though you could easily make a handler to override it.
Override getContentSize() not getLogicalSize() in your components, the latter calls getContentSize() and does further calculations on the child components
Note: The logical size will be used for automatic layout once that becomes a thing
Focused and Enabled are two fields that do nothing to base components, but will be used to standardize some common interfaces. Focused components are components that the user is activly interacting with, such as a text field or a dropdown selector. Input-like components that aren't enabled should disable interaction. Such as a button being greyed out and unresponsive, or a text field becoming non-editable.
Visible is a field that toggles the visibility (gasp!) of a component. If it is false, then the component won't be drawn or recive input of any kind. It also won't be considered in logical size calculations or hover calculations.
Invalidating a component means that before it's drawn the next frame it will be removed from the parent. This is mostly a method for components to self-destruct.
Handlers are the event system of components, and in my opinion, one of the API's most powerful and difficult to fully utilize feature. Handlers allow you to run code when an event happens, much akin to Forge's event bus.
The HandlerList is one event for one component. They are typically initialized like so:
public final HandlerList<HandlerInterface> handlerName = new HandlerList<>()
To call the handler you can use one of three methods:
-
.fireAll(caller)which fires all of the handlers and doesn't require a return value from the caller - caller:(handler) -> void -
.fire(caller)which fires all the handlers until the caller returns true (this is often just the return value from an interface with a boolean return value) and returns true if it was canceled in this way - caller:(handler) -> boolean -
.fire(value, caller)which fires all the handlers and allows each to modify the value. The caller must return the modified value, this is often just a method in the handler interface that is returned by a lambda. - caller:(handler, T value) -> T
Here are some example caller implementations:
public final HandlerList<IClickEventHandler> click = new HandlerList<>();
// h is an IClickEventHandler
click.fireAll( (h) -> h.handle(/* params */) );// IPreDrawEventHandler.handle(T component) returns true if the
// component shouldn't be drawn
public final HandlerList<IPreDrawEventHandler<T>> click = new HandlerList<>();
// h is an IPreDrawEventHandler<T>
// h.handle returns a boolean, the first time the lambda returns true
// (lambdas automatically return if they need to and are only one statement)
// the handling will stop and click.fire() will return true
// if none of the handlers return true, it will return false and
// the draw method won't return prematurely
if( click.fire( (h) -> h.handle(/* params */) ) )
return;
// IModifyBobEvent.handle(String bob) returns a modified version of bob
public final HandlerList<IModifyBobEvent<String>> bob = new HandlerList<>();
String bobsName = "bob";
// h is an IModifyBobEvent<String>
bobsName = bob.fire( bobsName, (h, v) -> h.handle(/* params */));
They are just a name for methods that add a set group of handlers to a component. e.g. buttons are a mixin, not a type of component. Any component can be a button.
They are a name for methods that generate a component and it's children. Maybe there would be one for making basic text buttons.
It would create a ComponentVoid, add a button mixin, then add the text and sprite components.