richarddlu / jmonkeyengine

Automatically exported from code.google.com/p/jmonkeyengine
0 stars 0 forks source link

New Custom Control Action does only find controls that either implement Control or directly derive from AbstractControl #623

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Say, if you have some AbstractCustomControl from which you derive your concrete 
controls from, then only the AbstractCustomControl will show up in the 
selection list of the wizard. Any controls derived from the abstract control 
will simply be ignored.

The problem lies in 
com.jme3.gde.core.sceneexplorer.nodes.actions.impl.NewCustomControlVisualPanel1#
getSources()

[...]
TypeElement elem = elementHandle.resolve(control);
List<? extends TypeMirror> interfaces = elem.getInterfaces();
for (TypeMirror typeMirror : interfaces) {
    String interfaceName = typeMirror.toString();
    if ("com.jme3.scene.control.Control".equals(interfaceName)) {
        list.add(elem.getQualifiedName().toString());
    }
}
TypeMirror superClass = elem.getSuperclass();
String superClassName = superClass.toString();
if ("com.jme3.scene.control.AbstractControl".equals(superClassName)) {
    list.add(elem.getQualifiedName().toString());
}
[...]

A better way would be to traverse the hierachy of direct supertypes like so

[...]
TypeElement elem = elementHandle.resolve(control);
if (isCustomControl(control, elem)) {
    list.add(elem.getQualifiedName().toString());
}
[...]

/**
 * Traverses the hierarchy of direct supertypes for the specified
 * typeElement and finds out whether one of these is either
 * com.jme3.scene.control.Control or com.jme3.scene.control.AbstractControl.
 *
 * @param control
 * @param typeElement
 * @return true whether this is a non abstract custom control, false
 * otherwise
 */
private boolean isCustomControl(CompilationController control, TypeElement 
typeElement) {
    boolean result = false;

    // we do not want any abstract elements
    if (!typeElement.getModifiers().contains(Modifier.ABSTRACT)
            && !ElementKind.INTERFACE.equals(typeElement.getKind())) {
        Types types = control.getTypes();
        Stack<TypeElement> stack = new Stack<TypeElement>();
        stack.add(typeElement);
        while (!stack.isEmpty()) {
            TypeElement element = stack.pop();
            List<? extends TypeMirror> directSupertypes = types.directSupertypes(element.asType());
            for (TypeMirror supertypeMirror : directSupertypes) {
                TypeElement supertypeElement = (TypeElement) types.asElement(supertypeMirror);
                String qualifiedName = supertypeElement.getQualifiedName().toString();
                if ("com.jme3.scene.control.Control".equals(qualifiedName)
                        || "com.jme3.scene.control.AbstractControl".equals(qualifiedName)) {
                    // we are done
                    result = true;
                    break;
                } else if (!"java.lang.Object".equals(qualifiedName)) {
                    // continue for all non java.lang.Object classes and interfaces
                    stack.push(supertypeElement);
                }
            }
        }
    }

    return result;
}

The above works fine with custom controls having been derived from custom 
abstract bases based on either interfaces which have been derived from Control 
or AbstractControl.
In addition, all abstract classes will be filtered out so one cannot 
accidentally select an AbstractCustomControl which would definetely cause an 
error as soon as the scene gets loaded.

Original issue reported on code.google.com by axnsoftw...@gmail.com on 28 Jan 2014 at 10:20

GoogleCodeExporter commented 8 years ago
The same holds true for the 
com.jme3.gde.core.sceneexplorer.nodes.actions.UserDataPicker which fails to 
find classes that are derived from custom savables...

Original comment by axnsoftw...@gmail.com on 28 Jan 2014 at 4:37

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Sorting the resulting list would be fine. Having many controls in different 
packages tends to become difficult when searching through the unsorted list.

Original comment by axnsoftw...@gmail.com on 28 Jan 2014 at 5:32

GoogleCodeExporter commented 8 years ago
Cool, thanks. You can create any conteol by simply specifying its full name 
though.

Original comment by normen667 on 29 Jan 2014 at 11:11

GoogleCodeExporter commented 8 years ago

Original comment by normen667 on 29 Jan 2014 at 11:11