Skip to content
Daniel Gerson edited this page Aug 19, 2013 · 33 revisions

TriplePlay uses PlayN’s API so make sure you’re familiar with the various rendering types before continuing. ( src: https://developers.google.com/playn/devguide/rendering )

The TriplePlay UI system is designed to provide standardized widgets and layouts for UI interaction, while preserving and utilizing PlayN’s game loop to achieve this goal. As such, the UI system will usually be kicked off as follows:

  • Create a tripleplay.ui.Interface instance.
  • Use this interface instance to create various root elements
  • Add a number of tripleplay.ui.Group instances to the root as a hierarchy.
  • Add various widgets as the lowest elements in the hierarchy.

##Understanding tripleplay.ui.Root The Root element represents the top of a discrete hierarchy and can be thought of similarly to the RootPanel in GWT. The Root acts simlarly to the Group below in that it also operates with a provided Layout policy.

##Understanding tripleplay.ui.Interface The interface object is needed to marshal all the time related “events” of all the root panels it’s created and for all of their children. As such, it provides an Animator instance (refer to above) that all the sub elements will use for their animations(see tripleplay.ui.Menu for an example), and also provides a similar style Task mechanism that elements can use to make use of the update-loop until such time as the Task completes.

Are you supposed to only create one interface? Ideally yes, but if you have separate parts of your PlayN game or have packaged a library to be used in other games that needed control of its own interface, then it's conceivable to have more.

##Understanding tripleplay.ui.Group : As is described in the documentation, the Group element is used for containing other elements and laying them out according to a layout-policy.

##Making sense of Style, Styles and Stylesheet : The styles mechanism in tripleplay is similar, but not exactly the same as CSS. Every property of an element that is considered a style of that element, is represented by an instance of the Style class. The sum collection of styles that happen to be set for an element is represented by an instance of Styles. A collection of Styles for various kinds of elements (or for various elements??) is represented by a Stylesheet.

##Understanding tripleplay.ui.Layout Layouts of any UI framework can be confusing, depending on your expectation, given other systems you may have used. Use the BoundaryDrawer.java tool (haven't yet posted it, it draws nested groups in different colours), to demonstrate how your code displays the Roots, Groups and different types of layers.

Tripleplay uses the Layout class to define a set of constraints (layout policy). It then has a LayoutData which as far as I can tell is kind of an instantiation of a particular Layout which is responsible for computing the size of that element/group given it's context.

?? How does preferredSize affect things ??

?? How does validation? computeSize()? layout()? affect things ??

####Example part 1. Let's start with an example.

//in the init()
GroupLayer layer = graphics().createGroupLayer();
iface = new Interface(); //used to take in delegate as argument
Stylesheet sheet = SimpleStyles.newSheet();
Root root = iface.createRoot(AxisLayout.vertical().gap(5), sheet);
root.addStyles(Style.HALIGN.left);
layer.add(root.layer);

The important things to notice here is we create an Interface, use it to create a Root with a vertical layout. We also add a style to the root (which is essentially a constraint.. the demarcation between styles and constraints is not crystal clear).

Finally we add the Root's layer to a GroupLayer which we add to the scene.

The most complicated code that is called so far is the root.addStyles(...), but this only really creates a new style bindings object the element in question (in this case the Root).

Nothing so far has actually really happened, except for a PlayN layer that has been created on behalf of the root.

//continuing in init()
Group group = new Group(new AxisLayout.Horizontal());
root.add(group);
group.add(new Button("A"));
group.add(new Button("B"));
group.add(new Button("C"));

This creates a Group and a series of buttons. Much like the code above, very little has actually happened yet. The button's text is specified, but not yet created. See part 2 below for an explanation of how the wiring of the button works.

//finally in init()
PlayN.graphics().rootLayer().add(layer);
root.pack();

####part 2

/** Creates a button with the supplied text and icon. */
    public Button (String text, Icon icon) {
        this.text.update(text);
        this.icon.update(icon);
        this.text.connect(textDidChange());
        this.icon.connect(iconDidChange());
    }

What exactly is happening here? We do know that the layerings/styles etc of the button have not been manifested yet (except for the icon which would have been created as a layer).

If this stuff here looks freaky apon inspection... it's because it is! You'll see lots of UnitSlots in the tripleplay ui code which hark from the react library. Here is an overview guide and there are also some youtube vids if you search for them. The value of functional-reactive-programming... I'm not quite sure yet. More research needed

From a cheat sheet perspective, always remember that there are types of objects that emit events: Signals emit one time events. Values emit events when their value gets changed.

Then there are Slots which listen for events and let you run some specific code (a handler).

I've done some very light searching for more complex examples of combining streams of events, but can't find anything very telling. At the moment React looks like it's being used as a potentially more powerful version of a simple event handling system.

####Part 3

###Understanding tripleplay.ui.layout.AxisLayout

###Extra notes

A thread on attempting to animate buttons

Clone this wiki locally