GenericObjectEditor.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 23k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    GenericObjectEditor.java
  18.  *    Copyright (C) 1999 Len Trigg
  19.  *
  20.  */
  21. package weka.gui;
  22. import weka.core.OptionHandler;
  23. import weka.core.Utils;
  24. import weka.core.Tag;
  25. import weka.core.SelectedTag;
  26. import weka.core.SerializedObject;
  27. import weka.core.Utils;
  28. import java.awt.BorderLayout;
  29. import java.awt.Component;
  30. import java.awt.Dimension;
  31. import java.awt.FontMetrics;
  32. import java.awt.GridLayout;
  33. import java.awt.Window;
  34. import java.awt.event.ActionEvent;
  35. import java.awt.event.ActionListener;
  36. import java.awt.event.ItemEvent;
  37. import java.awt.event.ItemListener;
  38. import java.awt.event.WindowAdapter;
  39. import java.awt.event.WindowEvent;
  40. import java.beans.PropertyChangeEvent;
  41. import java.beans.PropertyChangeListener;
  42. import java.beans.PropertyChangeSupport;
  43. import java.beans.PropertyEditor;
  44. import java.io.BufferedInputStream;
  45. import java.io.BufferedOutputStream;
  46. import java.io.File;
  47. import java.io.FileInputStream;
  48. import java.io.FileInputStream;
  49. import java.io.FileOutputStream;
  50. import java.io.ObjectInputStream;
  51. import java.io.ObjectOutputStream;
  52. import java.util.Properties;
  53. import java.util.StringTokenizer;
  54. import java.util.Vector;
  55. import javax.swing.BorderFactory;
  56. import javax.swing.DefaultComboBoxModel;
  57. import javax.swing.JButton;
  58. import javax.swing.JComboBox;
  59. import javax.swing.JFileChooser;
  60. import javax.swing.JFrame;
  61. import javax.swing.JOptionPane;
  62. import javax.swing.JPanel;
  63. import javax.swing.JScrollPane;
  64. /** 
  65.  * A PropertyEditor for objects that themselves have been defined as
  66.  * editable in the GenericObjectEditor configuration file, which lists
  67.  * possible values that can be selected from, and themselves configured.
  68.  * The configuration file is called "GenericObjectEditor.props" and
  69.  * may live in either the location given by "user.home" or the current
  70.  * directory (this last will take precedence), and a default properties
  71.  * file is read from the weka distribution. For speed, the properties
  72.  * file is read only once when the class is first loaded -- this may need
  73.  * to be changed if we ever end up running in a Java OS ;-).
  74.  *
  75.  * @author Len Trigg (trigg@cs.waikato.ac.nz)
  76.  * @version $Revision: 1.26 $
  77.  */
  78. public class GenericObjectEditor implements PropertyEditor {
  79.   /** The classifier being configured */
  80.   private Object m_Object;
  81.   /** Holds a copy of the current classifier that can be reverted to
  82.       if the user decides to cancel */
  83.   private Object m_Backup;
  84.   
  85.   /** Handles property change notification */
  86.   private PropertyChangeSupport m_Support = new PropertyChangeSupport(this);
  87.   /** The Class of objects being edited */
  88.   private Class m_ClassType;
  89.   /** The GUI component for editing values, created when needed */
  90.   private GOEPanel m_EditorComponent;
  91.   /** True if the GUI component is needed */
  92.   private boolean m_Enabled = true;
  93.   
  94.   /** The name of the properties file */
  95.   protected static String PROPERTY_FILE = "weka/gui/GenericObjectEditor.props";
  96.   /** Contains the editor properties */
  97.   private static Properties EDITOR_PROPERTIES;
  98.   /** Loads the configuration property file */
  99.   static {
  100.     // Allow a properties file in the current directory to override
  101.     try {
  102.       EDITOR_PROPERTIES = Utils.readProperties(PROPERTY_FILE);
  103.       java.util.Enumeration keys = 
  104. (java.util.Enumeration)EDITOR_PROPERTIES.propertyNames();
  105.       if (!keys.hasMoreElements()) {
  106. throw new Exception("Failed to read a property file for the "
  107.     +"generic object editor");
  108.       }
  109.     } catch (Exception ex) {
  110.       JOptionPane.showMessageDialog(null,
  111.           "Could not read a configuration file for the generic objectn"
  112.          +"editor. An example file is included with the Weka distribution.n"
  113.  +"This file should be named "" + PROPERTY_FILE + "" andn"
  114.  +"should be placed either in your user home (which is setn"
  115.  + "to "" + System.getProperties().getProperty("user.home") + "")n"
  116.  + "or the directory that java was started fromn",
  117.  "GenericObjectEditor",
  118.  JOptionPane.ERROR_MESSAGE);
  119.     }
  120.   }
  121.   /**
  122.    * Handles the GUI side of editing values.
  123.    */
  124.   public class GOEPanel extends JPanel implements ItemListener {
  125.     
  126.     /** The chooser component */
  127.     private JComboBox m_ObjectChooser;
  128.     
  129.     /** The component that performs classifier customization */
  130.     private PropertySheetPanel m_ChildPropertySheet;
  131.     /** The model containing the list of names to select from */
  132.     private DefaultComboBoxModel m_ObjectNames;
  133.     /** Open object from disk */
  134.     private JButton m_OpenBut;
  135.     /** Save object to disk */
  136.     private JButton m_SaveBut;
  137.     /** ok button */
  138.     private JButton m_okBut;
  139.     
  140.     /** cancel button */
  141.     private JButton m_cancelBut;
  142.     /** The filechooser for opening and saving object files */
  143.     private JFileChooser m_FileChooser;
  144.     /** Creates the GUI editor component */
  145.     public GOEPanel() {
  146.       m_Backup = copyObject(m_Object);
  147.       //System.err.println("GOE()");
  148.       m_ObjectNames = new DefaultComboBoxModel(new String [0]);
  149.       m_ObjectChooser = new JComboBox(m_ObjectNames);
  150.       m_ObjectChooser.setEditable(false);
  151.       m_ChildPropertySheet = new PropertySheetPanel();
  152.       m_ChildPropertySheet.addPropertyChangeListener(
  153.       new PropertyChangeListener() {
  154. public void propertyChange(PropertyChangeEvent evt) {
  155.   m_Support.firePropertyChange("", null, null);
  156. }
  157.       });
  158.       m_OpenBut = new JButton("Open...");
  159.       m_OpenBut.setToolTipText("Load a configured object");
  160.       m_OpenBut.setEnabled(true);
  161.       m_OpenBut.addActionListener(new ActionListener() {
  162. public void actionPerformed(ActionEvent e) {
  163.   Object object = openObject();
  164.           if (object != null) {
  165.             // setValue takes care of: Making sure obj is of right type,
  166.             // and firing property change.
  167.             setValue(object);
  168.             // Need a second setValue to get property values filled in OK.
  169.             // Not sure why.
  170.             setValue(object);
  171.           }
  172. }
  173.       });
  174.       m_SaveBut = new JButton("Save...");
  175.       m_SaveBut.setToolTipText("Save the current configured object");
  176.       m_SaveBut.setEnabled(true);
  177.       m_SaveBut.addActionListener(new ActionListener() {
  178. public void actionPerformed(ActionEvent e) {
  179.   saveObject(m_Object);
  180. }
  181.       });
  182.       m_okBut = new JButton("OK");
  183.       m_okBut.setEnabled(true);
  184.       m_okBut.addActionListener(new ActionListener() {
  185. public void actionPerformed(ActionEvent e) {
  186.   m_Backup = copyObject(m_Object);
  187.   if ((getTopLevelAncestor() != null)
  188.       && (getTopLevelAncestor() instanceof Window)) {
  189.     Window w = (Window) getTopLevelAncestor();
  190.     w.dispose();
  191.   }
  192. }
  193.       });
  194.       m_cancelBut = new JButton("Cancel");
  195.       m_cancelBut.setEnabled(true);
  196.       m_cancelBut.addActionListener(new ActionListener() {
  197. public void actionPerformed(ActionEvent e) {
  198.   if (m_Backup != null) {
  199.     m_Object = copyObject(m_Backup);
  200.     setObject(m_Object);
  201.     updateClassType();
  202.     updateChooser();
  203.     updateChildPropertySheet();
  204.   }
  205.   if ((getTopLevelAncestor() != null)
  206.       && (getTopLevelAncestor() instanceof Window)) {
  207.     Window w = (Window) getTopLevelAncestor();
  208.     w.dispose();
  209.   }
  210. }
  211.       });
  212.       
  213.       setLayout(new BorderLayout());
  214.       add(m_ObjectChooser, BorderLayout.NORTH);
  215.       add(m_ChildPropertySheet, BorderLayout.CENTER);
  216.       // Since we resize to the size of the property sheet, a scrollpane isn't
  217.       // typically needed
  218.       // add(new JScrollPane(m_ChildPropertySheet), BorderLayout.CENTER);
  219.       JPanel okcButs = new JPanel();
  220.       okcButs.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  221.       okcButs.setLayout(new GridLayout(1, 4, 5, 5));
  222.       okcButs.add(m_OpenBut);
  223.       okcButs.add(m_SaveBut);
  224.       okcButs.add(m_okBut);
  225.       okcButs.add(m_cancelBut);
  226.       add(okcButs, BorderLayout.SOUTH);
  227.       
  228.       if (m_ClassType != null) {
  229. updateClassType();
  230. updateChooser();
  231. updateChildPropertySheet();
  232.       }
  233.       m_ObjectChooser.addItemListener(this);
  234.     }
  235.     /**
  236.      * Opens an object from a file selected by the user.
  237.      * 
  238.      * @return the loaded object, or null if the operation was cancelled
  239.      */
  240.     protected Object openObject() {
  241.       if (m_FileChooser == null) {
  242.         createFileChooser();
  243.       }
  244.       int returnVal = m_FileChooser.showOpenDialog(this);
  245.       if (returnVal == JFileChooser.APPROVE_OPTION) {
  246. File selected = m_FileChooser.getSelectedFile();
  247. try {
  248.   ObjectInputStream oi = new ObjectInputStream(new BufferedInputStream(new FileInputStream(selected)));
  249.           Object obj = oi.readObject();
  250.           oi.close();
  251.           if (!m_ClassType.isAssignableFrom(obj.getClass())) {
  252.             throw new Exception("Object not of type: " + m_ClassType.getName());
  253.           }
  254.           return obj;
  255. } catch (Exception ex) {
  256.   JOptionPane.showMessageDialog(this,
  257. "Couldn't read object: "
  258. + selected.getName() 
  259. + "n" + ex.getMessage(),
  260. "Open object file",
  261. JOptionPane.ERROR_MESSAGE);
  262. }
  263.       }
  264.       return null;
  265.     }
  266.     /**
  267.      * Opens an object from a file selected by the user.
  268.      * 
  269.      * @return the loaded object, or null if the operation was cancelled
  270.      */
  271.     protected void saveObject(Object object) {
  272.       if (m_FileChooser == null) {
  273.         createFileChooser();
  274.       }
  275.       int returnVal = m_FileChooser.showSaveDialog(this);
  276.       if (returnVal == JFileChooser.APPROVE_OPTION) {
  277. File sFile = m_FileChooser.getSelectedFile();
  278. try {
  279.   ObjectOutputStream oo = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(sFile)));
  280.           oo.writeObject(object);
  281.           oo.close();
  282. } catch (Exception ex) {
  283.   JOptionPane.showMessageDialog(this,
  284. "Couldn't write to file: "
  285. + sFile.getName() 
  286. + "n" + ex.getMessage(),
  287. "Save object",
  288. JOptionPane.ERROR_MESSAGE);
  289. }
  290.       }
  291.     }
  292.     protected void createFileChooser() {
  293.       m_FileChooser = new JFileChooser(new File(System.getProperty("user.dir")));
  294.       m_FileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  295.     }
  296.     /**
  297.      * Makes a copy of an object using serialization
  298.      * @param source the object to copy
  299.      * @return a copy of the source object
  300.      */
  301.     protected Object copyObject(Object source) {
  302.       Object result = null;
  303.       try {
  304.         SerializedObject so = new SerializedObject(source);
  305. result = so.getObject();
  306.       } catch (Exception ex) {
  307. System.err.println("GenericObjectEditor: Problem making backup object");
  308. System.err.print(ex);
  309.       }
  310.       return result;
  311.     }
  312.     /** 
  313.      * This is used to hook an action listener to the ok button
  314.      * @param a The action listener.
  315.      */
  316.     public void addOkListener(ActionListener a) {
  317.       m_okBut.addActionListener(a);
  318.     }
  319.     /**
  320.      * This is used to hook an action listener to the cancel button
  321.      * @param a The action listener.
  322.      */
  323.     public void addCancelListener(ActionListener a) {
  324.       m_cancelBut.addActionListener(a);
  325.     }
  326.     
  327.     /**
  328.      * This is used to remove an action listener from the ok button
  329.      * @param a The action listener
  330.      */
  331.     public void removeOkListener(ActionListener a) {
  332.       m_okBut.removeActionListener(a);
  333.     }
  334.     /**
  335.      * This is used to remove an action listener from the cancel button
  336.      * @param a The action listener
  337.      */
  338.     public void removeCancelListener(ActionListener a) {
  339.       m_cancelBut.removeActionListener(a);
  340.     }
  341.      
  342.     /** Called when the class of object being edited changes. */
  343.     protected void updateClassType() {
  344.       
  345.       Vector classes = getClassesFromProperties();
  346.       m_ObjectChooser.setModel(new DefaultComboBoxModel(classes));
  347.       if (classes.size() > 0) {
  348. add(m_ObjectChooser, BorderLayout.NORTH);
  349.       } else {
  350. remove(m_ObjectChooser);
  351.       }
  352.     }
  353.     /** Called to update the list of values to be selected from */
  354.     protected void updateChooser() {
  355.       //System.err.println("GOE::updateChooser()");
  356.       String objectName = m_Object.getClass().getName();
  357.       boolean found = false;
  358.       for (int i = 0; i < m_ObjectNames.getSize(); i++) {
  359. if (objectName.equals((String)m_ObjectNames.getElementAt(i))) {
  360.   found = true;
  361.   break;
  362. }
  363.       }
  364.       if (!found) {
  365. m_ObjectNames.addElement(objectName);
  366.       }
  367.       m_ObjectChooser.setSelectedItem(objectName);
  368.     }
  369.     /** Updates the child property sheet, and creates if needed */
  370.     public void updateChildPropertySheet() {
  371.       //System.err.println("GOE::updateChildPropertySheet()");
  372.       // Set the object as the target of the propertysheet
  373.       m_ChildPropertySheet.setTarget(m_Object);
  374.       // Adjust size of containing window if possible
  375.       if ((getTopLevelAncestor() != null)
  376.   && (getTopLevelAncestor() instanceof Window)) {
  377. ((Window) getTopLevelAncestor()).pack();
  378.       }
  379.     }
  380.     /**
  381.      * When the chooser selection is changed, ensures that the Object
  382.      * is changed appropriately.
  383.      *
  384.      * @param e a value of type 'ItemEvent'
  385.      */
  386.     public void itemStateChanged(ItemEvent e) {
  387.       //System.err.println("GOE::itemStateChanged()");
  388.       if ((e.getSource() == m_ObjectChooser)
  389.   && (e.getStateChange() == ItemEvent.SELECTED)){
  390. String className = (String)m_ObjectChooser
  391.      .getSelectedItem();
  392. try {
  393.   //System.err.println("Setting object from chooser");
  394.   setObject((Object)Class
  395.     .forName(className)
  396.     .newInstance());
  397.   //System.err.println("done setting object from chooser");
  398. } catch (Exception ex) {
  399.   m_ObjectChooser.hidePopup();
  400.   m_ObjectChooser.setSelectedIndex(0);
  401.   JOptionPane.showMessageDialog(this,
  402. "Could not create an example ofn"
  403. + className + "n"
  404. + "from the current classpath",
  405. "GenericObjectEditor",
  406. JOptionPane.ERROR_MESSAGE);
  407. }
  408.       }
  409.     }
  410.   }
  411.   /** Called when the class of object being edited changes. */
  412.   protected Vector getClassesFromProperties() {
  413.     
  414.     Vector classes = new Vector();
  415.     String className = m_ClassType.getName();
  416.     String typeOptions = EDITOR_PROPERTIES.getProperty(className);
  417.     if (typeOptions == null) {
  418.       System.err.println("Warning: No configuration property found inn"
  419.  + PROPERTY_FILE + "n"
  420.  + "for " + className);
  421.     } else {
  422.       StringTokenizer st = new StringTokenizer(typeOptions, ", ");
  423.       while (st.hasMoreTokens()) {
  424. String current = st.nextToken().trim();
  425. if (false) {
  426.   // Verify that class names are OK. Slow -- with Java2 we could
  427.   // try Class.forName(current, false, getClass().getClassLoader());
  428.   try {
  429.     Class c = Class.forName(current);
  430.     classes.addElement(current);
  431.   } catch (Exception ex) {
  432.     System.err.println("Couldn't find class with name" + current);
  433.   }
  434. } else {
  435.   classes.addElement(current);
  436. }
  437.       }
  438.     }
  439.     return classes;
  440.   }
  441.   /**
  442.    * Sets whether the editor is "enabled", meaning that the current
  443.    * values will be painted.
  444.    *
  445.    * @param newVal a value of type 'boolean'
  446.    */
  447.   public void setEnabled(boolean newVal) {
  448.     if (newVal != m_Enabled) {
  449.       m_Enabled = newVal;
  450.       /*
  451.       if (m_EditorComponent != null) {
  452. m_EditorComponent.setEnabled(m_Enabled);
  453.       }
  454.       */
  455.     }
  456.   }
  457.   
  458.   /**
  459.    * Sets the class of values that can be edited.
  460.    *
  461.    * @param type a value of type 'Class'
  462.    */
  463.   public void setClassType(Class type) {
  464.     //System.err.println("setClassType("
  465.     //        + (type == null? "<null>" : type.getName()) + ")");
  466.     m_ClassType = type;
  467.     if (m_EditorComponent != null) {
  468.       m_EditorComponent.updateClassType();
  469.     }
  470.   }
  471.   /**
  472.    * Sets the current object to be the default, taken as the first item in
  473.    * the chooser
  474.    */
  475.   public void setDefaultValue() {
  476.     if (m_ClassType == null) {
  477.       System.err.println("No ClassType set up for GenericObjectEditor!!");
  478.       return;
  479.     }
  480.     Vector v = getClassesFromProperties();
  481.     try {
  482.       if (v.size() > 0) {
  483. setObject((Object)Class.forName((String)v.elementAt(0)).newInstance());
  484.       }
  485.     } catch (Exception ex) {
  486.     }
  487.   }
  488.   
  489.   /**
  490.    * Sets the current Object. If the Object is in the
  491.    * Object chooser, this becomes the selected item (and added
  492.    * to the chooser if necessary).
  493.    *
  494.    * @param o an object that must be a Object.
  495.    */
  496.   public void setValue(Object o) {
  497.     //System.err.println("setValue()");
  498.     if (m_ClassType == null) {
  499.       System.err.println("No ClassType set up for GenericObjectEditor!!");
  500.       return;
  501.     }
  502.     if (!m_ClassType.isAssignableFrom(o.getClass())) {
  503.       System.err.println("setValue object not of correct type!");
  504.       return;
  505.     }
  506.     
  507.     setObject((Object)o);
  508.       
  509.     if (m_EditorComponent != null) {
  510.       m_EditorComponent.updateChooser();
  511.     }
  512.   }
  513.   /**
  514.    * Sets the current Object, but doesn't worry about updating
  515.    * the state of the Object chooser.
  516.    *
  517.    * @param c a value of type 'Object'
  518.    */
  519.   private void setObject(Object c) {
  520.     // This should really call equals() for comparison.
  521.     boolean trueChange = (c != getValue());
  522.     /*
  523.     System.err.println("Didn't even try to make a Object copy!! "
  524.        + "(using original)");
  525.     */
  526.     m_Backup = m_Object;
  527.     m_Object = c;
  528.     if (m_EditorComponent != null) {
  529.       m_EditorComponent.updateChildPropertySheet();
  530.       if (trueChange) {
  531. m_Support.firePropertyChange("", null, null);
  532.       }
  533.     }
  534.   }
  535.   
  536.   /**
  537.    * Gets the current Object.
  538.    *
  539.    * @return the current Object
  540.    */
  541.   public Object getValue() {
  542.     //System.err.println("getValue()");
  543.     return m_Object;
  544.   }
  545.   
  546.   /**
  547.    * Supposedly returns an initialization string to create a Object
  548.    * identical to the current one, including it's state, but this doesn't
  549.    * appear possible given that the initialization string isn't supposed to
  550.    * contain multiple statements.
  551.    *
  552.    * @return the java source code initialisation string
  553.    */
  554.   public String getJavaInitializationString() {
  555.     return "new " + m_Object.getClass().getName() + "()";
  556.   }
  557.   /**
  558.    * Returns true to indicate that we can paint a representation of the
  559.    * Object.
  560.    *
  561.    * @return true
  562.    */
  563.   public boolean isPaintable() {
  564.     return true;
  565.   }
  566.   /**
  567.    * Paints a representation of the current Object.
  568.    *
  569.    * @param gfx the graphics context to use
  570.    * @param box the area we are allowed to paint into
  571.    */
  572.   public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
  573.     if (m_Enabled && m_Object != null) {
  574.       String rep = m_Object.getClass().getName();
  575.       int dotPos = rep.lastIndexOf('.');
  576.       if (dotPos != -1) {
  577. rep = rep.substring(dotPos + 1);
  578.       }
  579.       if (m_Object instanceof OptionHandler) {
  580. rep += " " + Utils.joinOptions(((OptionHandler)m_Object)
  581.        .getOptions());
  582.       }
  583.       FontMetrics fm = gfx.getFontMetrics();
  584.       int vpad = (box.height - fm.getHeight()) / 2;
  585.       gfx.drawString(rep, 2, fm.getHeight() + vpad);
  586.     } else {
  587.     }
  588.   }
  589.   /**
  590.    * Returns null as we don't support getting/setting values as text.
  591.    *
  592.    * @return null
  593.    */
  594.   public String getAsText() {
  595.     return null;
  596.   }
  597.   /**
  598.    * Returns null as we don't support getting/setting values as text. 
  599.    *
  600.    * @param text the text value
  601.    * @exception IllegalArgumentException as we don't support
  602.    * getting/setting values as text.
  603.    */
  604.   public void setAsText(String text) throws IllegalArgumentException {
  605.     throw new IllegalArgumentException(text);
  606.   }
  607.   /**
  608.    * Returns null as we don't support getting values as tags.
  609.    *
  610.    * @return null
  611.    */
  612.   public String[] getTags() {
  613.     return null;
  614.   }
  615.   /**
  616.    * Returns true because we do support a custom editor.
  617.    *
  618.    * @return true
  619.    */
  620.   public boolean supportsCustomEditor() {
  621.     return true;
  622.   }
  623.   
  624.   /**
  625.    * Returns the array editing component.
  626.    *
  627.    * @return a value of type 'java.awt.Component'
  628.    */
  629.   public java.awt.Component getCustomEditor() {
  630.     //System.err.println("getCustomEditor()");
  631.     if (m_EditorComponent == null) {
  632.       //System.err.println("creating new editing component");
  633.       m_EditorComponent = new GOEPanel();
  634.     }
  635.     return m_EditorComponent;
  636.   }
  637.   /**
  638.    * Adds a PropertyChangeListener who will be notified of value changes.
  639.    *
  640.    * @param l a value of type 'PropertyChangeListener'
  641.    */
  642.   public void addPropertyChangeListener(PropertyChangeListener l) {
  643.     m_Support.addPropertyChangeListener(l);
  644.   }
  645.   /**
  646.    * Removes a PropertyChangeListener.
  647.    *
  648.    * @param l a value of type 'PropertyChangeListener'
  649.    */
  650.   public void removePropertyChangeListener(PropertyChangeListener l) {
  651.     m_Support.removePropertyChangeListener(l);
  652.   }
  653.   /**
  654.    * Tests out the Object editor from the command line.
  655.    *
  656.    * @param args may contain the class name of a Object to edit
  657.    */
  658.   public static void main(String [] args) {
  659.     try {
  660.       System.err.println("---Registering Weka Editors---");
  661.       java.beans.PropertyEditorManager
  662. .registerEditor(weka.experiment.ResultProducer.class,
  663. GenericObjectEditor.class);
  664.       java.beans.PropertyEditorManager
  665. .registerEditor(weka.experiment.SplitEvaluator.class,
  666. GenericObjectEditor.class);
  667.       java.beans.PropertyEditorManager
  668. .registerEditor(weka.classifiers.Classifier.class,
  669. GenericObjectEditor.class);
  670.       java.beans.PropertyEditorManager
  671. .registerEditor(weka.attributeSelection.ASEvaluation.class,
  672. GenericObjectEditor.class);
  673.       java.beans.PropertyEditorManager
  674. .registerEditor(weka.attributeSelection.ASSearch.class,
  675. GenericObjectEditor.class);
  676.       java.beans.PropertyEditorManager
  677. .registerEditor(SelectedTag.class,
  678. SelectedTagEditor.class);
  679.       java.beans.PropertyEditorManager
  680. .registerEditor(java.io.File.class,
  681. FileEditor.class);
  682.       GenericObjectEditor ce = new GenericObjectEditor();
  683.       ce.setClassType(weka.filters.Filter.class);
  684.       Object initial = new weka.filters.AddFilter();
  685.       if (args.length > 0) {
  686. initial = (Object)Class.forName(args[0]).newInstance();
  687.       }
  688.       ce.setValue(initial);
  689.       PropertyDialog pd = new PropertyDialog(ce, 100, 100);
  690.       pd.addWindowListener(new WindowAdapter() {
  691. public void windowClosing(WindowEvent e) {
  692.   PropertyEditor pe = ((PropertyDialog)e.getSource()).getEditor();
  693.   Object c = (Object)pe.getValue();
  694.   String options = "";
  695.   if (c instanceof OptionHandler) {
  696.     options = Utils.joinOptions(((OptionHandler)c).getOptions());
  697.   }
  698.   System.out.println(c.getClass().getName() + " " + options);
  699.   System.exit(0);
  700. }
  701.       });
  702.     } catch (Exception ex) {
  703.       ex.printStackTrace();
  704.       System.err.println(ex.getMessage());
  705.     }
  706.   }
  707. }