Skip to content

Instantly share code, notes, and snippets.

@frankleonrose
Created December 11, 2012 20:32
Show Gist options
  • Save frankleonrose/4261903 to your computer and use it in GitHub Desktop.
Save frankleonrose/4261903 to your computer and use it in GitHub Desktop.
Simple class to create a set of controlP5.Slider controllers from a POJO with setValueName(<Numeric Type>) methods. Optional Range annotation and getting of default value.
// I ran into a weird unknown method invocation with cp5magic (perhaps because I have to use Processing 1.5.1 because of bugs in 2.0b).
// That combined with having classes with setParamName1(numeric) style setters, I wrote this. Enjoy.
/*
Usage:
public class MyParameterClass {
double myParameter = 100d;
@Range(max=200)
public void setMyParameter(double v) { myParameter = v; }
public double getMyParameter() { return myParameter; }
// Any number of other params, same structure…
// Only the setter method is required
}
MyParameterClass myParams = new MyParameterClass();
ParameterView pv = new ParameterView(cp5);
pv.createControllers(myParams);
*/
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.InvalidParameterException;
import controlP5.ControlEvent;
import controlP5.ControlListener;
import controlP5.ControlP5;
import controlP5.ControlWindow;
import controlP5.ControllerGroup;
import controlP5.Slider;
import controlP5.Tab;
public class ParameterView {
@Retention(RetentionPolicy.RUNTIME)
public @interface Range {
float min() default 0f;
float max();
}
private ControlP5 cp5;
private int width;
private int controlY = 0;
private ControlWindow window;
public ParameterView(final ControlP5 cp5) {
this.cp5 = cp5;
this.width = 400;
window = cp5.controlWindow;
// cp5.addControlWindow("Parameter Window", 100, 100, 400, 600)
// .hideCoordinates().setBackground(0);
cp5.addBang("Save Properties").addListener(new ControlListener() {
@Override
public void controlEvent(ControlEvent theEvent) {
cp5.saveProperties();
}
});
}
public void createControllers(final Object pojo) {
Tab tab = cp5.addTab(window, pojo.getClass().getSimpleName());
ControllerGroup<?> group = cp5.begin(window);
controlY = 0;
for (final Method setter : pojo.getClass().getMethods()) {
if (setter.getName().startsWith("set")) {
@SuppressWarnings("rawtypes")
final Class parameterClass = getNumericParameter(setter);
if (parameterClass != null) {
float min = 0;
float max = 100;
float defalt = 50;
try {
Method getter = pojo.getClass().getMethod(
setter.getName().replace("set", "get"));
Object val = getter.invoke(pojo);
if (val instanceof Number) {
defalt = ((Number) val).floatValue();
// Make sure range includes default...
max = Math.max(max, defalt);
min = Math.min(min, defalt);
}
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoSuchMethodException e1) {
// Possible...
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Range a = setter.getAnnotation(Range.class);
if (a!=null) {
min = a.min();
max = a.max();
// Ensure that defalt is within min<=defalt<=max
defalt = Math.min(defalt, max);
defalt = Math.max(min, defalt);
}
String label = setter.getName().replace("set", "");
Slider slider = cp5.addSlider(label)
.setLabelVisible(true)
.setPosition(0, controlY += 20)
.setSize(width / 2, 20)
.setRange(min, max)
.setValue(defalt)
.setGroup(group)
.setTab(tab.getName());
slider.addListener(new ControlListener() {
@Override
public void controlEvent(ControlEvent theEvent) {
try {
if (parameterClass == Integer.class
|| parameterClass == Integer.TYPE) {
int val = (int) theEvent.getValue();
setter.invoke(pojo, val);
}
else if (parameterClass == Double.class
|| parameterClass == Double.TYPE) {
double val = theEvent.getValue();
setter.invoke(pojo, val);
}
else if (parameterClass == Float.class
|| parameterClass == Float.TYPE) {
float val = theEvent.getValue();
setter.invoke(pojo, val);
}
else {
throw new InvalidParameterException(
"Cannot handle parameter type "
+ parameterClass);
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
}
cp5.end();
}
@SuppressWarnings("rawtypes")
private Class getNumericParameter(Method m) {
if (m.getParameterTypes().length != 1) {
return null;
}
// @SuppressWarnings("rawtypes")
Class pc = m.getParameterTypes()[0];
if (pc.getSuperclass() == Number.class) {
return pc;
}
if (pc == Double.TYPE || pc == Float.TYPE || pc == Integer.TYPE
|| pc == Long.TYPE) {
return pc;
}
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment