From e0dac249a436442495dcf299368722439c3bf488 Mon Sep 17 00:00:00 2001 From: "rem..om" Date: Mon, 20 Aug 2012 21:02:30 +0000 Subject: [PATCH] SDK : One can now add and edit user data of a custom data type. The custom type must be a Savable with get and set accessors for every attribute and propper read an write method. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9671 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../gde/core/properties/UserDataProperty.java | 26 +- .../core/sceneexplorer/nodes/JmeSpatial.java | 2 +- .../nodes/actions/AddUserDataAction.java | 2 +- .../nodes/actions/Bundle.properties | 5 + .../nodes/actions/UserDataDialog.form | 68 ++++- .../nodes/actions/UserDataDialog.java | 228 +++++++++++++- .../nodes/actions/UserDataPicker.form | 138 +++++++++ .../nodes/actions/UserDataPicker.java | 284 ++++++++++++++++++ 8 files changed, 723 insertions(+), 30 deletions(-) create mode 100644 sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.form create mode 100644 sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.java diff --git a/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java b/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java index 75980a25d..7918ae1d0 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/properties/UserDataProperty.java @@ -32,8 +32,12 @@ package com.jme3.gde.core.properties; import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.sceneexplorer.nodes.actions.UserDataDialog; import com.jme3.scene.Spatial; +import java.awt.Component; import java.beans.PropertyEditor; +import java.beans.PropertyEditorSupport; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.LinkedList; @@ -42,6 +46,7 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.JFrame; import org.openide.nodes.PropertySupport; import org.openide.util.Exceptions; @@ -52,15 +57,17 @@ import org.openide.util.Exceptions; public class UserDataProperty extends PropertySupport.ReadWrite { private Spatial spatial; + private JmeSpatial node; private String name = "null"; private int type = 0; private List listeners = new LinkedList(); - public UserDataProperty(Spatial node, String name) { + public UserDataProperty(JmeSpatial node, String name) { super(name, String.class, name, ""); - this.spatial = node; + this.spatial = node.getLookup().lookup(Spatial.class); + this.node = node; this.name = name; - this.type = getObjectType(node.getUserData(name)); + this.type = getObjectType(spatial.getUserData(name)); } public static int getObjectType(Object type) { @@ -126,7 +133,18 @@ public class UserDataProperty extends PropertySupport.ReadWrite { @Override public PropertyEditor getPropertyEditor() { - return null; + return new PropertyEditorSupport(spatial.getUserData(name)) { + + @Override + public boolean supportsCustomEditor() { + return true; + } + + @Override + public Component getCustomEditor() { + return new UserDataDialog(new JFrame(), true, node, name); + } + }; // return new AnimationPropertyEditor(control); } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java index 39d2d4af1..b132b7dbf 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/JmeSpatial.java @@ -304,7 +304,7 @@ public class JmeSpatial extends AbstractSceneExplorerNode { set.setName(Spatial.class.getName() + "_UserData"); for (Iterator it = dataKeys.iterator(); it.hasNext();) { String string = it.next(); - UserDataProperty prop = new UserDataProperty(spatial, string); + UserDataProperty prop = new UserDataProperty(this, string); prop.addPropertyChangeListener(this); set.put(prop); } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddUserDataAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddUserDataAction.java index 1b096c472..4524f2dae 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddUserDataAction.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AddUserDataAction.java @@ -43,7 +43,7 @@ public final class AddUserDataAction implements ActionListener { public AddUserDataAction(JmeSpatial context) { this.context = context; - dialog=new UserDataDialog(new JFrame(), true, context); + dialog=new UserDataDialog(new JFrame(), true, context,null); } public void actionPerformed(ActionEvent ev) { diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/Bundle.properties b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/Bundle.properties index 2a3ddc099..6a3c71744 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/Bundle.properties +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/Bundle.properties @@ -5,3 +5,8 @@ UserDataDialog.jButton2.text=Cancel UserDataDialog.jLabel1.text=Name: UserDataDialog.jTextField2.text= UserDataDialog.jLabel2.text=Data: +UserDataDialog.jButton3.text=Remove +UserDataPicker.jPanel1.border.title=Chose a UserData type +UserDataPicker.jTextField1.text= +UserDataPicker.jButton1.text=Ok +UserDataPicker.jButton2.text=Cancel diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form index 022c23cbc..5ca6d5389 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.form @@ -1,6 +1,12 @@
+ + + + + + @@ -22,20 +28,19 @@ - + - - + + - - + - + @@ -45,9 +50,17 @@ + + + + + + + + + - @@ -65,12 +78,15 @@ - + + + + - + @@ -79,15 +95,19 @@ - + + + + + @@ -140,5 +160,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java index 5cbfb689c..419306d13 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataDialog.java @@ -37,26 +37,119 @@ */ package com.jme3.gde.core.sceneexplorer.nodes.actions; +import com.jme3.effect.influencers.ParticleInfluencer; +import com.jme3.export.Savable; +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.properties.SceneExplorerProperty; +import com.jme3.gde.core.properties.ScenePropertyChangeListener; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.core.util.PropertyUtils; import com.jme3.scene.Spatial; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Label; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.explorer.propertysheet.PropertyPanel; import org.openide.loaders.DataObject; +import org.openide.nodes.Node.Property; +import org.openide.util.Exceptions; /** * * @author normenhansen */ -public class UserDataDialog extends javax.swing.JDialog { +public class UserDataDialog extends javax.swing.JDialog implements ScenePropertyChangeListener { JmeSpatial spat; + boolean initialized = false; + Object userData; /** Creates new form UserDataDialog */ - public UserDataDialog(java.awt.Frame parent, boolean modal, JmeSpatial spat) { + public UserDataDialog(java.awt.Frame parent, boolean modal, JmeSpatial spat, String userDataName) { super(parent, modal); this.spat = spat; + + setLocationRelativeTo(null); initComponents(); + jButton3.setVisible(false); + if (userDataName != null) { + jButton3.setVisible(true); + jTextField2.setEditable(false); + jComboBox1.setEnabled(false); + + userData = spat.getLookup().lookup(Spatial.class).getUserData(userDataName); + jTextField2.setText(userDataName); + jTextField1.setText(userData.toString()); + jPanel1.setVisible(false); + if (userData instanceof String) { + jComboBox1.setSelectedItem("String"); + } else if (userData instanceof Integer) { + jComboBox1.setSelectedItem("Int"); + } else if (userData instanceof Float) { + jComboBox1.setSelectedItem("Float"); + } else if (userData instanceof Boolean) { + jComboBox1.setSelectedItem("Boolean"); + } else if (userData instanceof Long) { + jComboBox1.setSelectedItem("Long"); + } else { + jComboBox1.setSelectedItem("Custom"); + + buildCustomSheet(userData); + } + } + } + + private void buildCustomSheet(Object userData) { + jPanel1.setVisible(true); + jTextField1.setEditable(false); + jTextField1.setText(userData.getClass().getName()); + Class c = userData.getClass(); + if (!initialized) { + initialized = true; + + + GridLayout layout = new GridLayout(0, 2); + layout.setHgap(10); + jPanel1.setLayout(layout); + jPanel1.setPreferredSize(new Dimension(300, c.getDeclaredFields().length * 20)); + + + for (Field field : c.getDeclaredFields()) { + PropertyDescriptor prop = PropertyUtils.getPropertyDescriptor(c, field); + if (prop != null) { + PropertyPanel p = new PropertyPanel(makeProperty(userData, prop.getPropertyType(), prop.getReadMethod().getName(), prop.getWriteMethod().getName(), prop.getDisplayName())); + jPanel1.add(new Label(field.getName() + " :", Label.RIGHT)); + jPanel1.add(p); + } + } + } + setSize(getWidth(), getHeight() + c.getDeclaredFields().length * 20); + + } + + public void propertyChange(String property, Object oldValue, Object newValue) { + //System.out.println(property + " changed"); + } + + protected Property makeProperty(Object obj, Class returntype, String method, String setter, String name) { + Property prop = null; + try { + + prop = new SceneExplorerProperty(obj.getClass().cast(obj), returntype, method, setter, this); + + prop.setName(name); + + } catch (NoSuchMethodException ex) { + Exceptions.printStackTrace(ex); + } + return prop; } private void updateSpatial() { @@ -71,6 +164,7 @@ public class UserDataDialog extends javax.swing.JDialog { SceneApplication.getApplication().enqueue(new Callable() { public Void call() throws Exception { + if (format.equals("String")) { spatial.setUserData(name, data); } else if (format.equals("Int")) { @@ -81,6 +175,8 @@ public class UserDataDialog extends javax.swing.JDialog { spatial.setUserData(name, Boolean.parseBoolean(data)); } else if (format.equals("Long")) { spatial.setUserData(name, Long.parseLong(data)); + } else if (userData != null) { + spatial.setUserData(name, userData); } return null; } @@ -93,6 +189,46 @@ public class UserDataDialog extends javax.swing.JDialog { setVisible(false); } + public void setUserDataType(String className) { + ProjectAssetManager manager = (ProjectAssetManager) spat.getLookup().lookup(ProjectAssetManager.class); + List loaders = manager.getClassLoaders(); + + + 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 obj = clazz.newInstance(); + if (obj instanceof Savable) { + userData = obj; + buildCustomSheet(userData); + } else { + DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("This is no ParticleInfluencer class!")); + } + } catch (InstantiationException ex) { + Exceptions.printStackTrace(ex); + DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Error instatiating class!")); + } catch (IllegalAccessException ex) { + Exceptions.printStackTrace(ex); + DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Error instatiating class!")); + } + } else { + DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Cannot find class: " + className + "\nMake sure the name is correct and the project is compiled,\nbest enable 'Save on Compile' in the project preferences.")); + } + + } + /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is @@ -102,6 +238,7 @@ public class UserDataDialog extends javax.swing.JDialog { // //GEN-BEGIN:initComponents private void initComponents() { + jScrollPane1 = new javax.swing.JScrollPane(); jComboBox1 = new javax.swing.JComboBox(); jTextField1 = new javax.swing.JTextField(); jButton1 = new javax.swing.JButton(); @@ -109,10 +246,17 @@ public class UserDataDialog extends javax.swing.JDialog { jLabel1 = new javax.swing.JLabel(); jTextField2 = new javax.swing.JTextField(); jLabel2 = new javax.swing.JLabel(); + jButton3 = new javax.swing.JButton(); + jPanel1 = new javax.swing.JPanel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "String", "Int", "Float", "Boolean", "Long" })); + jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "String", "Int", "Float", "Boolean", "Long", "Custom" })); + jComboBox1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jComboBox1ActionPerformed(evt); + } + }); jTextField1.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jTextField1.text")); // NOI18N jTextField1.addActionListener(new java.awt.event.ActionListener() { @@ -141,6 +285,26 @@ public class UserDataDialog extends javax.swing.JDialog { jLabel2.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jLabel2.text")); // NOI18N + jButton3.setText(org.openide.util.NbBundle.getMessage(UserDataDialog.class, "UserDataDialog.jButton3.text")); // NOI18N + jButton3.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton3ActionPerformed(evt); + } + }); + + jPanel1.setAutoscrolls(true); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 322, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 0, Short.MAX_VALUE) + ); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -148,23 +312,29 @@ public class UserDataDialog extends javax.swing.JDialog { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(jButton2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButton1)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 187, Short.MAX_VALUE)) + .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addComponent(jLabel2) .addGap(18, 18, 18) .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 186, Short.MAX_VALUE))) .addGap(18, 18, 18) - .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGap(20, 20, 20)) + .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(20, 20, 20)) + .addGroup(layout.createSequentialGroup() + .addComponent(jButton3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 123, Short.MAX_VALUE) + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1) + .addGap(20, 20, 20)))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -178,11 +348,14 @@ public class UserDataDialog extends javax.swing.JDialog { .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel2)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jButton1) - .addComponent(jButton2)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(jButton2) + .addComponent(jButton3)) + .addContainerGap()) ); pack(); @@ -199,12 +372,39 @@ public class UserDataDialog extends javax.swing.JDialog { private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed updateSpatial(); }//GEN-LAST:event_jButton1ActionPerformed + +private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed + spat.getLookup().lookup(Spatial.class).setUserData(jTextField2.getText(), null); + spat.refreshProperties(); + spat.getLookup().lookup(DataObject.class).setModified(true); + setVisible(false); +}//GEN-LAST:event_jButton3ActionPerformed + +private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed + if (jComboBox1.getSelectedItem().equals("Custom")) { + if (userData != null) { + buildCustomSheet(userData); + + } else { + UserDataPicker picker = new UserDataPicker(null, true, this, spat); + picker.setVisible(true); + } + } else { + jPanel1.setVisible(false); + jTextField1.setEditable(true); + setSize(getWidth(), getHeight() - jPanel1.getHeight()); + + } +}//GEN-LAST:event_jComboBox1ActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; + private javax.swing.JButton jButton3; private javax.swing.JComboBox jComboBox1; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTextField jTextField1; private javax.swing.JTextField jTextField2; // End of variables declaration//GEN-END:variables diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.form b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.form new file mode 100644 index 000000000..14ac68f10 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.form @@ -0,0 +1,138 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.java new file mode 100644 index 000000000..4acfd85b0 --- /dev/null +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/UserDataPicker.java @@ -0,0 +1,284 @@ + /* + * 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. + */ +/* + * UserDataPicker.java + * + * Created on 20 août 2012, 22:09:04 + */ +package com.jme3.gde.core.sceneexplorer.nodes.actions; + +import com.jme3.gde.core.assets.ProjectAssetManager; +import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import java.awt.EventQueue; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.swing.DefaultListModel; +import javax.swing.JComboBox; +import javax.swing.ListModel; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.java.project.JavaProjectConstants; +import org.netbeans.api.java.source.ClassIndex; +import org.netbeans.api.java.source.ClassIndex.NameKind; +import org.netbeans.api.java.source.ClassIndex.SearchScope; +import org.netbeans.api.java.source.ClasspathInfo; +import org.netbeans.api.java.source.CompilationController; +import org.netbeans.api.java.source.ElementHandle; +import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.java.source.JavaSource.Phase; +import org.netbeans.api.java.source.Task; +import org.netbeans.api.project.SourceGroup; +import org.netbeans.api.project.Sources; +import org.openide.util.Exceptions; + +/** + * + * @author Nehon + */ +public class UserDataPicker extends javax.swing.JDialog { + + UserDataDialog parentDialog; + JmeSpatial spat; + + /** Creates new form UserDataPicker */ + public UserDataPicker(java.awt.Frame parent, boolean modal, UserDataDialog parentDialog, JmeSpatial spat) { + super(parent, modal); + this.spat = spat; + this.parentDialog = parentDialog; + initComponents(); + + setLocationRelativeTo(null); + ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); + + jList1.setEnabled(false); + //loading savable list in a new Thread + exec.execute(new Runnable() { + + public void run() { + final DefaultListModel model = getSources(); + EventQueue.invokeLater(new Runnable() { + + public void run() { + jList1.setModel(model); + jList1.setEnabled(true); + } + }); + + } + }); + + + } + + private DefaultListModel getSources() { + final DefaultListModel model = new DefaultListModel(); + Sources sources = spat.getLookup().lookup(ProjectAssetManager.class).getProject().getLookup().lookup(Sources.class); + if (sources != null) { + SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); + if (groups != null) { + for (SourceGroup sourceGroup : groups) { + ClasspathInfo cpInfo = ClasspathInfo.create(ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.BOOT), + ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.COMPILE), + ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.SOURCE)); + + HashSet set = new HashSet(); + set.add(ClassIndex.SearchScope.SOURCE); + + Set> types = cpInfo.getClassIndex().getDeclaredTypes("", NameKind.PREFIX, set); + for (Iterator> it = types.iterator(); it.hasNext();) { + final ElementHandle elementHandle = it.next(); + JavaSource js = JavaSource.create(cpInfo); + try { + js.runUserActionTask(new Task() { + + public void run(CompilationController control) + throws Exception { + control.toPhase(Phase.RESOLVED); + //TODO: check with proper casting check.. gotta get TypeMirror of Control interface.. +// TypeUtilities util = control.getTypeUtilities();//.isCastable(Types., null) +// util.isCastable(null, null); + TypeElement elem = elementHandle.resolve(control); + List interfaces = elem.getInterfaces(); + for (TypeMirror typeMirror : interfaces) { + String interfaceName = typeMirror.toString(); + if ("com.jme3.export.Savable".equals(interfaceName)) { + model.addElement(elem.getQualifiedName().toString()); + } + } + } + }, false); + } catch (Exception ioe) { + Exceptions.printStackTrace(ioe); + } + } + + } + } + } + return model; + } + + /** 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. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jList1 = new javax.swing.JList(); + jTextField1 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(UserDataPicker.class, "UserDataPicker.jPanel1.border.title"))); // NOI18N + + jList1.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "Loading Savable types..." }; + public int getSize() { return strings.length; } + public Object getElementAt(int i) { return strings[i]; } + }); + jList1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + jList1MouseClicked(evt); + } + }); + jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + jList1ValueChanged(evt); + } + }); + jScrollPane1.setViewportView(jList1); + + jTextField1.setText(org.openide.util.NbBundle.getMessage(UserDataPicker.class, "UserDataPicker.jTextField1.text")); // NOI18N + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jTextField1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 323, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 323, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 204, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + jButton1.setText(org.openide.util.NbBundle.getMessage(UserDataPicker.class, "UserDataPicker.jButton1.text")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText(org.openide.util.NbBundle.getMessage(UserDataPicker.class, "UserDataPicker.jButton2.text")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(jButton2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 225, Short.MAX_VALUE) + .addComponent(jButton1) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1) + .addComponent(jButton2)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + +private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + setVisible(false); +}//GEN-LAST:event_jButton2ActionPerformed + +private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + + + parentDialog.setUserDataType(jTextField1.getText()); + setVisible(false); + +}//GEN-LAST:event_jButton1ActionPerformed + +private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_jList1ValueChanged + jTextField1.setText(jList1.getSelectedValue().toString()); +}//GEN-LAST:event_jList1ValueChanged + +private void jList1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jList1MouseClicked + if (evt.getClickCount() == 2) { + jButton1ActionPerformed(null); + } +}//GEN-LAST:event_jList1MouseClicked + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JList jList1; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables +}