Commits

Karsten Schmidt committed 9ffd5d1

removing GUIElement annotation param from all GUIElementBuilders, adding @FieldSelector annotation and selector utility method to allow for extra level of object scope. Also enforcing range limits when setting default value in Int/FloatRangeBuilders

Comments (0)

Files changed (11)

src/toxi/gui/AnnoTest.java

 import java.util.List;
 
 import processing.core.PApplet;
+import toxi.geom.Vec3D;
 import toxi.util.datatypes.FloatRange;
 import toxi.util.datatypes.IntegerRange;
 import controlP5.ControlEvent;
     @GUIElement(builder = FloatRangeBuilder.class)
     public FloatRange r2 = new FloatRange(-1, 1);
 
+    @GUIElement(label = "vector")
+    @FieldSelector(fields = "x,z")
+    public Vec3D pos = new Vec3D();
+
     private GUIManager gui;
 
     public void doRestart(ControlEvent e) {

src/toxi/gui/ButtonBuilder.java

 public class ButtonBuilder implements GUIElementBuilder {
 
     public List<Controller> createElementsFor(final Object context,
-            final Field field, GUIElement anno, Vec2D pos, String id,
-            String label, GUIManager gui) throws IllegalArgumentException,
+            final Field field, Vec2D pos, String id, String label,
+            GUIManager gui) throws IllegalArgumentException,
             IllegalAccessException {
         int buttonID;
         if (field.get(context).getClass() == String.class) {

src/toxi/gui/CheckboxBuilder.java

 public class CheckboxBuilder implements GUIElementBuilder {
 
     public List<Controller> createElementsFor(final Object context,
-            final Field field, GUIElement anno, Vec2D pos, String id,
-            String label, GUIManager gui) throws IllegalArgumentException,
+            final Field field, Vec2D pos, String id, String label,
+            GUIManager gui) throws IllegalArgumentException,
             IllegalAccessException {
         boolean state = field.getBoolean(context);
         Toggle ctrl =

src/toxi/gui/FieldSelector.java

+/*
+ * Copyright (c) 2010 Karsten Schmidt
+ * 
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ * 
+ * http://creativecommons.org/licenses/LGPL/2.1/
+ * 
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package toxi.gui;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FieldSelector {
+
+    public static final String EMPTY = "<empty>";
+
+    public String fields() default EMPTY;
+}

src/toxi/gui/FloatRangeBuilder.java

 import java.util.List;
 
 import toxi.geom.Vec2D;
+import toxi.math.MathUtils;
 import toxi.util.datatypes.FloatRange;
 import controlP5.ControlEvent;
 import controlP5.ControlListener;
     }
 
     public List<Controller> createElementsFor(final Object context,
-            final Field field, GUIElement anno, Vec2D pos, String id,
-            String label, GUIManager gui) throws IllegalArgumentException,
+            final Field field, Vec2D pos, String id, String label,
+            GUIManager gui) throws IllegalArgumentException,
             IllegalAccessException {
         List<Controller> controllers = new ArrayList<Controller>(1);
         FloatRange r = null;
             Range ra = field.getAnnotation(Range.class);
             if (ra != null) {
                 r = new FloatRange(ra.min(), ra.max());
-                r.setCurrent(field.getFloat(context));
+                r.setCurrent(MathUtils.clip(field.getFloat(context), r.min,
+                        r.max));
                 singleValue = true;
+            } else {
+                logger.warning("missing @Range for fieldID: " + id);
             }
         } else {
             r = (FloatRange) field.get(context);

src/toxi/gui/FloatRangeMinMaxBuilder.java

 public class FloatRangeMinMaxBuilder extends FloatRangeBuilder implements
         GUIElementBuilder {
 
+    @Override
     public List<Controller> createElementsFor(final Object context,
-            final Field field, GUIElement anno, Vec2D pos, String id,
-            String label, GUIManager gui) throws IllegalArgumentException,
+            final Field field, Vec2D pos, String id, String label,
+            GUIManager gui) throws IllegalArgumentException,
             IllegalAccessException {
         List<Controller> controllers = new ArrayList<Controller>(2);
         final FloatRange range = (FloatRange) field.get(context);

src/toxi/gui/GUIElementBuilder.java

 
 import java.lang.reflect.Field;
 import java.util.List;
+import java.util.logging.Logger;
 
 import toxi.geom.Vec2D;
 import controlP5.Controller;
 
 public interface GUIElementBuilder {
 
+    public static final Logger logger = Logger
+            .getLogger(GUIElementBuilder.class.getName());
+
+    /**
+     * @param context
+     *            the instance the variable to be controlled is belonging to
+     * @param field
+     *            reference to the actual variable field within the context
+     *            object
+     * @param pos
+     *            screen position for the controller
+     * @param id
+     *            controller ID
+     * @param label
+     *            controller label
+     * @param gui
+     *            ControlP5 parent instance
+     * @return
+     * @throws IllegalArgumentException
+     * @throws IllegalAccessException
+     */
     public List<Controller> createElementsFor(final Object context,
-            final Field field, GUIElement anno, Vec2D pos, String id,
-            String label, GUIManager gui) throws IllegalArgumentException,
+            final Field field, Vec2D pos, String id, String label,
+            GUIManager gui) throws IllegalArgumentException,
             IllegalAccessException;
 
     public int getMinSpacing();

src/toxi/gui/GUIManager.java

 import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.StringTokenizer;
 import java.util.logging.Logger;
 
 import toxi.geom.Vec2D;
     public static final Logger logger = Logger.getLogger(GUIManager.class
             .getName());
 
+    /**
+     * Attempts to retrieve {@link Field} references from the given context
+     * object and a list of comma-separated field names.
+     * 
+     * @param context
+     *            object to retrieve fields from
+     * @param fieldNames
+     *            list of field names
+     * @return list of field
+     */
+    public static List<Field> getSelectedFieldsIn(Object context,
+            String fieldNames) {
+        List<Field> fields = new LinkedList<Field>();
+        StringTokenizer st = new StringTokenizer(fieldNames, ",");
+        while (st.hasMoreTokens()) {
+            String id = st.nextToken();
+            try {
+                Field f = context.getClass().getField(id);
+                fields.add(f);
+            } catch (Exception e) {
+                logger.warning("can't access/find field: " + id
+                        + " in context: " + context.getClass().getName());
+            }
+        }
+        return fields;
+    }
+
     private ControlP5 gui;
     private Vec2D currPos;
 
         builders.put(c, builder);
     }
 
+    public void createControllers(Object context) {
+        createControllers(context, null);
+    }
+
     public void createControllers(Object context, int x, int y, String tab) {
         this.currPos = new Vec2D(x, y);
         try {
             for (Field f : context.getClass().getFields()) {
                 if (f.isAnnotationPresent(GUIElement.class)) {
+                    GUIElement a = f.getAnnotation(GUIElement.class);
                     Class<?> type = f.get(context).getClass();
-                    GUIElement a = f.getAnnotation(GUIElement.class);
                     GUIElementBuilder builder = null;
                     if (a.builder() != GUIElementBuilder.class) {
                         builder = a.builder().newInstance();
                     } else {
                         builder = getMappingForType(type);
                     }
-                    System.out.println(type + ": " + builder);
+                    // logger.info(type + ": " + builder);
                     if (builder != null) {
                         String label =
                                 !a.label().equals(GUIElement.NO_LABEL) ? a
                                         .label() : f.getName();
                         Vec2D pos = getPositionFor(a);
                         List<Controller> items =
-                                builder.createElementsFor(context, f, a, pos,
+                                builder.createElementsFor(context, f, pos,
                                         f.getName(), label, this);
                         for (Controller c : items) {
                             if (tab != null) {
                             currPos.y += builder.getMinSpacing();
                         }
                     } else {
-                        System.out.println("no mapping found for: " + type);
+                        logger.info("no mapping found for: " + type);
                     }
                 }
             }
         }
     }
 
-    public void createControllers(Object context) {
-        createControllers(context, null);
-    }
-
     public void createControllers(Object context, String tab) {
         int x, y;
         GUIConfiguration config =

src/toxi/gui/IntRangeBuilder.java

 import java.util.List;
 
 import toxi.geom.Vec2D;
+import toxi.math.MathUtils;
 import toxi.util.datatypes.IntegerRange;
 import controlP5.ControlEvent;
 import controlP5.ControlListener;
     }
 
     public List<Controller> createElementsFor(final Object context,
-            final Field field, GUIElement anno, Vec2D pos, String id,
-            String label, GUIManager gui) throws IllegalArgumentException,
+            final Field field, Vec2D pos, String id, String label,
+            GUIManager gui) throws IllegalArgumentException,
             IllegalAccessException {
         List<Controller> controllers = new ArrayList<Controller>(1);
         IntegerRange r = null;
             Range ra = field.getAnnotation(Range.class);
             if (ra != null) {
                 r = new IntegerRange((int) ra.min(), (int) ra.max());
-                r.setCurrent(field.getInt(context));
+                r.setCurrent(MathUtils.clip(field.getInt(context), r.min, r.max));
                 singleValue = true;
             }
         } else {

src/toxi/gui/IntRangeMinMaxBuilder.java

 public class IntRangeMinMaxBuilder extends IntRangeBuilder implements
         GUIElementBuilder {
 
+    @Override
     public List<Controller> createElementsFor(final Object context,
-            final Field field, GUIElement anno, Vec2D pos, String id,
-            String label, GUIManager gui) throws IllegalArgumentException,
+            final Field field, Vec2D pos, String id, String label,
+            GUIManager gui) throws IllegalArgumentException,
             IllegalAccessException {
         List<Controller> controllers = new ArrayList<Controller>(2);
         final IntegerRange range = (IntegerRange) field.get(context);

src/toxi/gui/RadioBuilder.java

     private int itemCount;
 
     public List<Controller> createElementsFor(Object context, Field field,
-            GUIElement anno, Vec2D pos, String id, String label, GUIManager gui)
+            Vec2D pos, String id, String label, GUIManager gui)
             throws IllegalArgumentException, IllegalAccessException {
         Radio r = gui.getGUI().addRadio(id, (int) pos.x, (int) pos.y);
         r.setBroadcast(false);