Home

What is so magic about cp5magic?

This is a little helper library for users of Processing and the popular ControlP5 GUI library (by Andreas Schlegel). Whilst both are great tools for small applications, the design approach of both is not very welcoming for slightly more complex usage scenarios, especially cases where one's data is more distributed and not all part of one large class. ControlP5 is providing some form of automatic GUI controller-to-variable mapping, however this works only for fields (variables) within the given PApplet instance to which the library is directly attached to (This is the standard anti-pattern used by most Processing libraries). Cumbersome boilerplate code is needed, if one wants to create GUI controllers for parameters stored in other classes. Furthermore, the creation of GUI controllers in general is done manually and requires repetitive code and manual placement of elements...

((Very) unfortunate) Disclaimer

It turns out Processing 1.2 isn't fully supporting Java 5 syntax as promised and plainly strips all annotations from code written in the PDE. So dear PDE users, sorry! If you're using Eclipse or another contemporary IDE you should be all set though...

Features

This library is an attempt to remedy all of these above issues by introducing a Java annotations based approach to automatic GUI generation. By simply using a set of simple annotations for all fields desired to have a GUI controller attached to, the actual GUI creation is reduced to 2 lines of code, regardless of how many controllers will be created.

GUIManager gui=new GUIManager(new ControlP5(this));
gui.createControllers(myDataObject);

myDataObject can be any container object with annotated fields as described below.

The GUIManager class is using the builder pattern and an extensible system to map field types to specific builders, which in turn are responsible for creating the actual ControlP5 elements. That way one can specify default mappings for any class and pick a compatible builder. So far the library supports the following types:

TypeDefault builderResulting controller
booleanCheckboxBuilderToggle
intIntRangeBuilderSlider
floatFloatRangeBuilderSlider
StringButtonBuilderButton
java.util.CollectionRadioBuilderRadio
toxi.util.datatypes.FloatRangeFloatRangeBuilder or FloatRangeMinMaxBuilder1 or 2 sliders
toxi.util.datatypes.IntegerRangeIntRangeBuilder or IntRangeMinMaxBuilder1 or 2 sliders

To create custom builders, simply create a new class implementing the GUIElementBuilder interface.

Auto-positioning

Unless coordinates for a GUI element are explicitly specified, the element will be automatically positioned below the previously created one. The spacing is done dynamically and provided by the individual builder instances (e.g. a toggle will require more vertical spacing than a slider).

The createControllers() method can also take x & y start coordinates and also supports placing elements in a given ControlP5 UI tab. E.g.

void setup() {
  size(640,480);
  ControlP5 cp5=new ControlP5(this);
  GUIManager gui=new GUIManager(cp5);
  Tab tab=cp5.addTab("misc");
  gui.createControllers(this,20,40,tab);
}

Annotations

There're currently 3 annotations used and defined by this system:

@GUIElement

This is the main annotation used to indicate that a GUI controller should be generated for this field. The annotation has several optional parameters to customize the default behaviour:

  • label: The label to be used for the GUI controller (if omitted, the variable name is used as label)
  • x: The X position of the GUI controller
  • y: The Y position of the GUI controller
  • builder: A class reference to a specific builder class, responsible for constructing the actual GUI controller. Can be omitted in most cases, but exists merely to provide more flexibility. If specified, it overrides the default mapping for this field type.
// mark this variable as GUI element
// (since no builder is specified the default mapping will be used)
@GUIElement(label = "wireframe mode")
public boolean isWireframe = true;

range

This annotation is used to define a possible value interval for float or int variables. When using the default builder, this annotation is required in addition to the standard @GUIElement one for variables of these types. The following parameters need to be specified for this annotation:

  • min possible min value
  • max possible max value
/// mark this variable as GUI element and specify value range for slider
@GUIElement(label = "number of columns")
@Range(min = 1, max = 30)
public int cols = 10;

@GUIConfiguration

This is a simple class-level annotation to specify the top-left position from which to automatically place GUI elements. Just like the @GUIElement class, it has an x and y parameter...

@GUIConfiguration(x=20, y=200)
public class CityConfig {
	
	@GUIElement
	public String btRegenerate
}

To init a GUI using an annotated data class like this, just use the version of createControllers() not needing x & y start coordinates:

// only specify the context object
gui.createControllers(new CityConfig());

Usage examples

Below are some typical examples how this library might be used:

// a java.util.List is a java.util.Collection and by default mapped to a Radio button group
@GUIElement(label="export format")
public List<String> formats=new ArrayList<String>();

void setup() {
  ...
  formats.add("png");
  formats.add("tga");
  formats.add("jpg");

  gui.createControllers(this);

  // now add a listener to this field by giving:
  // the field name,
  // the name of the handler/listener method
  // the instance of the listener (here we use the main PApplet, but could be another class too)
  gui.addListenerFor("formats","selectFormat",this);
}

void selectFormat(ControlEvent e) {
  println("format: "+formats.get((int)e.value()));
}

Some design contexts also require to parameters to be expressed as range only and allow users to manipulate both the min/max values. The toxiclibscore package therefore contains different range types, which can be used with this library to create a pair of sliders.

// the MinMax builder will create 2 sliders: 1 to adjust the min value, the other for the max value
@GUIElement(label="block size", x=20, y=40, builder=toxi.gui.FloatRangeMinMaxBuilder.class)
public FloatRange blockSize=new FloatRange(50,100);

For more examples please see the AnnoTest demo in the repo: http://bitbucket.org/postspectacular/cp5magic/src/tip/src/toxi/gui/AnnoTest.java

Dependencies

The library depends on the following other projects/libraries (bundled with the source repo, but not with the release jar):

Source checkout

Simply clone this repository to get the full Eclipse project onto your machine (instructions above). Then, in Eclipse, choose:

File > Import... > Existing projects into Workspace

Contact & license

This is a PostSpectacular offering released under the GNU LPGL 2.1 (c) 2010 Karsten Schmidt

Have fun!

Updated

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.