📄 genericobjecteditor.java
字号:
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* GenericObjectEditor.java
* Copyright (C) 2002 Len Trigg, Xin Xu, Richard Kirkby
*
*/
package weka.gui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyEditor;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Properties;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import weka.core.OptionHandler;
import weka.core.SelectedTag;
import weka.core.SerializedObject;
import weka.core.Utils;
/**
* A PropertyEditor for objects that themselves have been defined as
* editable in the GenericObjectEditor configuration file, which lists
* possible values that can be selected from, and themselves configured.
* The configuration file is called "GenericObjectEditor.props" and
* may live in either the location given by "user.home" or the current
* directory (this last will take precedence), and a default properties
* file is read from the weka distribution. For speed, the properties
* file is read only once when the class is first loaded -- this may need
* to be changed if we ever end up running in a Java OS ;-).
*
* @author Len Trigg (trigg@cs.waikato.ac.nz)
* @author Xin Xu (xx5@cs.waikato.ac.nz)
* @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
* @version $Revision$
*/
public class GenericObjectEditor implements PropertyEditor, CustomPanelSupplier {
/** The object being configured */
protected Object m_Object;
/** Holds a copy of the current object that can be reverted to
if the user decides to cancel */
protected Object m_Backup;
/** Handles property change notification */
protected PropertyChangeSupport m_Support = new PropertyChangeSupport(this);
/** The Class of objects being edited */
protected Class m_ClassType;
/** The model containing the list of names to select from */
protected HierarchyPropertyParser m_ObjectNames;
/** The GUI component for editing values, created when needed */
protected GOEPanel m_EditorComponent;
/** True if the GUI component is needed */
protected boolean m_Enabled = true;
/** The name of the properties file */
protected static String PROPERTY_FILE = "weka/gui/GenericObjectEditor.props";
/** Contains the editor properties */
protected static Properties EDITOR_PROPERTIES;
/** The tree node of the current object so we can re-select it for the user */
protected DefaultMutableTreeNode m_treeNodeOfCurrentObject;
/** The property panel created for the objects */
protected PropertyPanel m_ObjectPropertyPanel;
protected boolean m_canChangeClassInDialog;
/** Loads the configuration property file */
static {
// Allow a properties file in the current directory to override
try {
EDITOR_PROPERTIES = Utils.readProperties(PROPERTY_FILE);
java.util.Enumeration keys =
(java.util.Enumeration)EDITOR_PROPERTIES.propertyNames();
if (!keys.hasMoreElements()) {
throw new Exception("Failed to read a property file for the "
+"generic object editor");
}
} catch (Exception ex) {
ex.printStackTrace();
/*
JOptionPane.showMessageDialog(null,
"Could not read a configuration file for the generic object\n"
+"editor. An example file is included with the Weka distribution.\n"
+"This file should be named \"" + PROPERTY_FILE + "\" and\n"
+"should be placed either in your user home (which is set\n"
+ "to \"" + System.getProperties().getProperty("user.home") + "\")\n"
+ "or the directory that java was started from\n",
"GenericObjectEditor",
JOptionPane.ERROR_MESSAGE);
*/
}
}
/**
* Creates a popup menu containing a tree that is aware
* of the screen dimensions.
*/
public class JTreePopupMenu extends JPopupMenu {
/**
*
*/
private static final long serialVersionUID = -6578083341781752138L;
/** The tree */
JTree m_tree;
/** The scroller */
JScrollPane m_scroller;
/**
* Constructs a new popup menu.
*
* @param tree the tree to put in the menu
*/
public JTreePopupMenu(JTree tree) {
m_tree = tree;
JPanel treeView = new JPanel();
treeView.setLayout(new BorderLayout());
treeView.add(m_tree, BorderLayout.NORTH);
// make backgrounds look the same
treeView.setBackground(m_tree.getBackground());
m_scroller = new JScrollPane(treeView);
m_scroller.setPreferredSize(new Dimension(300, 400));
add(m_scroller);
}
/**
* Displays the menu, making sure it will fit on the screen.
*
* @param invoker the component thast invoked the menu
* @param x the x location of the popup
* @param y the y location of the popup
*/
public void show(Component invoker, int x, int y) {
super.show(invoker, x, y);
// calculate available screen area for popup
java.awt.Point location = getLocationOnScreen();
java.awt.Dimension screenSize = getToolkit().getScreenSize();
int maxWidth = (int) (screenSize.getWidth() - location.getX());
int maxHeight = (int) (screenSize.getHeight() - location.getY());
// if the part of the popup goes off the screen then resize it
Dimension scrollerSize = m_scroller.getPreferredSize();
int height = (int) scrollerSize.getHeight();
int width = (int) scrollerSize.getWidth();
if (width > maxWidth) width = maxWidth;
if (height > maxHeight) height = maxHeight;
// commit any size changes
m_scroller.setPreferredSize(new Dimension(width, height));
revalidate();
pack();
}
}
/**
* Handles the GUI side of editing values.
*/
public class GOEPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = -2649653612618495253L;
/** The component that performs classifier customization */
protected PropertySheetPanel m_ChildPropertySheet;
/** The name of the current class */
protected JLabel m_ClassNameLabel;
/** Open object from disk */
protected JButton m_OpenBut;
/** Save object to disk */
protected JButton m_SaveBut;
/** ok button */
protected JButton m_okBut;
/** cancel button */
protected JButton m_cancelBut;
/** The filechooser for opening and saving object files */
protected JFileChooser m_FileChooser;
/** Creates the GUI editor component */
public GOEPanel() {
m_Backup = copyObject(m_Object);
m_ClassNameLabel = new JLabel("None");
m_ClassNameLabel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
m_ChildPropertySheet = new PropertySheetPanel();
m_ChildPropertySheet.addPropertyChangeListener
(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
m_Support.firePropertyChange("", null, null);
}
});
m_OpenBut = new JButton("Open...");
m_OpenBut.setToolTipText("Load a configured object");
m_OpenBut.setEnabled(true);
m_OpenBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object object = openObject();
if (object != null) {
// setValue takes care of: Making sure obj is of right type,
// and firing property change.
setValue(object);
// Need a second setValue to get property values filled in OK.
// Not sure why.
setValue(object);
}
}
});
m_SaveBut = new JButton("Save...");
m_SaveBut.setToolTipText("Save the current configured object");
m_SaveBut.setEnabled(true);
m_SaveBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveObject(m_Object);
}
});
m_okBut = new JButton("OK");
m_okBut.setEnabled(true);
m_okBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
m_Backup = copyObject(m_Object);
if ((getTopLevelAncestor() != null)
&& (getTopLevelAncestor() instanceof Window)) {
Window w = (Window) getTopLevelAncestor();
w.dispose();
}
}
});
m_cancelBut = new JButton("Cancel");
m_cancelBut.setEnabled(true);
m_cancelBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (m_Backup != null) {
m_Object = copyObject(m_Backup);
// To fire property change
m_Support.firePropertyChange("", null, null);
m_ObjectNames = getClassesFromProperties();
updateObjectNames();
updateChildPropertySheet();
}
if ((getTopLevelAncestor() != null)
&& (getTopLevelAncestor() instanceof Window)) {
Window w = (Window) getTopLevelAncestor();
w.dispose();
}
}
});
setLayout(new BorderLayout());
if (m_canChangeClassInDialog) {
JButton chooseButton = createChooseClassButton();
JPanel top = new JPanel();
top.setLayout(new BorderLayout());
top.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
top.add(chooseButton, BorderLayout.WEST);
top.add(m_ClassNameLabel, BorderLayout.CENTER);
add(top, BorderLayout.NORTH);
} else {
add(m_ClassNameLabel, BorderLayout.NORTH);
}
add(m_ChildPropertySheet, BorderLayout.CENTER);
// Since we resize to the size of the property sheet, a scrollpane isn't
// typically needed
// add(new JScrollPane(m_ChildPropertySheet), BorderLayout.CENTER);
JPanel okcButs = new JPanel();
okcButs.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
okcButs.setLayout(new GridLayout(1, 4, 5, 5));
okcButs.add(m_OpenBut);
okcButs.add(m_SaveBut);
okcButs.add(m_okBut);
okcButs.add(m_cancelBut);
add(okcButs, BorderLayout.SOUTH);
if (m_ClassType != null) {
m_ObjectNames = getClassesFromProperties();
if (m_Object != null) {
updateObjectNames();
updateChildPropertySheet();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -