Commit 2cf40cc0 authored by Dumoulin Nicolas's avatar Dumoulin Nicolas
Browse files

branch

parent 3e75c76a
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- ************************************************************* -->
<!-- *** POM Relationships *************************************** -->
<!-- ************************************************************* -->
<groupId>fr.cemagref</groupId>
<artifactId>ohoui</artifactId>
<version>0.1.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>fr.cemagref</groupId>
<artifactId>lisc-commons</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.netbeans.api</groupId>
<artifactId>org-openide-util-lookup</artifactId>
<version>RELEASE691</version>
</dependency>
</dependencies>
<!-- ************************************************************* -->
<!-- *** Project Information ************************************* -->
<!-- ************************************************************* -->
<name>${project.artifactId} ${project.version}</name>
<description />
<url>http://trac.clermont.cemagref.fr/projets/LISC/wiki/JavaObservation</url>
<licenses>
<license>
<name>GPL</name>
<url>http://www.gnu.org/copyleft/gpl.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<!-- ************************************************************* -->
<!-- *** Build Settings ****************************************** -->
<!-- ************************************************************* -->
<packaging>jar</packaging>
<scm>
<connection>scm:svn:http://trac.clermont.cemagref.fr/svn/LISC/OhOUI/branches/0.1</connection>
<url>http://trac.clermont.cemagref.fr/projets/LISC/browser/OhOUI/branches/0.1</url>
</scm>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<!-- Cemagref - Lisc repository -->
<repository>
<id>fr.cemagref.lisc.maven2</id>
<name>Lisc repository</name>
<url>http://trac.clermont.cemagref.fr/maven/repo/</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>trac.clermont.cemagref.fr.nexus</id>
<url>http://trac.clermont.cemagref.fr/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>trac.clermont.cemagref.fr.nexus</id>
<url>http://trac.clermont.cemagref.fr/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>
package demo;
import java.awt.Color;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import fr.cemagref.commons.modulesloader.ModulesLoader;
import fr.cemagref.ohoui.annotations.Anchor;
import fr.cemagref.ohoui.annotations.Description;
import fr.cemagref.ohoui.annotations.Link;
import fr.cemagref.ohoui.annotations.XStreamable;
import fr.cemagref.ohoui.filters.NoTransientField;
import fr.cemagref.ohoui.swing.OhOUI;
import fr.cemagref.ohoui.swing.OhOUIDialog;
public class OhOUIDemo {
public static void main(String[] args) throws Exception {
// Init the engine
//ModulesLoader.addModulesPackage("demo");
//ModulesLoader.setLogStream(System.err);
ModulesLoader.addModulesJAR("rt.jar");
ModulesLoader.addModulesPackageForJar("rt.jar", "java.util");
ModulesLoader.addModulesPackageForJar("rt.jar", "java.lang");
ModulesLoader.addModulesPackageForJar("rt.jar", "java.io");
MyModel maclasse = new MyModel();
// Run the GUI
OhOUIDialog dialog = OhOUI.getDialog(null, maclasse, new NoTransientField());
if (dialog != null) {
dialog.pack();
dialog.setVisible(true);
}
// launch the method defined by the abstract class Algo
if (maclasse.algo != null) {
maclasse.algo.process();
}
if (maclasse.init != null) {
maclasse.init.doProcess();
}
// print the complete state of the object after edition
//System.out.println((new XStream(new DomDriver())).toXML(maclasse));
}
public static class MyModel<A extends Algo> {
public MyModel() {
listAlgo = new ArrayList<Algo>();
listAlgo.add(new AlgoAccurate());
listAlgo.add(new AlgoFaster());
//listAlgo2 = new ArrayList<AlgoAccurate>();
}
Test1 test1;
Test2 test2;
@Description(name = "A number", tooltip = "Here, you can add some indications")
private Integer aNumber = 1;
private double aDouble = 0.5f;
@Description(name = "Use color ?", tooltip = "Use the checkbox")
@Link(action = "enable", target = "color")
boolean b = true;
@Description(name = "The color of the sky ", tooltip = "Please, change this color")
@Anchor(id = "color")
Color color = new Color(150, 150, 150);
// without metadata
private String aString;
InitOpinionIncertitude init;
private Algo algo;
@Description(name = "List of processes", tooltip = "Used to compute your solution")
@XStreamable(load = true, save = true)
private List<Algo> listAlgo;
/*@XStreamable(load = true, save = true)
private List<? extends Algo> listAlgo2;*/
private List<A> listAlgo3;
//private List listAlgo4;
/*@Description(name = "Process", tooltip = "Used to compute your solution")
@XStreamable(load = true, save = true)
private Algo algo = new AlgoAccurate();*/
}
public static abstract class Algo {
@Description(name = "Input data", tooltip = "")
File input;
abstract void process();
}
public static class AlgoFaster extends Algo {
// some params that you may need for your algo
public double param1;
public double param2;
@Override
void process() {
// Here your process
System.out.println("fast " + param1);
}
}
public static class AlgoAccurate extends Algo {
public int param;
InitOpinionIncertitude trux;
@Override
void process() {
System.out.println("accurate");
// Here your process
}
}
public interface InitOpinionIncertitude {
void doProcess();
}
public class InitOpinionIncertitudeRandom implements InitOpinionIncertitude {
public InitOpinionIncertitudeRandom() {
System.out.println("*********************PLOP***************");
}
public void doProcess() {
System.out.println("Init Random");
}
}
}
package demo;
import java.util.List;
import fr.cemagref.commons.modulesloader.ModulesLoader;
import fr.cemagref.ohoui.filters.NoTransientField;
import fr.cemagref.ohoui.swing.OhOUI;
import fr.cemagref.ohoui.swing.OhOUIDialog;
public class Test1 {
int truc;
List<Integer> list;
public static void main(String[] args) throws Exception {
// Init the engine
//ModulesLoader.addModulesPackage("demo");
//ModulesLoader.setLogStream(System.err);
ModulesLoader.addModulesJAR("rt.jar");
ModulesLoader.addModulesPackageForJar("rt.jar","java.util");
ModulesLoader.addModulesPackageForJar("rt.jar","java.lang");
ModulesLoader.addModulesPackageForJar("rt.jar","java.io");
// Run the GUI
OhOUIDialog dialog = OhOUI.getDialog(null, new Test1(), new NoTransientField());
if (dialog != null) {
dialog.pack();
dialog.setVisible(true);
}
}
}
package demo;
public class Test2 {
}
package fr.cemagref.ohoui.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <code>Anchor</code>
*
* @see fr.cemagref.ohoui.annotations.Link
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Anchor {
String id();
}
package fr.cemagref.ohoui.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Description {
String name();
String tooltip();
}
package fr.cemagref.ohoui.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <code>Link</code> Allow to link action to another field.
*
* For example the action "disable" on a boolean will disable the OUIPanel
* targeted when the checkbox corresponding to the boolean field will be
* checked. To set the target,
*
* @see fr.cemagref.ohoui.annotations.Anchor
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Link {
String action();
String target();
}
package fr.cemagref.ohoui.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <code>NoRecursive</code> This annotation is used to decide if the
* introspection process should inpect recursively superClass.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface NoRecursive {
}
package fr.cemagref.ohoui.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XStreamable {
boolean load();
boolean save();
}
package fr.cemagref.ohoui.core;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.openide.util.Lookup;
public abstract class AbstractCollectionPanel<C> extends AbstractOUIPanel<C> {
protected IntrospectionContext collectionContext;
protected IntrospectionContext itemsContext;
protected Class itemClass;
protected Class[] availableTypesForItems;
protected List<AbstractOUIPanel<C>> ouiPanels;
public AbstractCollectionPanel(Object object) {
super(object);
}
public AbstractCollectionPanel(IntrospectionContext collectionContext) {
this(collectionContext.getObject());
this.collectionContext = collectionContext;
if (collectionContext.getObjectDeclaredType() == null) {
itemClass = getItemClass(collectionContext.getField().getGenericType());
} else {
itemClass = getItemClass(collectionContext.getObjectDeclaredType());
}
this.itemsContext = new IntrospectionContext(collectionContext).setObjectDeclaredType(itemClass);
availableTypesForItems = new ArrayList<Class>(Lookup.getDefault().lookupResult(itemClass).allClasses()).toArray(new Class[]{});
ouiPanels = new ArrayList<AbstractOUIPanel<C>>();
IntrospectionContext itemContext;
AbstractOUIPanel<C> buff;
for (Object element : (Collection) collectionContext.getObject()) {
itemContext = new IntrospectionContext(this.itemsContext).setObject(element);
buff = AbstractOhOUI.getProducerLookup().lookupProducer(itemContext.getObject().getClass()).getPanel(itemContext);
if (buff != null) {
ouiPanels.add(buff);
}
}
}
@Override
public Object getObject() {
// call the recursive update (especially for nested ObjectOUIPanel)
for (AbstractOUIPanel ouiPanel : ouiPanels) {
ouiPanel.getObject();
}
return super.object;
}
/**
* <code>getItemClass</code> retrieves the class allowed for the items of
* the field passed as argument. In fact, the class depends of the
* collection declaration :
* <ul>
* <li>Collection : Object is returned</li>
* <li>Collection<AClass> : AClass is returned</li>
* <li>Collection<? extends AClass> or Collection<? super AClass> :
* AClass is returned.</li>
* </ul>
*/
private Class getItemClass(Type gtype) {
Class result = Object.class;
try {
// if the type is parametrized, we look for this type
if (gtype instanceof ParameterizedType) {
// Collection are suposed to have only one parametrized type
assert ((ParameterizedType) gtype).getActualTypeArguments().length == 1;
Type type = ((ParameterizedType) gtype).getActualTypeArguments()[0];
if (type instanceof ParameterizedType) {
result = (Class) ((ParameterizedType) type).getRawType();
} else if (type instanceof WildcardType) {
// case with wildcard
if (((WildcardType) type).getLowerBounds().length > 0) {
result = (Class) ((WildcardType) type).getLowerBounds()[0];
} else if (((WildcardType) type).getUpperBounds().length > 0) {
result = (Class) ((WildcardType) type).getUpperBounds()[0];
}
} else if (type instanceof TypeVariable) {
Type bound = ((TypeVariable) type).getBounds()[0];
if (bound instanceof ParameterizedType) {
// if the parameter is again parametrized
result = (Class) ((ParameterizedType) bound).getRawType();
} else if (bound instanceof Class) {
result = (Class) bound;
}
} else if (type instanceof Class) // classical case
{
result = (Class) type;
}
}
} catch (Exception e) {
// if error, fall to Object.class
}
return result;
}
}
package fr.cemagref.ohoui.core;
import fr.cemagref.ohoui.annotations.Description;
import fr.cemagref.ohoui.annotations.NoRecursive;
import fr.cemagref.ohoui.annotations.XStreamable;
import fr.cemagref.ohoui.filters.FieldFilter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openide.util.Lookup;
/**
* <code>AbstractDefaultObjectProducer</code> is used to produce graphical
* form to edit an object that isn't handle by another producer.
*/
public abstract class AbstractDefaultObjectProducer<C> implements OUIPanelProducer<C> {
@Override
public Class[] getCompatibleTypes() {
return null;
}
/**
* <code>getPanel</code> is the main method for the introspection
* mechanism. Each field is introspected and generate calls to abstract
* method for generating the graphical controls.
*
* @param context
* @param objectPanel
* @return The panel to edit the object.
*/
protected AbstractOUIPanel<C> getPanel(IntrospectionContext context, AbstractObjectOUIPanel<C> objectPanel) {
assert context.getObject() != null;
// This object must not be parsed an other time
if (context.getStack().search(context.getObject()) >= 0) {
return null;
}
context.getStack().push(context.getObject());
// The index of panels corresponding to inner fields is used for
// rebuilding a nested panel
int indexOfCurrentNestedPanel = 0;
// And now, we begin the instrospection
Class type = context.getObject().getClass();
// First, we fetch the declared fields of this object
List<Field> fields = new ArrayList<Field>(Arrays.asList(type.getDeclaredFields()));
// Then, we fetch fields of super-classes
if (!context.getObject().getClass().isAnnotationPresent(NoRecursive.class)) {
type = type.getSuperclass();
while (type != null) {
for (Field innerField : type.getDeclaredFields()) {
fields.add(innerField);
}
type = type.getSuperclass();
}
}
// Now, we build a panel for each field
AbstractOUIPanel<C> fieldPanel;
IntrospectionContext fieldContext;
fieldsLoop:
for (Field innerField : fields) {
if (!innerField.isAccessible()) {
innerField.setAccessible(true);
// if one filter fails, we jump to the next field
}
for (FieldFilter fieldFilter : context.getFieldFilters()) {
if (!fieldFilter.accept(innerField)) {
continue fieldsLoop;
}
}
Logger.getLogger(AbstractDefaultObjectProducer.class.getName()).log(Level.FINER, "Introspecting a field: {0}.{1}",
new Object[]{innerField.getDeclaringClass().getName(), innerField.getName()});
fieldContext = new IntrospectionContext(context);
// updating the context
fieldContext.setField(innerField);
fieldContext.setObjectDeclaredType(innerField.getGenericType());
// fetching metadata
fieldContext.setTitle(innerField.getName()).setTooltip("");
if (innerField.isAnnotationPresent(Description.class)) {
fieldContext.setTitle(innerField.getAnnotation(Description.class).name());
fieldContext.setTooltip(innerField.getAnnotation(Description.class).tooltip().trim());
}
// fetching field content
try {
fieldContext.setObject(innerField.get(context.getObject()));
} catch (Exception e) {
e.printStackTrace();
return null;
}
// building the panel
List<Class> modules = new ArrayList<Class>(Lookup.getDefault().lookupResult(fieldContext.getField().getType()).allClasses());
Class[] moduleArray;
if (modules == null) {
moduleArray = new Class[]{fieldContext.getField().getType()};
} else {