Skip to content

GUI API Home

thecodewarrior edited this page Jul 16, 2016 · 2 revisions

Gui Framework

Note: this page will be split up later, I just don't have time tonight

Main Concepts

  • Components
  • Handlers
  • Mixins
  • Templates

Components

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.

Tags

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.

Subcomponents

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).

Positioning

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().

Size

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.

Logical size

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

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.

Visibility

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.

Invalidation

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

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.

HandlerList

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 */));

Mixins

Super-quickie explanation

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.

Templates

Super-quickie explanation

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.

Implemented components

ComponentVoid

Clone this wiki locally