⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genericobjecteditor.java

📁 MacroWeka扩展了著名数据挖掘工具weka
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 *    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 weka.core.OptionHandler;
import weka.core.SerializedObject;
import weka.core.Utils;

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.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

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;

/**
 * A PropertyEditor for objects. It can be used either in a static or a dynamic
 * way. <br>
 * <br>
 * In the <b>static</b> way (<code>USE_DYNAMIC</code> is <code>false</code>) the
 * objects 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 ;-). <br>
 * <br>
 * If it is used in a <b>dynamic</b> way (<code>USE_DYNAMIC</code> is
 * <code>true</code>) then the classes to list are discovered by the 
 * <code>GenericPropertiesCreator</code> class (it checks the complete classpath). 
 * 
 * @see #USE_DYNAMIC
 * @see GenericPropertiesCreator
 * @see GenericPropertiesCreator#CREATOR_FILE
 * @see weka.core.RTSI
 * 
 * @author Len Trigg (trigg@cs.waikato.ac.nz)
 * @author Xin Xu (xx5@cs.waikato.ac.nz)
 * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
 * @author FracPete (fracpete at waikato dot ac dot nz)
 * @version $Revision: 1.1 $
 */
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 Hashtable 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;
    
  /** whether the class can be changed */
  protected boolean m_canChangeClassInDialog;

  /** whether to generate the properties dynamically or use the static props-file */
  protected final static boolean USE_DYNAMIC = true;
  
  /** whether the Weka Editors were already registered */
  protected static boolean m_EditorsRegistered;
  
  /** 
   * Loads the configuration property file (USE_DYNAMIC is FALSE) or determines
   * the classes dynamically (USE_DYNAMIC is TRUE)
   * @see #USE_DYNAMIC
   * @see GenericPropertiesCreator
   */
  static {
	
    if (USE_DYNAMIC) {
      try {
        GenericPropertiesCreator creator = new GenericPropertiesCreator();
        creator.execute(false);
        EDITOR_PROPERTIES = creator.getOutputProperties();
      }
      catch (Exception e) {
        JOptionPane.showMessageDialog(
            null,
              "Could not determine the properties for the generic object\n"
            + "editor. This exception was produced:\n"
            + e.toString(),
            "GenericObjectEditor",
            JOptionPane.ERROR_MESSAGE);
      }
    }
    else {
      // 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) {
        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 {

    /** 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));
      m_scroller.getVerticalScrollBar().setUnitIncrement(20);

      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 {
    
    /** 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();
	}
      }
    }
    
    /**
     * Enables/disables the cancel button.
     *
     * @param flag true to enable cancel button, false
     * to disable it
     */
    protected void setCancelButton(boolean flag) {

      if(m_cancelBut != null)
	m_cancelBut.setEnabled(flag);
    }
    
    /**
     * Opens an object from a file selected by the user.
     * 
     * @return the loaded object, or null if the operation was cancelled
     */
    protected Object openObject() {
      
      if (m_FileChooser == null) {
	createFileChooser();
      }
      int returnVal = m_FileChooser.showOpenDialog(this);
      if (returnVal == JFileChooser.APPROVE_OPTION) {
	File selected = m_FileChooser.getSelectedFile();
	try {
	  ObjectInputStream oi = new ObjectInputStream(new BufferedInputStream(new FileInputStream(selected)));
	  Object obj = oi.readObject();
	  oi.close();
	  if (!m_ClassType.isAssignableFrom(obj.getClass())) {
	    throw new Exception("Object not of type: " + m_ClassType.getName());
	  }
	  return obj;
	} catch (Exception ex) {
	  JOptionPane.showMessageDialog(this,
					"Couldn't read object: "
					+ selected.getName() 
					+ "\n" + ex.getMessage(),
					"Open object file",
					JOptionPane.ERROR_MESSAGE);
	}
      }
      return null;
    }
    
    /**
     * Opens an object from a file selected by the user.
     * 
     * @return the loaded object, or null if the operation was cancelled
     */
    protected void saveObject(Object object) {
      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -