-
Notifications
You must be signed in to change notification settings - Fork 21
GUI API Home
- Components
- Handlers
- Options
- Mixins
- Templates
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 */));
Options are values used by a component that can be either a fixed value or a lambda to produce a value. Options have an input type and an output type.
public final Option<MyComponentClass, List<String>> myopt =
new Option<>(ImmutableList.of() /* default value */);
To set the value of an option you can either call .setValue(val)
to set it to a static value, or use .func(lambda)
to dynamically generate the value. In order to get the value you call .getValue(parameter)
with whatever parameter class you specified. Most of the time the parameter should be your component.
// comp has a <MyComponentClass, List<String>> option called "bob"
comp.bob.setValue("bob's name is bob");
comp.bob.getValue(comp); // -> "bob's name is bob"
comp.bob.func( (c) -> "obj " + c );
comp.bob.getValue(comp); // -> "obj MyComponentClass@12345"
Mixins are a name for anything that adds functionality through events. A mixin theoretically could be added to any component. Some mixins only make sense to be applied once, so the mixin should add a tag to the component and not apply itself if the component has that tag.
public class DragMixin {
public static final String TAG = "mixinDrag";
private boolean dragging = false;
public DragMixin(GuiComponent component) {
component.mouseDown.add( (c, pos, button) -> {
if(c.mouseOverThisFrame) {
dragging = true;
}
});
component.mouseUp.add( (c, pos, button) -> {
dragging = false;
} );
component.preDraw.add( (c, mousePos, partialTicks) -> {
c.setPos(mousePos);
} );
}
}
Templates are methods that generate a component in a DRY style. Instead of having complicated code in multiple places, you put it in one resuable place.
Examples of templates: Basic text buttons, Sliders (Book GUI), Modules (Worktable GUI), etc.