Ver código fonte

SDK:
- Add support for loading classes from the project classpath with j3o files and use them in the editors
- Add support for adding custom Control classes to SceneExplorer

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8601 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

nor..67 14 anos atrás
pai
commit
c10f1641d0

+ 18 - 0
jme3-core/nbproject/project.xml

@@ -30,6 +30,15 @@
                         <specification-version>3.0.0</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.api.java.classpath</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.29</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.api.progress</code-name-base>
                     <build-prerequisite/>
@@ -80,6 +89,15 @@
                         <implementation-version/>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.java.project</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.38</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.java.source</code-name-base>
                     <build-prerequisite/>

+ 43 - 0
jme3-core/src/com/jme3/gde/core/assets/ProjectAssetManager.java

@@ -35,6 +35,8 @@ import com.jme3.asset.AssetEventListener;
 import com.jme3.asset.AssetKey;
 import com.jme3.asset.AssetManager;
 import com.jme3.asset.DesktopAssetManager;
+import java.net.URL;
+import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -42,9 +44,16 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.project.JavaProjectConstants;
 import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.api.project.Sources;
 import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileStateInvalidException;
 import org.openide.filesystems.XMLFileSystem;
+import org.openide.util.Exceptions;
 import org.openide.util.Lookup;
 import org.openide.util.lookup.Lookups;
 
