Building UI with PulpCore

I have been working on a little project that has a slightly more involved UI interface and while PulpCore provides enough widgets there is no easy way of laying out interface elements other that calculating pixel coordinates and sizes.

Anyway, after trying a few things I ended with a little DSL that looks like this:

uiHelper.place(toolbar).in(ui).height(40).spacing(2).top().left().hfill();

The code above places a sprite named toolbar inside a group named ui, positioned at the top/left corner, leaving a margin of 2 pixels and filling all the available space horizontally.

A few more examples:

Button buttonNew = uiHelper.place(
Button.createLabeledButton("New", 0, 0)).in(toolbar).vcenter().spacing(3).left().sprite();

Button buttonOpen = uiHelper.place(
Button.createLabeledButton("Open", 0, 0)).in(toolbar).vcenter().spacing(3).
rightOf(buttonNew).sprite();

uiHelper.place(palette).in(ui).width(250).spacing(2).below(toolbar).right().height(400);

uiHelper.place(timeline).in(ui).spacing(2).below(palette).left().hfill().vfill(palette);

Not too bad, once I got the hang of it things moved pretty quickly. Basically you start with a reference widget and add things to its right/below/whatever, widgets can then be resized to the size of a target sprite or can fill the remaining space using hfill/vfill.

The DSL is “imperative”, things are set/executed as soon as the method is called, there is no “do it” command at the end of the “sentence”.

This is the code that does it all in less than 100 LOC, just copy and paste into your project.

package toolkit.pulpcore;

import pulpcore.sprite.Group;
import pulpcore.sprite.Sprite;

public class SpriteHelper {
private Sprite sprite;
private Group container;
private int spacing;

public SpriteHelper place(Sprite sprite) {
this.sprite = sprite;
return this;
}

public SpriteHelper in(Group container) {
this.container = container;
container.add(sprite);
return this;
}

public SpriteHelper spacing(int spacing) {
this.spacing = spacing;
return this;
}

public SpriteHelper top() {
double y = spacing;
sprite.y.set(y);
return this;
}

public SpriteHelper bottom() {
double y = container.height.get() - sprite.height.get() - spacing;
sprite.y.set(y);
return this;
}

public SpriteHelper left() {
double x = spacing;
sprite.x.set(x);
return this;
}

public SpriteHelper right() {
double x = container.width.get() - sprite.width.get() - spacing;
sprite.x.set(x);
return this;
}

public SpriteHelper rightOf(Sprite target) {
double x = target.x.get() + target.width.get() + spacing;
sprite.x.set(x);
double y = target.y.get();
sprite.y.set(y);
return this;
}

public SpriteHelper leftOf(Sprite target) {
double y = target.y.get() - sprite.width.get() + -spacing;
sprite.y.set(y);
double x = target.x.get();
sprite.x.set(x);
return this;
}

public SpriteHelper below(Sprite target) {
double x = target.x.get();
sprite.x.set(x);
double y = target.y.get();
y += target.height.get();
y += spacing;
sprite.y.set(y);
return this;
}

public SpriteHelper hcenter() {
double x = container.width.get() / 2 - sprite.width.get() / 2;
sprite.x.set(x);

return this;
}

public SpriteHelper vcenter() {
double y = container.height.get() / 2 - sprite.height.get() / 2;
sprite.y.set(y);

return this;
}

/**
* Fill all the horizontal container space
*
* @return
*/
public SpriteHelper hfill() {
sprite.width.set(container.width.get() - spacing * 2);
return this;
}

/**
* Fill the remaining space to the right of the target
*
* @param target
*/
public void hfill(Sprite target) {
sprite.width.set(container.width.get() - target.x.get() - target.width.get() - 2 * spacing);
}

/**
* Fill all the vertical container space
*
* @return
*/
public SpriteHelper vfill() {
sprite.height.set(container.height.get() - spacing * 2);
return this;
}

/**
* Fill the remaining space below the target
*
* @param target
*/
public SpriteHelper vfill(Sprite target) {
sprite.height.set(container.height.get() - target.y.get() - target.height.get() - 2 * spacing);
return this;

}

public SpriteHelper height(double h) {
sprite.height.set(h);
return this;
}

public SpriteHelper width(double w) {
sprite.width.set(w);
return this;
}

@SuppressWarnings("unchecked")
public T sprite() {
return (T) sprite;
}
}

Leave a Reply

Your email address will not be published. Required fields are marked *