Add Custom Filter Functionality: Having some issues

Hi @normen,

I want to add a “Custom Filter” option to the “Add Filter…” menu on the FilterExplorer Window. Same funtionality to “Add Custom Control”.
I was able to write the code but I’m having an issue: I cann’t get the ProjectAssetManager instance to pass it to NewCustomFilterWizardAction class. ProjectAssetManager is null whe I use
pm = rootNode.getLookup().lookup(ProjectAssetManager.class);
on AbstractNewFilterWizardAction.makeAction()

Do you thing this functionality (adding custom filters to FilterExplorar Window) will be usseful/handy?
Please, can you take a look and help me to solve the issue when you have time?

Thanks

Patch
#P JME3Trunk
Index: sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterWizardPanel1.java

— sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterWizardPanel1.java (revision 0)
+++ sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterWizardPanel1.java (working copy)
@@ -0,0 +1,116 @@
+/*

    • Copyright © 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.filters.impl;

+import java.awt.Component;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.project.Project;
+import org.openide.WizardDescriptor;
+import org.openide.util.HelpCtx;
+
+public class NewCustomFilterWizardPanel1 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 NewCustomFilterVisualPanel1();
    
  •    }
    
  •    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) {
  •    ((NewCustomFilterVisualPanel1) component).load((Project)((WizardDescriptor) settings).getProperty("project"));
    
  • }
  • public void storeSettings(Object settings) {
  •    ((WizardDescriptor) settings).putProperty("class_name", ((NewCustomFilterVisualPanel1) component).getClassName());
    
  • }
    +}
    Index: sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterVisualPanel1.java
    ===================================================================
    — sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterVisualPanel1.java (revision 0)
    +++ sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterVisualPanel1.java (working copy)
    @@ -0,0 +1,224 @@
    +/*
    • Copyright © 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.filters.impl;

+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.swing.JPanel;
+
+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.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.api.project.Sources;
+import org.openide.util.Exceptions;
+
+public final class NewCustomFilterVisualPanel1 extends JPanel {
+

  • Project proj;
  • /**
  • * Creates new form NewCustomFilterVisualPanel1
    
  • */
    
  • public NewCustomFilterVisualPanel1() {
  •    this.proj = proj;
    
  •    initComponents();
    
  • }
  • @Override
  • public String getName() {
  •    return "Select Filter";
    
  • }
  • public String getClassName() {
  •    return this.jTextField1.getText();
    
  • }
  • private void scanFilters() {
  •    final List&lt;String&gt; sources = getSources();
    
  •    this.jList1.setListData(sources.toArray());
    
  • }
  • private List<String> getSources() {
  •    final Sources sources = this.proj.getLookup().lookup(Sources.class);
    
  •    final List&lt;String&gt; list = new LinkedList&lt;String&gt;();
    
  •    if (sources != null) {
    
  •        final SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
    
  •        if (groups != null) {
    
  •            for (final SourceGroup sourceGroup : groups) {
    
  •                final ClasspathInfo cpInfo = ClasspathInfo.create(
    
  •                        ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.BOOT),
    
  •                        ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.COMPILE),
    
  •                        ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.SOURCE));
    
  •                final HashSet&lt;SearchScope&gt; set = new HashSet&lt;SearchScope&gt;();
    
  •                set.add(ClassIndex.SearchScope.SOURCE);
    
  •                final Set&lt;ElementHandle&lt;TypeElement&gt;&gt; types = cpInfo.getClassIndex().getDeclaredTypes("",
    
  •                        NameKind.PREFIX, set);
    
  •                for (final ElementHandle&lt;TypeElement&gt; elementHandle : types) {
    
  •                    final JavaSource js = JavaSource.create(cpInfo);
    
  •                    try {
    
  •                        js.runUserActionTask(new Task&lt;CompilationController&gt;() {
    
  •                            @Override
    
  •                            public void run(final CompilationController control) throws Exception {
    
  •                                control.toPhase(Phase.RESOLVED);
    
  •                                // TODO: check with proper casting check.. gotta get TypeMirror of Filter
    
  •                                // interface..
    
  •                                // TypeUtilities util = control.getTypeUtilities();//.isCastable(Types., null)
    
  •                                // util.isCastable(null, null);
    
  •                                final TypeElement elem = elementHandle.resolve(control);
    
  •                                if (elem != null) {
    
  •                                    final List&lt;? extends TypeMirror&gt; interfaces = elem.getInterfaces();
    
  •                                    for (final TypeMirror typeMirror : interfaces) {
    
  •                                        final String interfaceName = typeMirror.toString();
    
  •                                        if ("com.jme3.post.Filter".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());
    
  •                                    // }
    
  •                                }
    
  •                            }
    
  •                        }, false);
    
  •                    } catch (final Exception ioe) {
    
  •                        Exceptions.printStackTrace(ioe);
    
  •                    }
    
  •                }
    
  •            }
    
  •        }
    
  •    }
    
  •    return list;
    
  • }
  • public void load(final Project proj) {
  •    this.proj = proj;
    
  •    scanFilters();
    
  • }
  • /**
  • * 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() {
  •    this.jTextField1 = new javax.swing.JTextField();
    
  •    this.jLabel1 = new javax.swing.JLabel();
    
  •    this.jScrollPane1 = new javax.swing.JScrollPane();
    
  •    this.jList1 = new javax.swing.JList();
    
  •    this.jTextField1.setText(org.openide.util.NbBundle.getMessage(NewCustomFilterVisualPanel1.class,
    
  •            "NewCustomFilterVisualPanel1.jTextField1.text")); // NOI18N
    
  •    org.openide.awt.Mnemonics.setLocalizedText(this.jLabel1, org.openide.util.NbBundle.getMessage(
    
  •            NewCustomFilterVisualPanel1.class, "NewCustomFilterVisualPanel1.jLabel1.text")); // NOI18N
    
  •    this.jList1.setModel(new javax.swing.AbstractListModel() {
    
  •        String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
    
  •        @Override
    
  •        public int getSize() {
    
  •            return this.strings.length;
    
  •        }
    
  •        @Override
    
  •        public Object getElementAt(final int i) {
    
  •            return this.strings[i];
    
  •        }
    
  •    });
    
  •    this.jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
    
  •        @Override
    
  •        public void valueChanged(final javax.swing.event.ListSelectionEvent evt) {
    
  •            updateClassName(evt);
    
  •        }
    
  •    });
    
  •    this.jScrollPane1.setViewportView(this.jList1);
    
  •    final 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(this.jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING,
    
  •                                            javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)
    
  •                                    .addComponent(this.jTextField1, javax.swing.GroupLayout.Alignment.LEADING,
    
  •                                            javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)
    
  •                                    .addComponent(this.jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 360,
    
  •                                            Short.MAX_VALUE)).addContainerGap()));
    
  •    layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
    
  •            javax.swing.GroupLayout.Alignment.TRAILING,
    
  •            layout.createSequentialGroup()
    
  •                    .addContainerGap()
    
  •                    .addComponent(this.jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE)
    
  •                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    
  •                    .addComponent(this.jLabel1)
    
  •                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
    
  •                    .addComponent(this.jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE,
    
  •                            javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
    
  •                    .addContainerGap()));
    
  • }// </editor-fold>//GEN-END:initComponents
  • private void updateClassName(final javax.swing.event.ListSelectionEvent evt) {// GEN-FIRST:event_updateClassName
  •    final Object obj = this.jList1.getSelectedValue();
    
  •    if (obj != null) {
    
  •        this.jTextField1.setText(obj + "");
    
  •    }
    
  • }// GEN-LAST:event_updateClassName
  • // Variables declaration - do not modify//GEN-BEGIN:variables
    
  • private javax.swing.JLabel jLabel1;
  • private javax.swing.JList jList1;
  • private javax.swing.JScrollPane jScrollPane1;
  • private javax.swing.JTextField jTextField1;
  • // End of variables declaration//GEN-END:variables
    +}
    Index: sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterWizardAction.java
    ===================================================================
    — sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterWizardAction.java (revision 0)
    +++ sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterWizardAction.java (working copy)
    @@ -0,0 +1,168 @@
    +/*
    • Copyright © 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.filters.impl;

+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;
+
+import com.jme3.gde.core.assets.ProjectAssetManager;
+import com.jme3.gde.core.filters.actions.AbstractNewFilterWizardAction;
+import com.jme3.gde.core.filters.actions.NewFilterAction;
+import com.jme3.post.Filter;
+import com.jme3.post.FilterPostProcessor;
+
+/**

    • @author normenhansen
  • */
    +@org.openide.util.lookup.ServiceProvider(service = NewFilterAction.class)
    +public class NewCustomFilterWizardAction extends AbstractNewFilterWizardAction {
  • private WizardDescriptor.Panel[] panels;
  • public NewCustomFilterWizardAction() {
  •    this.name = "Custom Filter";
    
  • }
  • @Override
  • protected Object showWizard(final Node node) {
  •    final WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
    
  •    // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
    
  •    wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
    
  •    wizardDescriptor.setTitle("Create Custom Filter");
    
  •    wizardDescriptor.putProperty("asset_manager", node.getLookup().lookup(ProjectAssetManager.class));
    
  •    wizardDescriptor.putProperty("project", node.getLookup().lookup(ProjectAssetManager.class).getProject());
    
  •    final Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
    
  •    dialog.setVisible(true);
    
  •    dialog.toFront();
    
  •    final boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
    
  •    if (!cancelled) {
    
  •        // do something
    
  •        return wizardDescriptor;
    
  •    }
    
  •    return null;
    
  • }
  • @Override
  • protected Filter doCreateFilter(final FilterPostProcessor parent, final Object configuration) {
  •    if (configuration == null) {
    
  •        return null;
    
  •    }
    
  •    final WizardDescriptor wizardDescriptor = (WizardDescriptor) configuration;
    
  •    final ProjectAssetManager manager = (ProjectAssetManager) wizardDescriptor.getProperty("asset_manager");
    
  •    final List&lt;ClassLoader&gt; loaders = manager.getClassLoaders();
    
  •    final String className = (String) wizardDescriptor.getProperty("class_name");
    
  •    Class clazz = null;
    
  •    try {
    
  •        clazz = getClass().getClassLoader().loadClass(className);
    
  •    } catch (final ClassNotFoundException ex) {
    
  •    }
    
  •    for (final ClassLoader classLoader : loaders) {
    
  •        if (clazz == null) {
    
  •            try {
    
  •                clazz = classLoader.loadClass(className);
    
  •                break;
    
  •            } catch (final ClassNotFoundException ex) {
    
  •            }
    
  •        }
    
  •    }
    
  •    if (clazz != null) {
    
  •        try {
    
  •            final Object contr = clazz.newInstance();
    
  •            if (contr instanceof Filter) {
    
  •                return (Filter) contr;
    
  •            } else {
    
  •                DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("This is no Filter class!"));
    
  •            }
    
  •        } catch (final InstantiationException ex) {
    
  •            Exceptions.printStackTrace(ex);
    
  •            DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Error instatiating class!"));
    
  •        } catch (final 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."));
    
  •    }
    
  •    return null;
    
  • }
  • /**
  • * Initialize panels representing individual wizard's steps and sets various properties for them influencing wizard
    
  • * appearance.
    
  • */
    
  • private WizardDescriptor.Panel[] getPanels() {
  •    if (this.panels == null) {
    
  •        this.panels = new WizardDescriptor.Panel[] { new NewCustomFilterWizardPanel1() };
    
  •        final String[] steps = new String[this.panels.length];
    
  •        for (int i = 0; i &lt; this.panels.length; i++) {
    
  •            final Component c = this.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
    
  •                final JComponent jc = (JComponent) c;
    
  •                // Sets step number of a component
    
  •                // TODO if using org.openide.dialogs &gt;= 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 this.panels;
    
  • }
    +}
    Index: sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterVisualPanel1.form
    ===================================================================
    — sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterVisualPanel1.form (revision 0)
    +++ sdk/jme3-core/src/com/jme3/gde/core/filters/impl/NewCustomFilterVisualPanel1.form (working copy)
    @@ -0,0 +1,85 @@
    +<?xml version=“1.0” 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”>
  •  &lt;Group type="103" groupAlignment="0" attributes="0"&gt;
    
  •      &lt;Group type="102" alignment="1" attributes="0"&gt;
    
  •          &lt;EmptySpace max="-2" attributes="0"/&gt;
    
  •          &lt;Group type="103" groupAlignment="1" attributes="0"&gt;
    
  •              &lt;Component id="jScrollPane1" alignment="0" pref="360" max="32767" attributes="0"/&gt;
    
  •              &lt;Component id="jTextField1" alignment="0" pref="360" max="32767" attributes="0"/&gt;
    
  •              &lt;Component id="jLabel1" alignment="1" pref="360" max="32767" attributes="0"/&gt;
    
  •          &lt;/Group&gt;
    
  •          &lt;EmptySpace max="-2" attributes="0"/&gt;
    
  •      &lt;/Group&gt;
    
  •  &lt;/Group&gt;
    
  • </DimensionLayout>
  • <DimensionLayout dim=“1”>
  •  &lt;Group type="103" groupAlignment="0" attributes="0"&gt;
    
  •      &lt;Group type="102" alignment="1" attributes="0"&gt;
    
  •          &lt;EmptySpace max="-2" attributes="0"/&gt;
    
  •          &lt;Component id="jScrollPane1" pref="200" max="32767" attributes="0"/&gt;
    
  •          &lt;EmptySpace max="-2" attributes="0"/&gt;
    
  •          &lt;Component id="jLabel1" min="-2" max="-2" attributes="0"/&gt;
    
  •          &lt;EmptySpace max="-2" attributes="0"/&gt;
    
  •          &lt;Component id="jTextField1" min="-2" max="-2" attributes="0"/&gt;
    
  •          &lt;EmptySpace max="-2" attributes="0"/&gt;
    
  •      &lt;/Group&gt;
    
  •  &lt;/Group&gt;
    
  • </DimensionLayout>
  • </Layout>
  • <SubComponents>
  • <Component class=“javax.swing.JTextField” name=“jTextField1”>
  •  &lt;Properties&gt;
    
  •    &lt;Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"&gt;
    
  •      &lt;ResourceString bundle="com/jme3/gde/core/filters/impl/Bundle.properties" key="NewCustomFilterVisualPanel1.jTextField1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/&gt;
    
  •    &lt;/Property&gt;
    
  •  &lt;/Properties&gt;
    
  • </Component>
  • <Component class=“javax.swing.JLabel” name=“jLabel1”>
  •  &lt;Properties&gt;
    
  •    &lt;Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"&gt;
    
  •      &lt;ResourceString bundle="com/jme3/gde/core/filters/impl/Bundle.properties" key="NewCustomFilterVisualPanel1.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/&gt;
    
  •    &lt;/Property&gt;
    
  •  &lt;/Properties&gt;
    
  • </Component>
  • <Container class=“javax.swing.JScrollPane” name=“jScrollPane1”>
  •  &lt;AuxValues&gt;
    
  •    &lt;AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/&gt;
    
  •  &lt;/AuxValues&gt;
    
  •  &lt;Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/&gt;
    
  •  &lt;SubComponents&gt;
    
  •    &lt;Component class="javax.swing.JList" name="jList1"&gt;
    
  •      &lt;Properties&gt;
    
  •        &lt;Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor"&gt;
    
  •          &lt;StringArray count="5"&gt;
    
  •            &lt;StringItem index="0" value="Item 1"/&gt;
    
  •            &lt;StringItem index="1" value="Item 2"/&gt;
    
  •            &lt;StringItem index="2" value="Item 3"/&gt;
    
  •            &lt;StringItem index="3" value="Item 4"/&gt;
    
  •            &lt;StringItem index="4" value="Item 5"/&gt;
    
  •          &lt;/StringArray&gt;
    
  •        &lt;/Property&gt;
    
  •      &lt;/Properties&gt;
    
  •      &lt;Events&gt;
    
  •        &lt;EventHandler event="valueChanged" listener="javax.swing.event.ListSelectionListener" parameters="javax.swing.event.ListSelectionEvent" handler="updateClassName"/&gt;
    
  •      &lt;/Events&gt;
    
  •    &lt;/Component&gt;
    
  •  &lt;/SubComponents&gt;
    
  • </Container>
  • </SubComponents>
    +</Form>
    Index: sdk/jme3-core/src/com/jme3/gde/core/filters/impl/Bundle.properties
    ===================================================================
    — sdk/jme3-core/src/com/jme3/gde/core/filters/impl/Bundle.properties (revision 0)
    +++ sdk/jme3-core/src/com/jme3/gde/core/filters/impl/Bundle.properties (working copy)
    @@ -0,0 +1,2 @@
    +NewCustomFilterVisualPanel1.jTextField1.text=com.mycompany.mygame.MyControl
    +NewCustomFilterVisualPanel1.jLabel1.text=Class Name:
    Index: sdk/jme3-core/src/com/jme3/gde/core/filters/actions/AbstractNewFilterWizardAction.java
    ===================================================================
    — sdk/jme3-core/src/com/jme3/gde/core/filters/actions/AbstractNewFilterWizardAction.java (revision 10484)
    +++ sdk/jme3-core/src/com/jme3/gde/core/filters/actions/AbstractNewFilterWizardAction.java (working copy)
    @@ -31,6 +31,7 @@
    */
    package com.jme3.gde.core.filters.actions;

+import com.jme3.gde.core.assets.ProjectAssetManager;
import com.jme3.gde.core.filters.FilterPostProcessorNode;
import com.jme3.gde.core.scene.SceneApplication;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
@@ -51,12 +52,14 @@
/
public abstract class AbstractNewFilterWizardAction implements NewFilterAction{
protected String name = "
";

  • protected ProjectAssetManager pm;

    protected abstract Object showWizard(org.openide.nodes.Node node);

    protected abstract Filter doCreateFilter(FilterPostProcessor parent, Object configuration);

    protected Action makeAction(final FilterPostProcessorNode rootNode) {

  •    pm = rootNode.getLookup().lookup(ProjectAssetManager.class);
       return new AbstractAction(name) {
    
           public void actionPerformed(ActionEvent e) {

@H it’s better to use www.pastebin.com for such things and paste the link here. HTML can make some errors.

Is the file part of a project? If not its doesn’t have a reference to an AssetManager as there is none.