Source Code Cross Referenced for GenericObjectEditor.java in  » Science » weka » weka » gui » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » weka » weka.gui 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *    This program is free software; you can redistribute it and/or modify
0003:         *    it under the terms of the GNU General Public License as published by
0004:         *    the Free Software Foundation; either version 2 of the License, or
0005:         *    (at your option) any later version.
0006:         *
0007:         *    This program is distributed in the hope that it will be useful,
0008:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0009:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0010:         *    GNU General Public License for more details.
0011:         *
0012:         *    You should have received a copy of the GNU General Public License
0013:         *    along with this program; if not, write to the Free Software
0014:         *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0015:         */
0016:
0017:        /*
0018:         *    GenericObjectEditor.java
0019:         *    Copyright (C) 2002 University of Waikato, Hamilton, New Zealand
0020:         *
0021:         */
0022:
0023:        package weka.gui;
0024:
0025:        import weka.core.Capabilities;
0026:        import weka.core.CapabilitiesHandler;
0027:        import weka.core.ClassDiscovery;
0028:        import weka.core.OptionHandler;
0029:        import weka.core.SerializedObject;
0030:        import weka.core.Utils;
0031:        import weka.core.Capabilities.Capability;
0032:        import weka.gui.CheckBoxList.CheckBoxListModel;
0033:
0034:        import java.awt.BorderLayout;
0035:        import java.awt.Component;
0036:        import java.awt.Dimension;
0037:        import java.awt.FlowLayout;
0038:        import java.awt.FontMetrics;
0039:        import java.awt.GridLayout;
0040:        import java.awt.Window;
0041:        import java.awt.event.ActionEvent;
0042:        import java.awt.event.ActionListener;
0043:        import java.awt.event.WindowAdapter;
0044:        import java.awt.event.WindowEvent;
0045:        import java.beans.PropertyChangeEvent;
0046:        import java.beans.PropertyChangeListener;
0047:        import java.beans.PropertyChangeSupport;
0048:        import java.beans.PropertyEditor;
0049:        import java.beans.PropertyEditorManager;
0050:        import java.io.BufferedInputStream;
0051:        import java.io.BufferedOutputStream;
0052:        import java.io.File;
0053:        import java.io.FileInputStream;
0054:        import java.io.FileOutputStream;
0055:        import java.io.ObjectInputStream;
0056:        import java.io.ObjectOutputStream;
0057:        import java.lang.reflect.Array;
0058:        import java.util.Enumeration;
0059:        import java.util.Hashtable;
0060:        import java.util.Properties;
0061:        import java.util.StringTokenizer;
0062:        import java.util.Vector;
0063:
0064:        import javax.swing.BorderFactory;
0065:        import javax.swing.JButton;
0066:        import javax.swing.JDialog;
0067:        import javax.swing.JFileChooser;
0068:        import javax.swing.JLabel;
0069:        import javax.swing.JOptionPane;
0070:        import javax.swing.JPanel;
0071:        import javax.swing.JPopupMenu;
0072:        import javax.swing.JScrollPane;
0073:        import javax.swing.JTree;
0074:        import javax.swing.event.TreeSelectionEvent;
0075:        import javax.swing.event.TreeSelectionListener;
0076:        import javax.swing.tree.DefaultMutableTreeNode;
0077:        import javax.swing.tree.TreePath;
0078:        import javax.swing.tree.TreeSelectionModel;
0079:
0080:        /**
0081:         * A PropertyEditor for objects. It can be used either in a static or a dynamic
0082:         * way. <br>
0083:         * <br>
0084:         * In the <b>static</b> way (<code>USE_DYNAMIC</code> is <code>false</code>) the
0085:         * objects have been defined as editable in the GenericObjectEditor
0086:         * configuration file, which lists possible values that can be selected from,
0087:         * and themselves configured. The configuration file is called
0088:         * "GenericObjectEditor.props" and may live in either the location given by
0089:         * "user.home" or the current directory (this last will take precedence), and a
0090:         * default properties file is read from the Weka distribution. For speed, the
0091:         * properties file is read only once when the class is first loaded -- this may
0092:         * need to be changed if we ever end up running in a Java OS ;-). <br>
0093:         * <br>
0094:         * If it is used in a <b>dynamic</b> way (the <code>UseDynamic</code> property 
0095:         * of the GenericPropertiesCreator props file is set to <code>true</code>) 
0096:         * then the classes to list are discovered by the 
0097:         * <code>GenericPropertiesCreator</code> class (it checks the complete classpath). 
0098:         * 
0099:         * @see GenericPropertiesCreator
0100:         * @see GenericPropertiesCreator#useDynamic()
0101:         * @see GenericPropertiesCreator#CREATOR_FILE
0102:         * @see weka.core.ClassDiscovery
0103:         * 
0104:         * @author Len Trigg (trigg@cs.waikato.ac.nz)
0105:         * @author Xin Xu (xx5@cs.waikato.ac.nz)
0106:         * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
0107:         * @author FracPete (fracpete at waikato dot ac dot nz)
0108:         * @version $Revision: 1.57 $
0109:         */
0110:        public class GenericObjectEditor implements  PropertyEditor,
0111:                CustomPanelSupplier {
0112:
0113:            /** The object being configured */
0114:            protected Object m_Object;
0115:
0116:            /** Holds a copy of the current object that can be reverted to
0117:                if the user decides to cancel */
0118:            protected Object m_Backup;
0119:
0120:            /** Handles property change notification */
0121:            protected PropertyChangeSupport m_Support = new PropertyChangeSupport(
0122:                    this );
0123:
0124:            /** The Class of objects being edited */
0125:            protected Class m_ClassType;
0126:
0127:            /** The model containing the list of names to select from */
0128:            protected Hashtable m_ObjectNames;
0129:
0130:            /** The GUI component for editing values, created when needed */
0131:            protected GOEPanel m_EditorComponent;
0132:
0133:            /** True if the GUI component is needed */
0134:            protected boolean m_Enabled = true;
0135:
0136:            /** The name of the properties file */
0137:            protected static String PROPERTY_FILE = "weka/gui/GenericObjectEditor.props";
0138:
0139:            /** Contains the editor properties */
0140:            protected static Properties EDITOR_PROPERTIES;
0141:
0142:            /** the properties files containing the class/editor mappings */
0143:            public static final String GUIEDITORS_PROPERTY_FILE = "weka/gui/GUIEditors.props";
0144:
0145:            /** The tree node of the current object so we can re-select it for the user */
0146:            protected GOETreeNode m_treeNodeOfCurrentObject;
0147:
0148:            /** The property panel created for the objects */
0149:            protected PropertyPanel m_ObjectPropertyPanel;
0150:
0151:            /** whether the class can be changed */
0152:            protected boolean m_canChangeClassInDialog;
0153:
0154:            /** whether the Weka Editors were already registered */
0155:            protected static boolean m_EditorsRegistered;
0156:
0157:            /** for filtering the tree based on the Capabilities of the leaves */
0158:            protected Capabilities m_CapabilitiesFilter = null;
0159:
0160:            /** 
0161:             * Loads the configuration property file (USE_DYNAMIC is FALSE) or determines
0162:             * the classes dynamically (USE_DYNAMIC is TRUE)
0163:             * @see #USE_DYNAMIC
0164:             * @see GenericPropertiesCreator
0165:             */
0166:            static {
0167:
0168:                try {
0169:                    GenericPropertiesCreator creator = new GenericPropertiesCreator();
0170:
0171:                    // dynamic approach?
0172:                    if (creator.useDynamic()) {
0173:                        try {
0174:                            creator.execute(false);
0175:                            EDITOR_PROPERTIES = creator.getOutputProperties();
0176:                        } catch (Exception e) {
0177:                            JOptionPane
0178:                                    .showMessageDialog(
0179:                                            null,
0180:                                            "Could not determine the properties for the generic object\n"
0181:                                                    + "editor. This exception was produced:\n"
0182:                                                    + e.toString(),
0183:                                            "GenericObjectEditor",
0184:                                            JOptionPane.ERROR_MESSAGE);
0185:                        }
0186:                    } else {
0187:                        // Allow a properties file in the current directory to override
0188:                        try {
0189:                            EDITOR_PROPERTIES = Utils
0190:                                    .readProperties(PROPERTY_FILE);
0191:                            java.util.Enumeration keys = (java.util.Enumeration) EDITOR_PROPERTIES
0192:                                    .propertyNames();
0193:                            if (!keys.hasMoreElements()) {
0194:                                throw new Exception(
0195:                                        "Failed to read a property file for the "
0196:                                                + "generic object editor");
0197:                            }
0198:                        } catch (Exception ex) {
0199:                            JOptionPane
0200:                                    .showMessageDialog(
0201:                                            null,
0202:                                            "Could not read a configuration file for the generic object\n"
0203:                                                    + "editor. An example file is included with the Weka distribution.\n"
0204:                                                    + "This file should be named \""
0205:                                                    + PROPERTY_FILE
0206:                                                    + "\" and\n"
0207:                                                    + "should be placed either in your user home (which is set\n"
0208:                                                    + "to \""
0209:                                                    + System
0210:                                                            .getProperties()
0211:                                                            .getProperty(
0212:                                                                    "user.home")
0213:                                                    + "\")\n"
0214:                                                    + "or the directory that java was started from\n",
0215:                                            "GenericObjectEditor",
0216:                                            JOptionPane.ERROR_MESSAGE);
0217:                        }
0218:                    }
0219:                } catch (Exception e) {
0220:                    JOptionPane.showMessageDialog(null,
0221:                            "Could not initialize the GenericPropertiesCreator. "
0222:                                    + "This exception was produced:\n"
0223:                                    + e.toString(), "GenericObjectEditor",
0224:                            JOptionPane.ERROR_MESSAGE);
0225:                }
0226:            }
0227:
0228:            /**
0229:             * A specialized TreeNode for supporting filtering via Capabilities
0230:             */
0231:            public class GOETreeNode extends DefaultMutableTreeNode {
0232:
0233:                /** for serialization */
0234:                static final long serialVersionUID = -1707872446682150133L;
0235:
0236:                /** color for "no support" */
0237:                public final static String NO_SUPPORT = "red";
0238:
0239:                /** color for "maybe support" */
0240:                public final static String MAYBE_SUPPORT = "blue";
0241:
0242:                /** the Capabilities object to use for filtering */
0243:                protected Capabilities m_Capabilities = null;
0244:
0245:                /**
0246:                 * Creates a tree node that has no parent and no children, but which 
0247:                 * allows children.
0248:                 */
0249:                public GOETreeNode() {
0250:                    super ();
0251:                }
0252:
0253:                /**
0254:                 * Creates a tree node with no parent, no children, but which allows 
0255:                 * children, and initializes it with the specified user object.
0256:                 * 
0257:                 * @param userObject	an Object provided by the user that constitutes 
0258:                 * 				the node's data
0259:                 */
0260:                public GOETreeNode(Object userObject) {
0261:                    super (userObject);
0262:                }
0263:
0264:                /**
0265:                 * Creates a tree node with no parent, no children, initialized with the 
0266:                 * specified user object, and that allows children only if specified.
0267:
0268:                 * @param userObject	an Object provided by the user that constitutes 
0269:                 * 				the node's data
0270:                 * @param allowsChildren	if true, the node is allowed to have child nodes 
0271:                 * 				-- otherwise, it is always a leaf node
0272:                 */
0273:                public GOETreeNode(Object userObject, boolean allowsChildren) {
0274:                    super (userObject, allowsChildren);
0275:                }
0276:
0277:                /**
0278:                 * generates if necessary a Capabilities object for the given leaf
0279:                 */
0280:                protected void initCapabilities() {
0281:                    String classname;
0282:                    Class cls;
0283:                    Object obj;
0284:
0285:                    if (m_Capabilities != null)
0286:                        return;
0287:                    if (!isLeaf())
0288:                        return;
0289:
0290:                    classname = getClassnameFromPath(new TreePath(getPath()));
0291:                    try {
0292:                        cls = Class.forName(classname);
0293:                        if (!ClassDiscovery.hasInterface(
0294:                                CapabilitiesHandler.class, cls))
0295:                            return;
0296:
0297:                        obj = cls.newInstance();
0298:                        m_Capabilities = ((CapabilitiesHandler) obj)
0299:                                .getCapabilities();
0300:                    } catch (Exception e) {
0301:                        // ignore it
0302:                    }
0303:                }
0304:
0305:                /**
0306:                 * returns a string representation of this treenode
0307:                 * 
0308:                 * @return 		the text to display 
0309:                 */
0310:                public String toString() {
0311:                    String result;
0312:
0313:                    result = super .toString();
0314:
0315:                    if (m_CapabilitiesFilter != null) {
0316:                        initCapabilities();
0317:                        if (m_Capabilities != null) {
0318:                            if (m_Capabilities
0319:                                    .supportsMaybe(m_CapabilitiesFilter)
0320:                                    && !m_Capabilities
0321:                                            .supports(m_CapabilitiesFilter))
0322:                                result = "<html><font color=\"" + MAYBE_SUPPORT
0323:                                        + "\">" + result + "</font></i><html>";
0324:                            else if (!m_Capabilities
0325:                                    .supports(m_CapabilitiesFilter))
0326:                                result = "<html><font color=\"" + NO_SUPPORT
0327:                                        + "\">" + result + "</font></i><html>";
0328:                        }
0329:                    }
0330:
0331:                    return result;
0332:                }
0333:            }
0334:
0335:            /**
0336:             * A dialog for selecting Capabilities to look for in the GOE tree.
0337:             */
0338:            public class CapabilitiesFilterDialog extends JDialog {
0339:
0340:                /** for serialization */
0341:                static final long serialVersionUID = -7845503345689646266L;
0342:
0343:                /** the dialog itself */
0344:                protected JDialog m_Self;
0345:
0346:                /** the popup to display again */
0347:                protected JPopupMenu m_Popup = null;
0348:
0349:                /** the capabilities used for initializing the dialog */
0350:                protected Capabilities m_Capabilities = new Capabilities(null);
0351:
0352:                /** the label, listing the name of the superclass */
0353:                protected JLabel m_InfoLabel = new JLabel();
0354:
0355:                /** the list with all the capabilities */
0356:                protected CheckBoxList m_List = new CheckBoxList();
0357:
0358:                /** the OK button */
0359:                protected JButton m_OkButton = new JButton("OK");
0360:
0361:                /** the Cancel button */
0362:                protected JButton m_CancelButton = new JButton("Cancel");
0363:
0364:                /**
0365:                 * creates a dialog to choose Capabilities from
0366:                 */
0367:                public CapabilitiesFilterDialog() {
0368:                    super ();
0369:
0370:                    m_Self = this ;
0371:
0372:                    initGUI();
0373:                }
0374:
0375:                /**
0376:                 * sets up the GUI
0377:                 */
0378:                protected void initGUI() {
0379:                    JPanel panel;
0380:                    CheckBoxListModel model;
0381:
0382:                    setTitle("Filtering Capabilities...");
0383:                    setLayout(new BorderLayout());
0384:
0385:                    panel = new JPanel(new BorderLayout());
0386:                    panel
0387:                            .setBorder(BorderFactory.createEmptyBorder(5, 5, 5,
0388:                                    5));
0389:                    getContentPane().add(panel, BorderLayout.NORTH);
0390:                    m_InfoLabel
0391:                            .setText("<html>"
0392:                                    + m_ClassType.getName().replaceAll(".*\\.",
0393:                                            "")
0394:                                    + "s"
0395:                                    + " have to support <i>at least</i> the following capabilities <br>"
0396:                                    + "(the ones highlighted <font color=\""
0397:                                    + GOETreeNode.NO_SUPPORT
0398:                                    + "\">"
0399:                                    + GOETreeNode.NO_SUPPORT
0400:                                    + "</font> don't meet these requirements <br>"
0401:                                    + "the ones highlighted  <font color=\""
0402:                                    + GOETreeNode.MAYBE_SUPPORT + "\">"
0403:                                    + GOETreeNode.MAYBE_SUPPORT
0404:                                    + "</font> possibly meet them):"
0405:                                    + "</html>");
0406:                    panel.add(m_InfoLabel, BorderLayout.CENTER);
0407:
0408:                    // list
0409:                    getContentPane().add(new JScrollPane(m_List),
0410:                            BorderLayout.CENTER);
0411:                    model = (CheckBoxListModel) m_List.getModel();
0412:                    for (Capability cap : Capability.values())
0413:                        model.addElement(cap);
0414:
0415:                    // buttons
0416:                    panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
0417:                    getContentPane().add(panel, BorderLayout.SOUTH);
0418:
0419:                    m_OkButton.setMnemonic('O');
0420:                    m_OkButton.addActionListener(new ActionListener() {
0421:                        public void actionPerformed(ActionEvent e) {
0422:                            updateCapabilities();
0423:                            if (m_CapabilitiesFilter == null)
0424:                                m_CapabilitiesFilter = new Capabilities(null);
0425:                            m_CapabilitiesFilter.assign(m_Capabilities);
0426:                            m_Self.setVisible(false);
0427:                            showPopup();
0428:                        }
0429:                    });
0430:                    panel.add(m_OkButton);
0431:
0432:                    m_CancelButton.setMnemonic('C');
0433:                    m_CancelButton.addActionListener(new ActionListener() {
0434:                        public void actionPerformed(ActionEvent e) {
0435:                            m_Self.setVisible(false);
0436:                            showPopup();
0437:                        }
0438:                    });
0439:                    panel.add(m_CancelButton);
0440:                    pack();
0441:                }
0442:
0443:                /**
0444:                 * transfers the Capabilities object to the JList
0445:                 * 
0446:                 * @see #m_Capabilities
0447:                 * @see #m_List
0448:                 */
0449:                protected void updateList() {
0450:                    CheckBoxListModel model;
0451:
0452:                    model = (CheckBoxListModel) m_List.getModel();
0453:
0454:                    for (Capability cap : Capability.values())
0455:                        model.setChecked(model.indexOf(cap), m_Capabilities
0456:                                .handles(cap));
0457:                }
0458:
0459:                /**
0460:                 * transfers the selected Capabilities from the JList to the 
0461:                 * Capabilities object
0462:                 * 
0463:                 * @see #m_Capabilities
0464:                 * @see #m_List
0465:                 */
0466:                protected void updateCapabilities() {
0467:                    CheckBoxListModel model;
0468:
0469:                    model = (CheckBoxListModel) m_List.getModel();
0470:
0471:                    for (Capability cap : Capability.values()) {
0472:                        if (model.getChecked(model.indexOf(cap)))
0473:                            m_Capabilities.enable(cap);
0474:                        else
0475:                            m_Capabilities.disable(cap);
0476:                    }
0477:                }
0478:
0479:                /**
0480:                 * sets the initial capabilities
0481:                 * 
0482:                 * @param value the capabilities to use
0483:                 */
0484:                public void setCapabilities(Capabilities value) {
0485:                    if (value != null)
0486:                        m_Capabilities.assign(value);
0487:                    else
0488:                        m_Capabilities = new Capabilities(null);
0489:
0490:                    updateList();
0491:                }
0492:
0493:                /**
0494:                 * returns the currently selected capabilities
0495:                 * 
0496:                 * @return the currently selected capabilities
0497:                 */
0498:                public Capabilities getCapabilities() {
0499:                    return m_Capabilities;
0500:                }
0501:
0502:                /**
0503:                 * sets the JPopupMenu to display again after closing the dialog
0504:                 * 
0505:                 * @param value the JPopupMenu to display again
0506:                 */
0507:                public void setPopup(JPopupMenu value) {
0508:                    m_Popup = value;
0509:                }
0510:
0511:                /**
0512:                 * returns the currently set JPopupMenu
0513:                 * 
0514:                 * @return the current JPopupMenu
0515:                 */
0516:                public JPopupMenu getPopup() {
0517:                    return m_Popup;
0518:                }
0519:
0520:                /**
0521:                 * if a JPopupMenu is set, it is displayed again. Displaying this dialog
0522:                 * closes any JPopupMenu automatically.
0523:                 */
0524:                public void showPopup() {
0525:                    if (getPopup() != null)
0526:                        getPopup().setVisible(true);
0527:                }
0528:            }
0529:
0530:            /**
0531:             * Creates a popup menu containing a tree that is aware
0532:             * of the screen dimensions.
0533:             */
0534:            public class JTreePopupMenu extends JPopupMenu {
0535:
0536:                /** for serialization */
0537:                static final long serialVersionUID = -3404546329655057387L;
0538:
0539:                /** the popup itself */
0540:                private JPopupMenu m_Self;
0541:
0542:                /** The tree */
0543:                private JTree m_tree;
0544:
0545:                /** The scroller */
0546:                private JScrollPane m_scroller;
0547:
0548:                /** The filter button in case of CapabilitiesHandlers */
0549:                private JButton m_FilterButton = new JButton("Filter...");
0550:
0551:                /** The remove filter button in case of CapabilitiesHandlers */
0552:                private JButton m_RemoveFilterButton = new JButton(
0553:                        "Remove filter");
0554:
0555:                /** The button for closing the popup again */
0556:                private JButton m_CloseButton = new JButton("Close");
0557:
0558:                /**
0559:                 * Constructs a new popup menu.
0560:                 *
0561:                 * @param tree the tree to put in the menu
0562:                 */
0563:                public JTreePopupMenu(JTree tree) {
0564:
0565:                    m_Self = this ;
0566:
0567:                    setLayout(new BorderLayout());
0568:                    JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
0569:                    add(panel, BorderLayout.SOUTH);
0570:
0571:                    if (ClassDiscovery.hasInterface(CapabilitiesHandler.class,
0572:                            m_ClassType)) {
0573:                        // filter
0574:                        m_FilterButton.setMnemonic('F');
0575:                        m_FilterButton.addActionListener(new ActionListener() {
0576:                            public void actionPerformed(ActionEvent e) {
0577:                                if (e.getSource() == m_FilterButton) {
0578:                                    CapabilitiesFilterDialog dialog = new CapabilitiesFilterDialog();
0579:                                    dialog
0580:                                            .setCapabilities(m_CapabilitiesFilter);
0581:                                    dialog.setPopup(m_Self);
0582:                                    dialog.setVisible(true);
0583:                                    repaint();
0584:                                }
0585:                            }
0586:                        });
0587:                        panel.add(m_FilterButton);
0588:
0589:                        // remove
0590:                        m_RemoveFilterButton.setMnemonic('R');
0591:                        m_RemoveFilterButton
0592:                                .addActionListener(new ActionListener() {
0593:                                    public void actionPerformed(ActionEvent e) {
0594:                                        if (e.getSource() == m_RemoveFilterButton) {
0595:                                            m_CapabilitiesFilter = null;
0596:                                            repaint();
0597:                                        }
0598:                                    }
0599:                                });
0600:                        panel.add(m_RemoveFilterButton);
0601:                    }
0602:
0603:                    // close
0604:                    m_CloseButton.setMnemonic('C');
0605:                    m_CloseButton.addActionListener(new ActionListener() {
0606:                        public void actionPerformed(ActionEvent e) {
0607:                            if (e.getSource() == m_CloseButton) {
0608:                                m_Self.setVisible(false);
0609:                            }
0610:                        }
0611:                    });
0612:                    panel.add(m_CloseButton);
0613:
0614:                    m_tree = tree;
0615:
0616:                    JPanel treeView = new JPanel();
0617:                    treeView.setLayout(new BorderLayout());
0618:                    treeView.add(m_tree, BorderLayout.NORTH);
0619:
0620:                    // make backgrounds look the same
0621:                    treeView.setBackground(m_tree.getBackground());
0622:
0623:                    m_scroller = new JScrollPane(treeView);
0624:
0625:                    m_scroller.setPreferredSize(new Dimension(300, 400));
0626:                    m_scroller.getVerticalScrollBar().setUnitIncrement(20);
0627:
0628:                    add(m_scroller);
0629:                }
0630:
0631:                /**
0632:                 * Displays the menu, making sure it will fit on the screen.
0633:                 *
0634:                 * @param invoker the component thast invoked the menu
0635:                 * @param x the x location of the popup
0636:                 * @param y the y location of the popup
0637:                 */
0638:                public void show(Component invoker, int x, int y) {
0639:
0640:                    super .show(invoker, x, y);
0641:
0642:                    // calculate available screen area for popup
0643:                    java.awt.Point location = getLocationOnScreen();
0644:                    java.awt.Dimension screenSize = getToolkit()
0645:                            .getScreenSize();
0646:                    int maxWidth = (int) (screenSize.getWidth() - location
0647:                            .getX());
0648:                    int maxHeight = (int) (screenSize.getHeight() - location
0649:                            .getY());
0650:
0651:                    // if the part of the popup goes off the screen then resize it
0652:                    Dimension scrollerSize = m_scroller.getPreferredSize();
0653:                    int height = (int) scrollerSize.getHeight();
0654:                    int width = (int) scrollerSize.getWidth();
0655:                    if (width > maxWidth)
0656:                        width = maxWidth;
0657:                    if (height > maxHeight)
0658:                        height = maxHeight;
0659:
0660:                    // commit any size changes
0661:                    m_scroller.setPreferredSize(new Dimension(width, height));
0662:                    revalidate();
0663:                    pack();
0664:                }
0665:            }
0666:
0667:            /**
0668:             * Handles the GUI side of editing values.
0669:             */
0670:            public class GOEPanel extends JPanel {
0671:
0672:                /** for serialization */
0673:                static final long serialVersionUID = 3656028520876011335L;
0674:
0675:                /** The component that performs classifier customization */
0676:                protected PropertySheetPanel m_ChildPropertySheet;
0677:
0678:                /** The name of the current class */
0679:                protected JLabel m_ClassNameLabel;
0680:
0681:                /** Open object from disk */
0682:                protected JButton m_OpenBut;
0683:
0684:                /** Save object to disk */
0685:                protected JButton m_SaveBut;
0686:
0687:                /** ok button */
0688:                protected JButton m_okBut;
0689:
0690:                /** cancel button */
0691:                protected JButton m_cancelBut;
0692:
0693:                /** The filechooser for opening and saving object files */
0694:                protected JFileChooser m_FileChooser;
0695:
0696:                /** Creates the GUI editor component */
0697:                public GOEPanel() {
0698:
0699:                    m_Backup = copyObject(m_Object);
0700:
0701:                    m_ClassNameLabel = new JLabel("None");
0702:                    m_ClassNameLabel.setBorder(BorderFactory.createEmptyBorder(
0703:                            5, 5, 5, 5));
0704:
0705:                    m_ChildPropertySheet = new PropertySheetPanel();
0706:                    m_ChildPropertySheet
0707:                            .addPropertyChangeListener(new PropertyChangeListener() {
0708:                                public void propertyChange(
0709:                                        PropertyChangeEvent evt) {
0710:                                    m_Support
0711:                                            .firePropertyChange("", null, null);
0712:                                }
0713:                            });
0714:
0715:                    m_OpenBut = new JButton("Open...");
0716:                    m_OpenBut.setToolTipText("Load a configured object");
0717:                    m_OpenBut.setEnabled(true);
0718:                    m_OpenBut.addActionListener(new ActionListener() {
0719:                        public void actionPerformed(ActionEvent e) {
0720:                            Object object = openObject();
0721:                            if (object != null) {
0722:                                // setValue takes care of: Making sure obj is of right type,
0723:                                // and firing property change.
0724:                                setValue(object);
0725:                                // Need a second setValue to get property values filled in OK.
0726:                                // Not sure why.
0727:                                setValue(object);
0728:                            }
0729:                        }
0730:                    });
0731:
0732:                    m_SaveBut = new JButton("Save...");
0733:                    m_SaveBut
0734:                            .setToolTipText("Save the current configured object");
0735:                    m_SaveBut.setEnabled(true);
0736:                    m_SaveBut.addActionListener(new ActionListener() {
0737:                        public void actionPerformed(ActionEvent e) {
0738:                            saveObject(m_Object);
0739:                        }
0740:                    });
0741:
0742:                    m_okBut = new JButton("OK");
0743:                    m_okBut.setEnabled(true);
0744:                    m_okBut.addActionListener(new ActionListener() {
0745:                        public void actionPerformed(ActionEvent e) {
0746:
0747:                            m_Backup = copyObject(m_Object);
0748:                            if ((getTopLevelAncestor() != null)
0749:                                    && (getTopLevelAncestor() instanceof  Window)) {
0750:                                Window w = (Window) getTopLevelAncestor();
0751:                                w.dispose();
0752:                            }
0753:                        }
0754:                    });
0755:
0756:                    m_cancelBut = new JButton("Cancel");
0757:                    m_cancelBut.setEnabled(true);
0758:                    m_cancelBut.addActionListener(new ActionListener() {
0759:                        public void actionPerformed(ActionEvent e) {
0760:                            if (m_Backup != null) {
0761:
0762:                                m_Object = copyObject(m_Backup);
0763:
0764:                                // To fire property change
0765:                                m_Support.firePropertyChange("", null, null);
0766:                                m_ObjectNames = getClassesFromProperties();
0767:                                updateObjectNames();
0768:                                updateChildPropertySheet();
0769:                            }
0770:                            if ((getTopLevelAncestor() != null)
0771:                                    && (getTopLevelAncestor() instanceof  Window)) {
0772:                                Window w = (Window) getTopLevelAncestor();
0773:                                w.dispose();
0774:                            }
0775:                        }
0776:                    });
0777:
0778:                    setLayout(new BorderLayout());
0779:
0780:                    if (m_canChangeClassInDialog) {
0781:                        JButton chooseButton = createChooseClassButton();
0782:                        JPanel top = new JPanel();
0783:                        top.setLayout(new BorderLayout());
0784:                        top.setBorder(BorderFactory.createEmptyBorder(5, 5, 5,
0785:                                5));
0786:                        top.add(chooseButton, BorderLayout.WEST);
0787:                        top.add(m_ClassNameLabel, BorderLayout.CENTER);
0788:                        add(top, BorderLayout.NORTH);
0789:                    } else {
0790:                        add(m_ClassNameLabel, BorderLayout.NORTH);
0791:                    }
0792:
0793:                    add(m_ChildPropertySheet, BorderLayout.CENTER);
0794:                    // Since we resize to the size of the property sheet, a scrollpane isn't
0795:                    // typically needed
0796:                    // add(new JScrollPane(m_ChildPropertySheet), BorderLayout.CENTER);
0797:
0798:                    JPanel okcButs = new JPanel();
0799:                    okcButs.setBorder(BorderFactory.createEmptyBorder(5, 5, 5,
0800:                            5));
0801:                    okcButs.setLayout(new GridLayout(1, 4, 5, 5));
0802:                    okcButs.add(m_OpenBut);
0803:                    okcButs.add(m_SaveBut);
0804:                    okcButs.add(m_okBut);
0805:                    okcButs.add(m_cancelBut);
0806:                    add(okcButs, BorderLayout.SOUTH);
0807:
0808:                    if (m_ClassType != null) {
0809:                        m_ObjectNames = getClassesFromProperties();
0810:                        if (m_Object != null) {
0811:                            updateObjectNames();
0812:                            updateChildPropertySheet();
0813:                        }
0814:                    }
0815:                }
0816:
0817:                /**
0818:                 * Enables/disables the cancel button.
0819:                 *
0820:                 * @param flag true to enable cancel button, false
0821:                 * to disable it
0822:                 */
0823:                protected void setCancelButton(boolean flag) {
0824:
0825:                    if (m_cancelBut != null)
0826:                        m_cancelBut.setEnabled(flag);
0827:                }
0828:
0829:                /**
0830:                 * Opens an object from a file selected by the user.
0831:                 * 
0832:                 * @return the loaded object, or null if the operation was cancelled
0833:                 */
0834:                protected Object openObject() {
0835:
0836:                    if (m_FileChooser == null) {
0837:                        createFileChooser();
0838:                    }
0839:                    int returnVal = m_FileChooser.showOpenDialog(this );
0840:                    if (returnVal == JFileChooser.APPROVE_OPTION) {
0841:                        File selected = m_FileChooser.getSelectedFile();
0842:                        try {
0843:                            ObjectInputStream oi = new ObjectInputStream(
0844:                                    new BufferedInputStream(
0845:                                            new FileInputStream(selected)));
0846:                            Object obj = oi.readObject();
0847:                            oi.close();
0848:                            if (!m_ClassType.isAssignableFrom(obj.getClass())) {
0849:                                throw new Exception("Object not of type: "
0850:                                        + m_ClassType.getName());
0851:                            }
0852:                            return obj;
0853:                        } catch (Exception ex) {
0854:                            JOptionPane.showMessageDialog(this ,
0855:                                    "Couldn't read object: "
0856:                                            + selected.getName() + "\n"
0857:                                            + ex.getMessage(),
0858:                                    "Open object file",
0859:                                    JOptionPane.ERROR_MESSAGE);
0860:                        }
0861:                    }
0862:                    return null;
0863:                }
0864:
0865:                /**
0866:                 * Saves an object to a file selected by the user.
0867:                 * 
0868:                 * @param object the object to save
0869:                 */
0870:                protected void saveObject(Object object) {
0871:
0872:                    if (m_FileChooser == null) {
0873:                        createFileChooser();
0874:                    }
0875:                    int returnVal = m_FileChooser.showSaveDialog(this );
0876:                    if (returnVal == JFileChooser.APPROVE_OPTION) {
0877:                        File sFile = m_FileChooser.getSelectedFile();
0878:                        try {
0879:                            ObjectOutputStream oo = new ObjectOutputStream(
0880:                                    new BufferedOutputStream(
0881:                                            new FileOutputStream(sFile)));
0882:                            oo.writeObject(object);
0883:                            oo.close();
0884:                        } catch (Exception ex) {
0885:                            JOptionPane.showMessageDialog(this ,
0886:                                    "Couldn't write to file: "
0887:                                            + sFile.getName() + "\n"
0888:                                            + ex.getMessage(), "Save object",
0889:                                    JOptionPane.ERROR_MESSAGE);
0890:                        }
0891:                    }
0892:                }
0893:
0894:                /**
0895:                 * Creates the file chooser the user will use to save/load files with.
0896:                 */
0897:                protected void createFileChooser() {
0898:
0899:                    m_FileChooser = new JFileChooser(new File(System
0900:                            .getProperty("user.dir")));
0901:                    m_FileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
0902:                }
0903:
0904:                /**
0905:                 * Makes a copy of an object using serialization
0906:                 * @param source the object to copy
0907:                 * @return a copy of the source object
0908:                 */
0909:                protected Object copyObject(Object source) {
0910:
0911:                    Object result = null;
0912:                    try {
0913:                        result = GenericObjectEditor.this .makeCopy(source);
0914:                        setCancelButton(true);
0915:
0916:                    } catch (Exception ex) {
0917:                        setCancelButton(false);
0918:                        System.err
0919:                                .println("GenericObjectEditor: Problem making backup object");
0920:                        System.err.println(ex);
0921:                    }
0922:                    return result;
0923:                }
0924:
0925:                /**
0926:                 * Allows customization of the action label on the dialog.
0927:                 * @param newLabel the new string for the ok button
0928:                 */
0929:                public void setOkButtonText(String newLabel) {
0930:
0931:                    m_okBut.setText(newLabel);
0932:                }
0933:
0934:                /** 
0935:                 * This is used to hook an action listener to the ok button
0936:                 * @param a The action listener.
0937:                 */
0938:                public void addOkListener(ActionListener a) {
0939:
0940:                    m_okBut.addActionListener(a);
0941:                }
0942:
0943:                /**
0944:                 * This is used to hook an action listener to the cancel button
0945:                 * @param a The action listener.
0946:                 */
0947:                public void addCancelListener(ActionListener a) {
0948:
0949:                    m_cancelBut.addActionListener(a);
0950:                }
0951:
0952:                /**
0953:                 * This is used to remove an action listener from the ok button
0954:                 * @param a The action listener
0955:                 */
0956:                public void removeOkListener(ActionListener a) {
0957:
0958:                    m_okBut.removeActionListener(a);
0959:                }
0960:
0961:                /**
0962:                 * This is used to remove an action listener from the cancel button
0963:                 * @param a The action listener
0964:                 */
0965:                public void removeCancelListener(ActionListener a) {
0966:
0967:                    m_cancelBut.removeActionListener(a);
0968:                }
0969:
0970:                /** Updates the child property sheet, and creates if needed */
0971:                public void updateChildPropertySheet() {
0972:
0973:                    // Update the object name displayed
0974:                    String className = "None";
0975:                    if (m_Object != null) {
0976:                        className = m_Object.getClass().getName();
0977:                    }
0978:                    m_ClassNameLabel.setText(className);
0979:
0980:                    // Set the object as the target of the propertysheet
0981:                    m_ChildPropertySheet.setTarget(m_Object);
0982:
0983:                    // Adjust size of containing window if possible
0984:                    if ((getTopLevelAncestor() != null)
0985:                            && (getTopLevelAncestor() instanceof  Window)) {
0986:                        ((Window) getTopLevelAncestor()).pack();
0987:                    }
0988:                }
0989:            }
0990:
0991:            /**
0992:             * Default constructor.
0993:             */
0994:            public GenericObjectEditor() {
0995:
0996:                this (false);
0997:            }
0998:
0999:            /**
1000:             * Constructor that allows specifying whether it is possible
1001:             * to change the class within the editor dialog.
1002:             *
1003:             * @param canChangeClassInDialog whether the user can change the class
1004:             */
1005:            public GenericObjectEditor(boolean canChangeClassInDialog) {
1006:
1007:                m_canChangeClassInDialog = canChangeClassInDialog;
1008:            }
1009:
1010:            /**
1011:             * registers all the editors in Weka
1012:             */
1013:            public static void registerEditors() {
1014:                Properties props;
1015:                Enumeration enm;
1016:                String name;
1017:                String value;
1018:                Class baseCls;
1019:                Class cls;
1020:
1021:                if (m_EditorsRegistered)
1022:                    return;
1023:
1024:                System.err.println("---Registering Weka Editors---");
1025:                m_EditorsRegistered = true;
1026:
1027:                // load properties
1028:                try {
1029:                    props = Utils.readProperties(GUIEDITORS_PROPERTY_FILE);
1030:                } catch (Exception e) {
1031:                    props = new Properties();
1032:                    e.printStackTrace();
1033:                }
1034:
1035:                enm = props.propertyNames();
1036:                while (enm.hasMoreElements()) {
1037:                    name = enm.nextElement().toString();
1038:                    value = props.getProperty(name, "");
1039:                    try {
1040:                        // array class?
1041:                        if (name.endsWith("[]")) {
1042:                            baseCls = Class.forName(name.substring(0, name
1043:                                    .indexOf("[]")));
1044:                            cls = Array.newInstance(baseCls, 1).getClass();
1045:                        } else {
1046:                            cls = Class.forName(name);
1047:                        }
1048:                        // register
1049:                        PropertyEditorManager.registerEditor(cls, Class
1050:                                .forName(value));
1051:                    } catch (Exception e) {
1052:                        System.err.println("Problem registering " + name + "/"
1053:                                + value + ": " + e);
1054:                    }
1055:                }
1056:            }
1057:
1058:            /**
1059:             * Returns the backup object (may be null if there is no
1060:             * backup.
1061:             *
1062:             * @return the backup object
1063:             */
1064:            public Object getBackup() {
1065:                return m_Backup;
1066:            }
1067:
1068:            /**
1069:             * returns the name of the root element of the given class name, 
1070:             * <code>null</code> if it doesn't contain the separator
1071:             * 
1072:             * @param clsname the full classname
1073:             * @param separator the separator 
1074:             * @return string the root element
1075:             */
1076:            protected static String getRootFromClass(String clsname,
1077:                    String separator) {
1078:                if (clsname.indexOf(separator) > -1)
1079:                    return clsname.substring(0, clsname.indexOf(separator));
1080:                else
1081:                    return null;
1082:            }
1083:
1084:            /**
1085:             * parses the given string of classes separated by ", " and returns the
1086:             * a hashtable with as many entries as there are different root elements in 
1087:             * the class names (the key is the root element). E.g. if there's only 
1088:             * "weka." as the prefix for all classes the a hashtable of size 1 is returned. 
1089:             * if NULL is the input, then NULL is also returned.
1090:             * 
1091:             * @param classes the classnames to work on
1092:             * @return for each distinct root element in the classnames, one entry in
1093:             * the hashtable (with the root element as key)
1094:             */
1095:            public static Hashtable sortClassesByRoot(String classes) {
1096:                Hashtable roots;
1097:                Hashtable result;
1098:                Enumeration enm;
1099:                int i;
1100:                StringTokenizer tok;
1101:                String clsname;
1102:                Vector list;
1103:                HierarchyPropertyParser hpp;
1104:                String separator;
1105:                String root;
1106:                String tmpStr;
1107:
1108:                if (classes == null)
1109:                    return null;
1110:
1111:                roots = new Hashtable();
1112:                hpp = new HierarchyPropertyParser();
1113:                separator = hpp.getSeperator();
1114:
1115:                // go over all classnames and store them in the hashtable, with the
1116:                // root element as the key
1117:                tok = new StringTokenizer(classes, ", ");
1118:                while (tok.hasMoreElements()) {
1119:                    clsname = tok.nextToken();
1120:                    root = getRootFromClass(clsname, separator);
1121:                    if (root == null)
1122:                        continue;
1123:
1124:                    // already stored?
1125:                    if (!roots.containsKey(root)) {
1126:                        list = new Vector();
1127:                        roots.put(root, list);
1128:                    } else {
1129:                        list = (Vector) roots.get(root);
1130:                    }
1131:
1132:                    list.add(clsname);
1133:                }
1134:
1135:                // build result
1136:                result = new Hashtable();
1137:                enm = roots.keys();
1138:                while (enm.hasMoreElements()) {
1139:                    root = (String) enm.nextElement();
1140:                    list = (Vector) roots.get(root);
1141:                    tmpStr = "";
1142:                    for (i = 0; i < list.size(); i++) {
1143:                        if (i > 0)
1144:                            tmpStr += ",";
1145:                        tmpStr += (String) list.get(i);
1146:                    }
1147:                    result.put(root, tmpStr);
1148:                }
1149:
1150:                return result;
1151:            }
1152:
1153:            /** 
1154:             * Called when the class of object being edited changes. 
1155:             * 
1156:             * @return the hashtable containing the HierarchyPropertyParsers for the root
1157:             *         elements
1158:             */
1159:            protected Hashtable getClassesFromProperties() {
1160:
1161:                Hashtable hpps = new Hashtable();
1162:                String className = m_ClassType.getName();
1163:                Hashtable typeOptions = sortClassesByRoot(EDITOR_PROPERTIES
1164:                        .getProperty(className));
1165:                if (typeOptions == null) {
1166:                    /*
1167:                    System.err.println("Warning: No configuration property found in\n"
1168:                    	 + PROPERTY_FILE + "\n"
1169:                    	 + "for " + className);
1170:                     */
1171:                } else {
1172:                    try {
1173:                        Enumeration enm = typeOptions.keys();
1174:                        while (enm.hasMoreElements()) {
1175:                            String root = (String) enm.nextElement();
1176:                            String typeOption = (String) typeOptions.get(root);
1177:                            HierarchyPropertyParser hpp = new HierarchyPropertyParser();
1178:                            hpp.build(typeOption, ", ");
1179:                            hpps.put(root, hpp);
1180:                        }
1181:                    } catch (Exception ex) {
1182:                        System.err.println("Invalid property: " + typeOptions);
1183:                    }
1184:                }
1185:                return hpps;
1186:            }
1187:
1188:            /**
1189:             * Updates the list of selectable object names, adding any new names to the list.
1190:             */
1191:            protected void updateObjectNames() {
1192:
1193:                if (m_ObjectNames == null) {
1194:                    m_ObjectNames = getClassesFromProperties();
1195:                }
1196:
1197:                if (m_Object != null) {
1198:                    String className = m_Object.getClass().getName();
1199:                    String root = getRootFromClass(className,
1200:                            new HierarchyPropertyParser().getSeperator());
1201:                    HierarchyPropertyParser hpp = (HierarchyPropertyParser) m_ObjectNames
1202:                            .get(root);
1203:                    if (hpp != null) {
1204:                        if (!hpp.contains(className)) {
1205:                            hpp.add(className);
1206:                        }
1207:                    }
1208:                }
1209:            }
1210:
1211:            /**
1212:             * Sets whether the editor is "enabled", meaning that the current
1213:             * values will be painted.
1214:             *
1215:             * @param newVal a value of type 'boolean'
1216:             */
1217:            public void setEnabled(boolean newVal) {
1218:
1219:                if (newVal != m_Enabled) {
1220:                    m_Enabled = newVal;
1221:                }
1222:            }
1223:
1224:            /**
1225:             * Sets the class of values that can be edited.
1226:             *
1227:             * @param type a value of type 'Class'
1228:             */
1229:            public void setClassType(Class type) {
1230:
1231:                m_ClassType = type;
1232:                m_ObjectNames = getClassesFromProperties();
1233:            }
1234:
1235:            /**
1236:             * Sets the current object to be the default, taken as the first item in
1237:             * the chooser
1238:             */
1239:            public void setDefaultValue() {
1240:
1241:                if (m_ClassType == null) {
1242:                    System.err
1243:                            .println("No ClassType set up for GenericObjectEditor!!");
1244:                    return;
1245:                }
1246:
1247:                Hashtable hpps = getClassesFromProperties();
1248:                HierarchyPropertyParser hpp = null;
1249:                Enumeration enm = hpps.elements();
1250:
1251:                try {
1252:                    while (enm.hasMoreElements()) {
1253:                        hpp = (HierarchyPropertyParser) enm.nextElement();
1254:                        if (hpp.depth() > 0) {
1255:                            hpp.goToRoot();
1256:                            while (!hpp.isLeafReached())
1257:                                hpp.goToChild(0);
1258:
1259:                            String defaultValue = hpp.fullValue();
1260:                            setValue(Class.forName(defaultValue).newInstance());
1261:                        }
1262:                    }
1263:                } catch (Exception ex) {
1264:                    System.err.println("Problem loading the first class: "
1265:                            + hpp.fullValue());
1266:                    ex.printStackTrace();
1267:                }
1268:            }
1269:
1270:            /**
1271:             * Sets the current Object. If the Object is in the
1272:             * Object chooser, this becomes the selected item (and added
1273:             * to the chooser if necessary).
1274:             *
1275:             * @param o an object that must be a Object.
1276:             */
1277:            public void setValue(Object o) {
1278:
1279:                if (m_ClassType == null) {
1280:                    System.err
1281:                            .println("No ClassType set up for GenericObjectEditor!!");
1282:                    return;
1283:                }
1284:                if (!m_ClassType.isAssignableFrom(o.getClass())) {
1285:                    System.err.println("setValue object not of correct type!");
1286:                    return;
1287:                }
1288:
1289:                setObject(o);
1290:
1291:                if (m_EditorComponent != null)
1292:                    m_EditorComponent.repaint();
1293:
1294:                updateObjectNames();
1295:            }
1296:
1297:            /**
1298:             * Sets the current Object.
1299:             *
1300:             * @param c a value of type 'Object'
1301:             */
1302:            protected void setObject(Object c) {
1303:
1304:                // This should really call equals() for comparison.
1305:                boolean trueChange;
1306:                if (getValue() != null) {
1307:                    trueChange = (!c.equals(getValue()));
1308:                } else
1309:                    trueChange = true;
1310:
1311:                m_Backup = m_Object;
1312:
1313:                m_Object = c;
1314:
1315:                if (m_EditorComponent != null) {
1316:                    m_EditorComponent.updateChildPropertySheet();
1317:                }
1318:                if (trueChange) {
1319:                    m_Support.firePropertyChange("", null, null);
1320:                }
1321:            }
1322:
1323:            /**
1324:             * Gets the current Object.
1325:             *
1326:             * @return the current Object
1327:             */
1328:            public Object getValue() {
1329:
1330:                Object result = null;
1331:                try {
1332:                    result = makeCopy(m_Object);
1333:                } catch (Exception ex) {
1334:                    ex.printStackTrace();
1335:                }
1336:                return result;
1337:            }
1338:
1339:            /**
1340:             * Supposedly returns an initialization string to create a Object
1341:             * identical to the current one, including it's state, but this doesn't
1342:             * appear possible given that the initialization string isn't supposed to
1343:             * contain multiple statements.
1344:             *
1345:             * @return the java source code initialisation string
1346:             */
1347:            public String getJavaInitializationString() {
1348:
1349:                return "new " + m_Object.getClass().getName() + "()";
1350:            }
1351:
1352:            /**
1353:             * Returns true to indicate that we can paint a representation of the
1354:             * Object.
1355:             *
1356:             * @return true
1357:             */
1358:            public boolean isPaintable() {
1359:
1360:                return true;
1361:            }
1362:
1363:            /**
1364:             * Paints a representation of the current Object.
1365:             *
1366:             * @param gfx the graphics context to use
1367:             * @param box the area we are allowed to paint into
1368:             */
1369:            public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
1370:
1371:                if (m_Enabled) {
1372:                    String rep;
1373:                    if (m_Object != null) {
1374:                        rep = m_Object.getClass().getName();
1375:                    } else {
1376:                        rep = "None";
1377:                    }
1378:                    int dotPos = rep.lastIndexOf('.');
1379:                    if (dotPos != -1) {
1380:                        rep = rep.substring(dotPos + 1);
1381:                    }
1382:                    /*
1383:                    if (m_Object instanceof OptionHandler) {
1384:                    rep += " " + Utils.joinOptions(((OptionHandler)m_Object)
1385:                    		       .getOptions());
1386:                    }
1387:                     */
1388:                    java.awt.Font originalFont = gfx.getFont();
1389:                    gfx.setFont(originalFont.deriveFont(java.awt.Font.BOLD));
1390:
1391:                    FontMetrics fm = gfx.getFontMetrics();
1392:                    int vpad = (box.height - fm.getHeight()) / 2;
1393:                    gfx.drawString(rep, 2, fm.getHeight() + vpad);
1394:                    int repwidth = fm.stringWidth(rep);
1395:
1396:                    gfx.setFont(originalFont);
1397:                    if (m_Object instanceof  OptionHandler) {
1398:                        gfx.drawString(" "
1399:                                + Utils.joinOptions(((OptionHandler) m_Object)
1400:                                        .getOptions()), repwidth + 2, fm
1401:                                .getHeight()
1402:                                + vpad);
1403:                    }
1404:                }
1405:            }
1406:
1407:            /**
1408:             * Returns null as we don't support getting/setting values as text.
1409:             *
1410:             * @return null
1411:             */
1412:            public String getAsText() {
1413:
1414:                return null;
1415:            }
1416:
1417:            /**
1418:             * Returns null as we don't support getting/setting values as text. 
1419:             *
1420:             * @param text the text value
1421:             * @throws IllegalArgumentException as we don't support
1422:             * getting/setting values as text.
1423:             */
1424:            public void setAsText(String text) {
1425:
1426:                throw new IllegalArgumentException(text);
1427:            }
1428:
1429:            /**
1430:             * Returns null as we don't support getting values as tags.
1431:             *
1432:             * @return null
1433:             */
1434:            public String[] getTags() {
1435:
1436:                return null;
1437:            }
1438:
1439:            /**
1440:             * Returns true because we do support a custom editor.
1441:             *
1442:             * @return true
1443:             */
1444:            public boolean supportsCustomEditor() {
1445:
1446:                return true;
1447:            }
1448:
1449:            /**
1450:             * Returns the array editing component.
1451:             *
1452:             * @return a value of type 'java.awt.Component'
1453:             */
1454:            public java.awt.Component getCustomEditor() {
1455:
1456:                if (m_EditorComponent == null) {
1457:                    m_EditorComponent = new GOEPanel();
1458:                }
1459:                return m_EditorComponent;
1460:            }
1461:
1462:            /**
1463:             * Adds a PropertyChangeListener who will be notified of value changes.
1464:             *
1465:             * @param l a value of type 'PropertyChangeListener'
1466:             */
1467:            public void addPropertyChangeListener(PropertyChangeListener l) {
1468:
1469:                m_Support.addPropertyChangeListener(l);
1470:            }
1471:
1472:            /**
1473:             * Removes a PropertyChangeListener.
1474:             *
1475:             * @param l a value of type 'PropertyChangeListener'
1476:             */
1477:            public void removePropertyChangeListener(PropertyChangeListener l) {
1478:
1479:                m_Support.removePropertyChangeListener(l);
1480:            }
1481:
1482:            /**
1483:             * Gets the custom panel used for editing the object.
1484:             *
1485:             * @return the panel
1486:             */
1487:            public JPanel getCustomPanel() {
1488:
1489:                JButton chooseButton = createChooseClassButton();
1490:                m_ObjectPropertyPanel = new PropertyPanel(this , true);
1491:
1492:                JPanel customPanel = new JPanel();
1493:                customPanel.setLayout(new BorderLayout());
1494:                customPanel.add(chooseButton, BorderLayout.WEST);
1495:                customPanel.add(m_ObjectPropertyPanel, BorderLayout.CENTER);
1496:                return customPanel;
1497:            }
1498:
1499:            /**
1500:             * Creates a button that when clicked will enable the user to change
1501:             * the class of the object being edited.
1502:             * 
1503:             * @return the choose button
1504:             */
1505:            protected JButton createChooseClassButton() {
1506:
1507:                JButton setButton = new JButton("Choose");
1508:
1509:                // anonymous action listener shows a JTree popup and allows the user
1510:                // to choose the class they want
1511:                setButton.addActionListener(new ActionListener() {
1512:                    public void actionPerformed(ActionEvent e) {
1513:
1514:                        JPopupMenu popup = getChooseClassPopupMenu();
1515:
1516:                        // show the popup where the source component is
1517:                        if (e.getSource() instanceof  Component) {
1518:                            Component comp = (Component) e.getSource();
1519:                            popup.show(comp, comp.getX(), comp.getY());
1520:                            popup.pack();
1521:                        }
1522:                    }
1523:                });
1524:
1525:                return setButton;
1526:            }
1527:
1528:            /**
1529:             * creates a classname from the given path
1530:             * 
1531:             * @param path	the path to generate the classname from
1532:             * @return		the generated classname
1533:             */
1534:            protected String getClassnameFromPath(TreePath path) {
1535:                StringBuffer classname = new StringBuffer();
1536:
1537:                // recreate class name from path
1538:                int start = 0;
1539:                if (m_ObjectNames.size() > 1)
1540:                    start = 1;
1541:
1542:                for (int i = start; i < path.getPathCount(); i++) {
1543:                    if (i > start)
1544:                        classname.append(".");
1545:                    classname.append((String) ((GOETreeNode) path
1546:                            .getPathComponent(i)).getUserObject());
1547:                }
1548:
1549:                return classname.toString();
1550:            }
1551:
1552:            /**
1553:             * Returns a popup menu that allows the user to change
1554:             * the class of object.
1555:             *
1556:             * @return a JPopupMenu that when shown will let the user choose the class
1557:             */
1558:            public JPopupMenu getChooseClassPopupMenu() {
1559:
1560:                updateObjectNames();
1561:
1562:                // create the tree, and find the path to the current class
1563:                m_treeNodeOfCurrentObject = null;
1564:                final JTree tree = createTree(m_ObjectNames);
1565:                if (m_treeNodeOfCurrentObject != null) {
1566:                    tree.setSelectionPath(new TreePath(
1567:                            m_treeNodeOfCurrentObject.getPath()));
1568:                }
1569:                tree.getSelectionModel().setSelectionMode(
1570:                        TreeSelectionModel.SINGLE_TREE_SELECTION);
1571:
1572:                // create the popup
1573:                final JPopupMenu popup = new JTreePopupMenu(tree);
1574:
1575:                // respond when the user chooses a class
1576:                tree.addTreeSelectionListener(new TreeSelectionListener() {
1577:                    public void valueChanged(TreeSelectionEvent e) {
1578:                        GOETreeNode node = (GOETreeNode) tree
1579:                                .getLastSelectedPathComponent();
1580:
1581:                        if (node == null)
1582:                            return;
1583:
1584:                        if (node.isLeaf()) {
1585:                            classSelected(getClassnameFromPath(tree
1586:                                    .getSelectionPath()));
1587:                            popup.setVisible(false);
1588:                        }
1589:                    }
1590:                });
1591:
1592:                return popup;
1593:            }
1594:
1595:            /**
1596:             * Creates a JTree from an object heirarchy.
1597:             *
1598:             * @param hpps the hierarchy of objects to mirror in the tree
1599:             * @return a JTree representation of the hierarchy
1600:             */
1601:            protected JTree createTree(Hashtable hpps) {
1602:                GOETreeNode super Root;
1603:                Enumeration enm;
1604:                HierarchyPropertyParser hpp;
1605:
1606:                if (hpps.size() > 1)
1607:                    super Root = new GOETreeNode("root");
1608:                else
1609:                    super Root = null;
1610:
1611:                enm = hpps.elements();
1612:                while (enm.hasMoreElements()) {
1613:                    hpp = (HierarchyPropertyParser) enm.nextElement();
1614:                    hpp.goToRoot();
1615:                    GOETreeNode root = new GOETreeNode(hpp.getValue());
1616:                    addChildrenToTree(root, hpp);
1617:
1618:                    if (super Root == null)
1619:                        super Root = root;
1620:                    else
1621:                        super Root.add(root);
1622:                }
1623:
1624:                JTree tree = new JTree(super Root);
1625:
1626:                return tree;
1627:            }
1628:
1629:            /**
1630:             * Recursively builds a JTree from an object heirarchy.
1631:             * Also updates m_treeNodeOfCurrentObject if the current object
1632:             * is discovered during creation.
1633:             *
1634:             * @param tree the root of the tree to add children to
1635:             * @param hpp the hierarchy of objects to mirror in the tree
1636:             */
1637:            protected void addChildrenToTree(GOETreeNode tree,
1638:                    HierarchyPropertyParser hpp) {
1639:
1640:                try {
1641:                    for (int i = 0; i < hpp.numChildren(); i++) {
1642:                        hpp.goToChild(i);
1643:                        GOETreeNode child = new GOETreeNode(hpp.getValue());
1644:                        if ((m_Object != null)
1645:                                && m_Object.getClass().getName().equals(
1646:                                        hpp.fullValue())) {
1647:                            m_treeNodeOfCurrentObject = child;
1648:                        }
1649:                        tree.add(child);
1650:                        addChildrenToTree(child, hpp);
1651:                        hpp.goToParent();
1652:                    }
1653:                } catch (Exception e) {
1654:                    e.printStackTrace();
1655:                }
1656:            }
1657:
1658:            /**
1659:             * Called when the user selects an class type to change to.
1660:             *
1661:             * @param className the name of the class that was selected
1662:             */
1663:            protected void classSelected(String className) {
1664:
1665:                try {
1666:                    if ((m_Object != null)
1667:                            && m_Object.getClass().getName().equals(className)) {
1668:                        return;
1669:                    }
1670:
1671:                    setValue(Class.forName(className).newInstance());
1672:                    //m_ObjectPropertyPanel.showPropertyDialog();
1673:                    if (m_EditorComponent != null) {
1674:                        m_EditorComponent.updateChildPropertySheet();
1675:                    }
1676:                } catch (Exception ex) {
1677:                    JOptionPane.showMessageDialog(null,
1678:                            "Could not create an example of\n" + className
1679:                                    + "\n" + "from the current classpath",
1680:                            "Class load failed", JOptionPane.ERROR_MESSAGE);
1681:                    ex.printStackTrace();
1682:                    try {
1683:                        if (m_Backup != null)
1684:                            setValue(m_Backup);
1685:                        else
1686:                            setDefaultValue();
1687:                    } catch (Exception e) {
1688:                        System.err.println(ex.getMessage());
1689:                        ex.printStackTrace();
1690:                    }
1691:                }
1692:            }
1693:
1694:            /**
1695:             * Sets the capabilities to use for filtering.
1696:             * 
1697:             * @param value	the object to get the filter capabilities from
1698:             */
1699:            public void setCapabilitiesFilter(Capabilities value) {
1700:                m_CapabilitiesFilter = new Capabilities(null);
1701:                m_CapabilitiesFilter.assign(value);
1702:            }
1703:
1704:            /**
1705:             * Returns the current Capabilities filter, can be null.
1706:             * 
1707:             * @return		the current Capabiliities used for filtering
1708:             */
1709:            public Capabilities getCapabilitiesFilter() {
1710:                return m_CapabilitiesFilter;
1711:            }
1712:
1713:            /**
1714:             * Removes the current Capabilities filter.
1715:             */
1716:            public void removeCapabilitiesFilter() {
1717:                m_CapabilitiesFilter = null;
1718:            }
1719:
1720:            /**
1721:             * Makes a copy of an object using serialization
1722:             * @param source the object to copy
1723:             * @return a copy of the source object
1724:             * @exception Exception if the copy fails
1725:             */
1726:            public Object makeCopy(Object source) throws Exception {
1727:                SerializedObject so = new SerializedObject(source);
1728:                Object result = so.getObject();
1729:                return result;
1730:            }
1731:
1732:            /**
1733:             * Tests out the Object editor from the command line.
1734:             *
1735:             * @param args may contain the class name of a Object to edit
1736:             */
1737:            public static void main(String[] args) {
1738:
1739:                try {
1740:                    GenericObjectEditor.registerEditors();
1741:                    GenericObjectEditor ce = new GenericObjectEditor(true);
1742:                    ce.setClassType(weka.classifiers.Classifier.class);
1743:                    Object initial = new weka.classifiers.rules.ZeroR();
1744:                    if (args.length > 0) {
1745:                        ce.setClassType(Class.forName(args[0]));
1746:                        if (args.length > 1) {
1747:                            initial = (Object) Class.forName(args[1])
1748:                                    .newInstance();
1749:                            ce.setValue(initial);
1750:                        } else
1751:                            ce.setDefaultValue();
1752:                    } else
1753:                        ce.setValue(initial);
1754:
1755:                    PropertyDialog pd = new PropertyDialog(ce, 100, 100);
1756:                    pd.addWindowListener(new WindowAdapter() {
1757:                        public void windowClosing(WindowEvent e) {
1758:                            PropertyEditor pe = ((PropertyDialog) e.getSource())
1759:                                    .getEditor();
1760:                            Object c = (Object) pe.getValue();
1761:                            String options = "";
1762:                            if (c instanceof  OptionHandler) {
1763:                                options = Utils.joinOptions(((OptionHandler) c)
1764:                                        .getOptions());
1765:                            }
1766:                            System.out.println(c.getClass().getName() + " "
1767:                                    + options);
1768:                            System.exit(0);
1769:                        }
1770:                    });
1771:                } catch (Exception ex) {
1772:                    ex.printStackTrace();
1773:                    System.err.println(ex.getMessage());
1774:                }
1775:            }
1776:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.