@@ -58,6 +67,7 @@ public class ProjectAssetManager extends DesktopAssetManager {
     private Project project;
     private List<String> folderNames = new LinkedList<String>();
     private List<AssetEventListener> assetEventListeners = new LinkedList<AssetEventListener>();
+    private URLClassLoader loader;
 
     public ProjectAssetManager(Project prj, String folderName) {
         super(true);
@@ -66,6 +76,39 @@ public class ProjectAssetManager extends DesktopAssetManager {
             di.prepareManager(this);
         }
         addFolderLocator(folderName);
+        ProjectManager.mutex().postWriteRequest(new Runnable() {
+
+            public void run() {
+                updateClassLoader();
+            }
+        });
+    }
+
+    public void updateClassLoader() {
+        Sources sources = project.getLookup().lookup(Sources.class);
+        if (sources != null) {
+            if (loader != null) {
+                removeClassLoader(loader);
+            }
+            SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
+            List<URL> urls = new LinkedList<URL>();
+            for (SourceGroup sourceGroup : groups) {
+                ClassPath path = ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.EXECUTE);
+                if (path != null) {
+                    System.out.println("Classpath: " + path);
+                    try {
+                        FileObject[] roots = path.getRoots();
+                        for (FileObject fileObject : roots) {
+                            urls.add(fileObject.getURL());
+                        }
+                    } catch (FileStateInvalidException ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                }
+            }
+            loader = new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader());
+            addClassLoader(loader);
+        }
     }
 
     public ProjectAssetManager(FileObject path) {

+ 2 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/Bundle.properties

@@ -0,0 +1,2 @@
+NewCustomControlVisualPanel1.jTextField1.text=com.mycompany.mygame.MyControl
+NewCustomControlVisualPanel1.jLabel1.text=Class Name:

+ 57 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewCustomControlVisualPanel1.form

@@ -0,0 +1,57 @@
+<?xml version="1.1" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="1" attributes="0">
+                  <Component id="jTextField1" alignment="0" pref="360" max="32767" attributes="0"/>
+                  <Component id="jLabel1" alignment="0" pref="360" max="32767" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jTextField1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace pref="228" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JTextField" name="jTextField1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/jme3/gde/core/sceneexplorer/nodes/actions/impl/Bundle.properties" key="NewCustomControlVisualPanel1.jTextField1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/jme3/gde/core/sceneexplorer/nodes/actions/impl/Bundle.properties" key="NewCustomControlVisualPanel1.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>

+ 92 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewCustomControlVisualPanel1.java

@@ -0,0 +1,92 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.sceneexplorer.nodes.actions.impl;
+
+import javax.swing.JPanel;
+
+public final class NewCustomControlVisualPanel1 extends JPanel {
+
+    /** Creates new form NewCustomControlVisualPanel1 */
+    public NewCustomControlVisualPanel1() {
+        initComponents();
+    }
+
+    @Override
+    public String getName() {
+        return "Select Control";
+    }
+    
+    public String getClassName(){
+        return jTextField1.getText();
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jTextField1 = new javax.swing.JTextField();
+        jLabel1 = new javax.swing.JLabel();
+
+        jTextField1.setText(org.openide.util.NbBundle.getMessage(NewCustomControlVisualPanel1.class, "NewCustomControlVisualPanel1.jTextField1.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(NewCustomControlVisualPanel1.class, "NewCustomControlVisualPanel1.jLabel1.text")); // NOI18N
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addComponent(jTextField1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)
+                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jLabel1)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap(228, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JTextField jTextField1;
+    // End of variables declaration//GEN-END:variables
+}

+ 156 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewCustomControlWizardAction.java

@@ -0,0 +1,156 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.sceneexplorer.nodes.actions.impl;
+
+import com.jme3.gde.core.assets.ProjectAssetManager;
+import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractNewControlWizardAction;
+import com.jme3.gde.core.sceneexplorer.nodes.actions.NewControlAction;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.control.Control;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.text.MessageFormat;
+import java.util.List;
+import javax.swing.JComponent;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.WizardDescriptor;
+import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
+
+// An example action demonstrating how the wizard could be called from within
+// your code. You can move the code below wherever you need, or register an action:
+// @ActionID(category="...", id="com.jme3.gde.core.sceneexplorer.nodes.actions.impl.NewCustomControlWizardAction")
+// @ActionRegistration(displayName="Open NewCustomControl Wizard")
+// @ActionReference(path="Menu/Tools", position=...)
[email protected](service = NewControlAction.class)
+public final class NewCustomControlWizardAction extends AbstractNewControlWizardAction {
+
+    private WizardDescriptor.Panel[] panels;
+
+    public NewCustomControlWizardAction() {
+        name = "Custom Control";
+    }
+
+    @Override
+    protected Object showWizard(Node node) {
+        WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
+        // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
+        wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
+        wizardDescriptor.setTitle("Your wizard dialog title here");
+        wizardDescriptor.putProperty("asset_manager", node.getLookup().lookup(ProjectAssetManager.class));
+        Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
+        dialog.setVisible(true);
+        dialog.toFront();
+        boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
+        if (!cancelled) {
+            // do something
+            return wizardDescriptor;
+        }
+        return null;
+    }
+
+    @Override
+    protected Control doCreateControl(Spatial spatial, Object configuration) {
+        if (configuration == null) {
+            return null;
+        }
+        WizardDescriptor wizardDescriptor = (WizardDescriptor) configuration;
+        ProjectAssetManager manager = (ProjectAssetManager) wizardDescriptor.getProperty("asset_manager");
+        List<ClassLoader> loaders = manager.getClassLoaders();
+
+        String className = (String) wizardDescriptor.getProperty("class_name");
+        Class clazz = null;
+        try {
+            clazz = getClass().getClassLoader().loadClass(className);
+        } catch (ClassNotFoundException ex) {
+        }
+        for (ClassLoader classLoader : loaders) {
+            if (clazz == null) {
+                try {
+                    clazz = classLoader.loadClass(className);
+                } catch (ClassNotFoundException ex) {
+                }
+            }
+        }
+        if (clazz != null) {
+            try {
+                Object contr = clazz.newInstance();
+                if (contr instanceof Control) {
+                    return (Control) contr;
+                }
+            } catch (InstantiationException ex) {
+                Exceptions.printStackTrace(ex);
+            } catch (IllegalAccessException ex) {
+                Exceptions.printStackTrace(ex);
+            }
+        } else {
+            DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Cannot find this class:\n" + className));
+        }
+        return null;
+    }
+
+    /**
+     * Initialize panels representing individual wizard's steps and sets
+     * various properties for them influencing wizard appearance.
+     */
+    private WizardDescriptor.Panel[] getPanels() {
+        if (panels == null) {
+            panels = new WizardDescriptor.Panel[]{
+                new NewCustomControlWizardPanel1()
+            };
+            String[] steps = new String[panels.length];
+            for (int i = 0; i < panels.length; i++) {
+                Component c = panels[i].getComponent();
+                // Default step name to component name of panel. Mainly useful
+                // for getting the name of the target chooser to appear in the
+                // list of steps.
+                steps[i] = c.getName();
+                if (c instanceof JComponent) { // assume Swing components
+                    JComponent jc = (JComponent) c;
+                    // Sets step number of a component
+                    // TODO if using org.openide.dialogs >= 7.8, can use WizardDescriptor.PROP_*:
+                    jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
+                    // Sets steps names for a panel
+                    jc.putClientProperty("WizardPanel_contentData", steps);
+                    // Turn on subtitle creation on each step
+                    jc.putClientProperty("WizardPanel_autoWizardStyle", Boolean.TRUE);
+                    // Show steps on the left side with the image on the background
+                    jc.putClientProperty("WizardPanel_contentDisplayed", Boolean.TRUE);
+                    // Turn on numbering of all steps
+                    jc.putClientProperty("WizardPanel_contentNumbered", Boolean.TRUE);
+                }
+            }
+        }
+        return panels;
+    }
+}

+ 114 - 0
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/NewCustomControlWizardPanel1.java

@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2009-2010 jMonkeyEngine
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ * 
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.core.sceneexplorer.nodes.actions.impl;
+
+import java.awt.Component;
+import javax.swing.event.ChangeListener;
+import org.openide.WizardDescriptor;
+import org.openide.util.HelpCtx;
+
+public class NewCustomControlWizardPanel1 implements WizardDescriptor.Panel {
+
+    /**
+     * The visual component that displays this panel. If you need to access the
+     * component from this class, just use getComponent().
+     */
+    private Component component;
+
+    // Get the visual component for the panel. In this template, the component
+    // is kept separate. This can be more efficient: if the wizard is created
+    // but never displayed, or not all panels are displayed, it is better to
+    // create only those which really need to be visible.
+    public Component getComponent() {
+        if (component == null) {
+            component = new NewCustomControlVisualPanel1();
+        }
+        return component;
+    }
+
+    public HelpCtx getHelp() {
+        // Show no Help button for this panel:
+        return HelpCtx.DEFAULT_HELP;
+        // If you have context help:
+        // return new HelpCtx(SampleWizardPanel1.class);
+    }
+
+    public boolean isValid() {
+        // If it is always OK to press Next or Finish, then:
+        return true;
+        // If it depends on some condition (form filled out...), then:
+        // return someCondition();
+        // and when this condition changes (last form field filled in...) then:
+        // fireChangeEvent();
+        // and uncomment the complicated stuff below.
+    }
+
+    public final void addChangeListener(ChangeListener l) {
+    }
+
+    public final void removeChangeListener(ChangeListener l) {
+    }
+    /*
+    private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
+    public final void addChangeListener(ChangeListener l) {
+    synchronized (listeners) {
+    listeners.add(l);
+    }
+    }
+    public final void removeChangeListener(ChangeListener l) {
+    synchronized (listeners) {
+    listeners.remove(l);
+    }
+    }
+    protected final void fireChangeEvent() {
+    Iterator<ChangeListener> it;
+    synchronized (listeners) {
+    it = new HashSet<ChangeListener>(listeners).iterator();
+    }
+    ChangeEvent ev = new ChangeEvent(this);
+    while (it.hasNext()) {
+    it.next().stateChanged(ev);
+    }
+    }
+     */
+
+    // You can use a settings object to keep track of state. Normally the
+    // settings object will be the WizardDescriptor, so you can use
+    // WizardDescriptor.getProperty & putProperty to store information entered
+    // by the user.
+    public void readSettings(Object settings) {
+    }
+
+    public void storeSettings(Object settings) {
+        ((WizardDescriptor) settings).putProperty("class_name", ((NewCustomControlVisualPanel1) component).getClassName());
+    }
+}

+ 1 - 6
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/OpenSceneComposer.java

@@ -4,22 +4,16 @@
  */
 package com.jme3.gde.scenecomposer;
 
-import com.jme3.asset.DesktopAssetManager;
 import com.jme3.gde.core.assets.ProjectAssetManager;
 import com.jme3.gde.core.assets.BinaryModelDataObject;
 import com.jme3.scene.Spatial;
 import java.awt.event.ActionListener;
 import java.awt.event.ActionEvent;
-import java.io.IOException;
 import org.netbeans.api.progress.ProgressHandle;
 import org.netbeans.api.progress.ProgressHandleFactory;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
 import org.openide.NotifyDescriptor.Confirmation;
-import org.openide.filesystems.FileLock;
-import org.openide.filesystems.FileObject;
-import org.openide.util.Exceptions;
-import sun.misc.Perf.GetPerfAction;
 
 public final class OpenSceneComposer implements ActionListener {
 
@@ -47,6 +41,7 @@ public final class OpenSceneComposer implements ActionListener {
                         java.awt.EventQueue.invokeLater(new Runnable() {
 
                             public void run() {
+                                manager.updateClassLoader();
                                 manager.clearCache();
                                 SceneComposerTopComponent composer = SceneComposerTopComponent.findInstance();
                                 composer.openScene(asset, context, manager);