Package weka.gui

Source Code of weka.gui.GenericArrayEditor

/*
*    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.
*/

/*
*    GenericArrayEditor.java
*    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
*
*/

package weka.gui;

import weka.core.SerializedObject;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
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.beans.PropertyEditorManager;
import java.lang.reflect.Array;

import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
* A PropertyEditor for arrays of objects that themselves have
* property editors.
*
* @author Len Trigg (trigg@cs.waikato.ac.nz)
* @version $Revision: 7221 $
*/
public class GenericArrayEditor
  extends JPanel
  implements PropertyEditor {

  /** for serialization. */
  private static final long serialVersionUID = 3914616975334750480L;

  /** Handles property change notification. */
  private PropertyChangeSupport m_Support = new PropertyChangeSupport(this);

  /** The label for when we can't edit that type. */
  private JLabel m_Label = new JLabel("Can't edit", SwingConstants.CENTER);
 
  /** The list component displaying current values. */
  private JList m_ElementList = new JList();

  /** The class of objects allowed in the array. */
  private Class m_ElementClass = String.class;

  /** The defaultlistmodel holding our data. */
  private DefaultListModel m_ListModel;

  /** The property editor for the class we are editing. */
  private PropertyEditor m_ElementEditor;

  /** Click this to delete the selected array values. */
  private JButton m_DeleteBut = new JButton("Delete");

  /** Click this to edit the selected array value. */
  private JButton m_EditBut = new JButton("Edit");

  /** Click this to move the selected array value(s) one up. */
  private JButton m_UpBut = new JButton("Up");

  /** Click this to move the selected array value(s) one down. */
  private JButton m_DownBut = new JButton("Down");

  /** Click to add the current object configuration to the array. */
  private JButton m_AddBut = new JButton("Add");

  /** The property editor for editing existing elements. */
  private PropertyEditor m_Editor = new GenericObjectEditor();

  /** The currently displayed property dialog, if any. */
  private PropertyDialog m_PD;

  /** Listens to buttons being pressed and taking the appropriate action. */
  private ActionListener m_InnerActionListener =
    new ActionListener() {

    public void actionPerformed(ActionEvent e) {

      if (e.getSource() == m_DeleteBut) {
  int [] selected = m_ElementList.getSelectedIndices();
  if (selected != null) {
    for (int i = selected.length - 1; i >= 0; i--) {
      int current = selected[i];
      m_ListModel.removeElementAt(current);
      if (m_ListModel.size() > current) {
        m_ElementList.setSelectedIndex(current);
      }
    }
    m_Support.firePropertyChange("", null, null);
  }
      } else if (e.getSource() == m_EditBut) {
        if (m_Editor instanceof GenericObjectEditor) {
          ((GenericObjectEditor) m_Editor).setClassType(m_ElementClass);
        }
        m_Editor.setValue(m_ElementList.getSelectedValue());
        if (m_Editor.getValue() != null) {
          if (m_PD == null) {
            int x = getLocationOnScreen().x;
            int y = getLocationOnScreen().y;
            if (PropertyDialog.getParentDialog(GenericArrayEditor.this) != null)
              m_PD = new PropertyDialog(
            PropertyDialog.getParentDialog(GenericArrayEditor.this),
            m_Editor, x, y);
            else
              m_PD = new PropertyDialog(
            PropertyDialog.getParentFrame(GenericArrayEditor.this),
            m_Editor, x, y);
            m_PD.setVisible(true);
          }
          else {
            m_PD.setVisible(true);
          }
          m_Support.firePropertyChange("", null, null);
        }
      } else if (e.getSource() == m_UpBut) {
        JListHelper.moveUp(m_ElementList);
  m_Support.firePropertyChange("", null, null);
      } else if (e.getSource() == m_DownBut) {
        JListHelper.moveDown(m_ElementList);
  m_Support.firePropertyChange("", null, null);
      } else if (e.getSource() == m_AddBut) {
  int selected = m_ElementList.getSelectedIndex();
  Object addObj = m_ElementEditor.getValue();
 
  // Make a full copy of the object using serialization
  try {
          SerializedObject so = new SerializedObject(addObj);
    addObj = so.getObject();
    if (selected != -1) {
      m_ListModel.insertElementAt(addObj, selected);
    } else {
      m_ListModel.addElement(addObj);
    }
    m_Support.firePropertyChange("", null, null);
  } catch (Exception ex) {
    JOptionPane.showMessageDialog(GenericArrayEditor.this,
          "Could not create an object copy",
          null,
          JOptionPane.ERROR_MESSAGE);
  }
      }
    }
  };

  /** Listens to list items being selected and takes appropriate action. */
  private ListSelectionListener m_InnerSelectionListener =
    new ListSelectionListener() {

      public void valueChanged(ListSelectionEvent e) {

  if (e.getSource() == m_ElementList) {
    // Enable the delete/edit button
    if (m_ElementList.getSelectedIndex() != -1) {
      m_DeleteBut.setEnabled(true);
      m_EditBut.setEnabled(m_ElementList.getSelectedIndices().length == 1);
      m_UpBut.setEnabled(JListHelper.canMoveUp(m_ElementList));
      m_DownBut.setEnabled(JListHelper.canMoveDown(m_ElementList));
    }
          // disable delete/edit button
          else {
      m_DeleteBut.setEnabled(false);
      m_EditBut.setEnabled(false);
      m_UpBut.setEnabled(false);
      m_DownBut.setEnabled(false);
          }
  }
      }
  };

  /** Listens to mouse events and takes appropriate action. */
  private MouseListener m_InnerMouseListener =
    new MouseAdapter() {

      public void mouseClicked(MouseEvent e) {
        if (e.getSource() == m_ElementList) {
          if (e.getClickCount() == 2) {
            // unfortunately, locationToIndex only returns the nearest entry
            // and not the exact one, i.e. if there's one item in the list and
            // one doublelclicks somewhere in the list, this index will be
            // returned
            int index = m_ElementList.locationToIndex(e.getPoint());
            if (index > -1)
              m_InnerActionListener.actionPerformed(
                  new ActionEvent(m_EditBut, 0, ""));
          }
        }
      }
  };
   

  /**
   * Sets up the array editor.
   */
  public GenericArrayEditor() {

    setLayout(new BorderLayout());
    add(m_Label, BorderLayout.CENTER);
    m_DeleteBut.addActionListener(m_InnerActionListener);
    m_EditBut.addActionListener(m_InnerActionListener);
    m_UpBut.addActionListener(m_InnerActionListener);
    m_DownBut.addActionListener(m_InnerActionListener);
    m_AddBut.addActionListener(m_InnerActionListener);
    m_ElementList.addListSelectionListener(m_InnerSelectionListener);
    m_ElementList.addMouseListener(m_InnerMouseListener);
    m_AddBut.setToolTipText("Add the current item to the list");
    m_DeleteBut.setToolTipText("Delete the selected list item");
    m_EditBut.setToolTipText("Edit the selected list item");
    m_UpBut.setToolTipText("Move the selected item(s) one up");
    m_DownBut.setToolTipText("Move the selected item(s) one down");
  }

  /** This class handles the creation of list cell renderers from the
   * property editors.
   */
  private class EditorListCellRenderer implements ListCellRenderer {

    /** The class of the property editor for array objects. */
    private Class m_EditorClass;

    /** The class of the array values. */
    private Class m_ValueClass;

    /**
     * Creates the list cell renderer.
     *
     * @param editorClass The class of the property editor for array objects
     * @param valueClass The class of the array values
     */
    public EditorListCellRenderer(Class editorClass, Class valueClass) {
      m_EditorClass = editorClass;
      m_ValueClass = valueClass;
    }

    /**
     * Creates a cell rendering component.
     *
     * @param list the list that will be rendered in
     * @param value the cell value
     * @param index which element of the list to render
     * @param isSelected true if the cell is selected
     * @param cellHasFocus true if the cell has the focus
     * @return the rendering component
     */
    public Component getListCellRendererComponent(final JList list,
              final Object value,
              final int index,
              final boolean isSelected,
              final boolean cellHasFocus) {
      try {
  final PropertyEditor e = (PropertyEditor)m_EditorClass.newInstance();
  if (e instanceof GenericObjectEditor) {
    //    ((GenericObjectEditor) e).setDisplayOnly(true);
    ((GenericObjectEditor) e).setClassType(m_ValueClass);
  }
  e.setValue(value);
  return new JPanel() {
   
    private static final long serialVersionUID = -3124434678426673334L;

    public void paintComponent(Graphics g) {

      Insets i = this.getInsets();
      Rectangle box = new Rectangle(i.left, i.top,
            this.getWidth() - i.right,
            this.getHeight() - i.bottom );
      g.setColor(isSelected
           ? list.getSelectionBackground()
           : list.getBackground());
      g.fillRect(0, 0, this.getWidth(), this.getHeight());
      g.setColor(isSelected
           ? list.getSelectionForeground()
           : list.getForeground());
      e.paintValue(g, box);
    }
   
    public Dimension getPreferredSize() {

      Font f = this.getFont();
      FontMetrics fm = this.getFontMetrics(f);
      return new Dimension(0, fm.getHeight());
    }
  };
      } catch (Exception ex) {
  return null;
      }
    }
  }

  /**
   * Updates the type of object being edited, so attempts to find an
   * appropriate propertyeditor.
   *
   * @param o a value of type 'Object'
   */
  private void updateEditorType(Object o) {

    // Determine if the current object is an array
    m_ElementEditor = null; m_ListModel = null;
    removeAll();
    if ((o != null) && (o.getClass().isArray())) {
      Class elementClass = o.getClass().getComponentType();   
      PropertyEditor editor = PropertyEditorManager.findEditor(elementClass);
      Component view = null;
      ListCellRenderer lcr = new DefaultListCellRenderer();
      if (editor != null) {
  if (editor instanceof GenericObjectEditor) {
    ((GenericObjectEditor) editor).setClassType(elementClass);
  }

        //setting the value in the editor so that
        //we don't get a NullPointerException
        //when we do getAsText() in the constructor of
        //PropertyValueSelector()
  if(Array.getLength(o) > 0) {
    editor.setValue(makeCopy(Array.get(o,0)));
  } else {
    if (editor instanceof GenericObjectEditor) {
      ((GenericObjectEditor)editor).setDefaultValue();
    } else {  
            try {
              if (editor instanceof FileEditor) {
                editor.setValue(new java.io.File("-NONE-"));
              } else {
                editor.setValue(elementClass.newInstance());
              }
            } catch(Exception ex) {
              m_ElementEditor=null;
              System.err.println(ex.getMessage());
              add(m_Label, BorderLayout.CENTER);
              m_Support.firePropertyChange("", null, null);
              validate();
              return;
            }
    }
  }
       
  if (editor.isPaintable() && editor.supportsCustomEditor()) {
    view = new PropertyPanel(editor);
    lcr = new EditorListCellRenderer(editor.getClass(), elementClass);
  } else if (editor.getTags() != null) {
    view = new PropertyValueSelector(editor);
  } else if (editor.getAsText() != null) {
    view = new PropertyText(editor);
  }
      }
      if (view == null) {
  System.err.println("No property editor for class: "
         + elementClass.getName());
      } else {
        m_ElementEditor = editor;
        try {
          m_Editor = editor.getClass().newInstance();
        } catch (InstantiationException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
        } catch (IllegalAccessException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
        }

  // Create the ListModel and populate it
  m_ListModel = new DefaultListModel();
  m_ElementClass = elementClass;
  for (int i = 0; i < Array.getLength(o); i++) {
    m_ListModel.addElement(Array.get(o,i));
  }
  m_ElementList.setCellRenderer(lcr);
  m_ElementList.setModel(m_ListModel);
  if (m_ListModel.getSize() > 0) {
    m_ElementList.setSelectedIndex(0);
  } else {
    m_DeleteBut.setEnabled(false);
    m_EditBut.setEnabled(false);
  }
  m_UpBut.setEnabled(JListHelper.canMoveDown(m_ElementList));
  m_DownBut.setEnabled(JListHelper.canMoveDown(m_ElementList));

        //have already set the value above in the editor
  //try {
    //if (m_ListModel.getSize() > 0) {
    //  m_ElementEditor.setValue(m_ListModel.getElementAt(0));
    //} else {
    //  if (m_ElementEditor instanceof GenericObjectEditor) {
    //    ((GenericObjectEditor)m_ElementEditor).setDefaultValue();
    //  } else {
    //    m_ElementEditor.setValue(m_ElementClass.newInstance());
    //  }
    //}
   
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.add(view, BorderLayout.CENTER);
    panel.add(m_AddBut, BorderLayout.EAST);
    add(panel, BorderLayout.NORTH);
    add(new JScrollPane(m_ElementList), BorderLayout.CENTER);
          JPanel panel2 = new JPanel();
          panel2.setLayout(new GridLayout(1, 4));
          panel2.add(m_DeleteBut);
          panel2.add(m_EditBut);
          panel2.add(m_UpBut);
          panel2.add(m_DownBut);
          add(panel2, BorderLayout.SOUTH);
    m_ElementEditor
      .addPropertyChangeListener(new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent e) {
        repaint();
      }
    });
  //} catch (Exception ex) {
  //  System.err.println(ex.getMessage());
  //  m_ElementEditor = null;
  //}
      }
    }
    if (m_ElementEditor == null) {
      add(m_Label, BorderLayout.CENTER);
    }
    m_Support.firePropertyChange("", null, null);
    validate();
  }

  /**
   * Sets the current object array.
   *
   * @param o an object that must be an array.
   */
  public void setValue(Object o) {

    // Create a new list model, put it in the list and resize?
    updateEditorType(o);
  }

  /**
   * Gets the current object array.
   *
   * @return the current object array
   */
  public Object getValue() {

    if (m_ListModel == null) {
      return null;
    }
    // Convert the listmodel to an array of strings and return it.
    int length = m_ListModel.getSize();
    Object result = Array.newInstance(m_ElementClass, length);
    for (int i = 0; i < length; i++) {
      Array.set(result, i, m_ListModel.elementAt(i));
    }
    return result;
  }
 
  /**
   * Supposedly returns an initialization string to create a classifier
   * identical to the current one, including it's state, but this doesn't
   * appear possible given that the initialization string isn't supposed to
   * contain multiple statements.
   *
   * @return the java source code initialisation string
   */
  public String getJavaInitializationString() {

    return "null";
  }

  /**
   * Returns true to indicate that we can paint a representation of the
   * string array.
   *
   * @return true
   */
  public boolean isPaintable() {
    return true;
  }

  /**
   * Paints a representation of the current classifier.
   *
   * @param gfx the graphics context to use
   * @param box the area we are allowed to paint into
   */
  public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {

    FontMetrics fm = gfx.getFontMetrics();
    int vpad = (box.height - fm.getHeight()) / 2;
    String rep = m_ListModel.getSize() + " " + m_ElementClass.getName();
    gfx.drawString(rep, 2, fm.getAscent() + vpad + 2);
  }

  /**
   * Returns null as we don't support getting/setting values as text.
   *
   * @return null
   */
  public String getAsText() {
    return null;
  }

  /**
   * Returns null as we don't support getting/setting values as text.
   *
   * @param text the text value
   * @exception IllegalArgumentException as we don't support
   * getting/setting values as text.
   */
  public void setAsText(String text) {
    throw new IllegalArgumentException(text);
  }

  /**
   * Returns null as we don't support getting values as tags.
   *
   * @return null
   */
  public String[] getTags() {
    return null;
  }

  /**
   * Returns true because we do support a custom editor.
   *
   * @return true
   */
  public boolean supportsCustomEditor() {
    return true;
  }
 
  /**
   * Returns the array editing component.
   *
   * @return a value of type 'java.awt.Component'
   */
  public java.awt.Component getCustomEditor() {
    return this;
  }

  /**
   * Adds a PropertyChangeListener who will be notified of value changes.
   *
   * @param l a value of type 'PropertyChangeListener'
   */
  public void addPropertyChangeListener(PropertyChangeListener l) {
    m_Support.addPropertyChangeListener(l);
  }

  /**
   * Removes a PropertyChangeListener.
   *
   * @param l a value of type 'PropertyChangeListener'
   */
  public void removePropertyChangeListener(PropertyChangeListener l) {
    m_Support.removePropertyChangeListener(l);
  }

  /**
   * Makes a copy of an object using serialization.
   *
   * @param source the object to copy
   * @return a copy of the source object, null if copying fails
   */
  public static Object makeCopy(Object source) {
    Object  result;
   
    try {
      result = GenericObjectEditor.makeCopy(source);
    }
    catch (Exception e) {
      result = null;
    }
   
    return result;
  }

  /**
   * Tests out the array editor from the command line.
   *
   * @param args ignored
   */
  public static void main(String [] args) {

    try {
      GenericObjectEditor.registerEditors();

      final GenericArrayEditor ce = new GenericArrayEditor();

      final weka.filters.Filter [] initial = new weka.filters.Filter [0];
  /*
      {
  new weka.filters.AddFilter()
  };*/
      /*
      final String [] initial = {
  "Hello",
  "There",
  "Bob"
  };*/
      PropertyDialog pd = new PropertyDialog((Frame) null, ce, 100, 100);
      pd.setSize(200,200);
      pd.addWindowListener(new WindowAdapter() {
  private static final long serialVersionUID = -3124434678426673334L;
  public void windowClosing(WindowEvent e) {
    System.exit(0);
  }
      });
      ce.setValue(initial);
      pd.setVisible(true);
      //ce.validate();
    } catch (Exception ex) {
      ex.printStackTrace();
      System.err.println(ex.getMessage());
    }
  }

}
TOP

Related Classes of weka.gui.GenericArrayEditor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.