/*
* 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.
*/
/*
* BeanVisual.java
* Copyright (C) 2002 University of Waikato, Hamilton, New Zealand
*
*/
package weka.gui.beans;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
* BeanVisual encapsulates icons and label for a given bean. Has methods
* to load icons, set label text and toggle between static and animated
* versions of a bean's icon.
*
* @author Mark Hall
* @version $Revision: 1.10 $
* @since 1.0
* @see JPanel
* @see Serializable
*/
public class BeanVisual
extends JPanel {
/** for serialization */
private static final long serialVersionUID = -6677473561687129614L;
public static final String ICON_PATH="weka/gui/beans/icons/";
public static final int NORTH_CONNECTOR = 0;
public static final int SOUTH_CONNECTOR = 1;
public static final int EAST_CONNECTOR = 2;
public static final int WEST_CONNECTOR = 3;
/**
* Holds name (including path) of the static icon
*/
protected String m_iconPath;
/**
* Holds name (including path) of the animated icon
*/
protected String m_animatedIconPath;
/**
* ImageIcons for the icons. Is transient because for some reason
* animated gifs cease to be animated after restoring from serialization.
* Icons are re-loaded from source after deserialization
*/
protected transient ImageIcon m_icon;
protected transient ImageIcon m_animatedIcon;
/**
* Name for the bean
*/
protected String m_visualName;
protected JLabel m_visualLabel;
/**
* Container for the icon
*/
// protected IconHolder m_visualHolder;
// protected JLabel m_textLabel;
private boolean m_stationary = true;
private PropertyChangeSupport m_pcs = new PropertyChangeSupport(this);
private boolean m_displayConnectors = false;
private Color m_connectorColor = Color.blue;
/**
* Constructor
*
* @param visualName name for the bean
* @param iconPath path to the icon file
* @param animatedIconPath path to the animated icon file
*/
public BeanVisual(String visualName, String iconPath,
String animatedIconPath) {
loadIcons(iconPath, animatedIconPath);
m_visualName = visualName;
// m_textLabel = new JLabel(m_visualName, JLabel.CENTER);
m_visualLabel = new JLabel(m_icon);
setLayout(new BorderLayout());
// m_visualHolder = new IconHolder(m_visualLabel);
add(m_visualLabel, BorderLayout.CENTER);
Dimension d = m_visualLabel.getPreferredSize();
// this.setSize((int)d.getWidth()+50, (int)d.getHeight()+50);
Dimension d2 = new Dimension((int)d.getWidth() + 10,
(int)d.getHeight() + 10);
setMinimumSize(d2);
setPreferredSize(d2);
setMaximumSize(d2);
}
/**
* Reduce this BeanVisual's icon size by the given factor
*
* @param factor the factor by which to reduce the icon size by
*/
public void scale(int factor) {
if (m_icon != null) {
removeAll();
Image pic = m_icon.getImage();
int width = m_icon.getIconWidth();
int height = m_icon.getIconHeight();
int reduction = width / factor;
width -= reduction;
height -= reduction;
pic = pic.getScaledInstance(width, height, Image.SCALE_SMOOTH);
m_icon = new ImageIcon(pic);
m_visualLabel = new JLabel(m_icon);
add(m_visualLabel, BorderLayout.CENTER);
Dimension d = m_visualLabel.getPreferredSize();
// this.setSize((int)d.getWidth()+50, (int)d.getHeight()+50);
Dimension d2 = new Dimension((int)d.getWidth() + 10,
(int)d.getHeight() + 10);
setMinimumSize(d2);
setPreferredSize(d2);
setMaximumSize(d2);
}
}
/**
* Loads static and animated versions of a beans icons. These are
* assumed to be defined in the system resource location (i.e. in the
* CLASSPATH). If the named icons do not exist, no changes to the
* visual appearance is made. Since default icons for generic
* types of beans (eg. DataSource, Classifier etc)
* are assumed to exist, it allows developers to add custom icons for
* for specific instantiations of these beans
* (eg. J48, DiscretizeFilter etc) at their leisure.
*
* @param iconPath path to
* @param animatedIconPath a String
value
*/
public boolean loadIcons(String iconPath, String animatedIconPath) {
boolean success = true;
// java.net.URL imageURL = ClassLoader.getSystemResource(iconPath);
java.net.URL imageURL = this.getClass().getClassLoader().getResource(iconPath);
if (imageURL == null) {
// System.err.println("Warning: unable to load "+iconPath);
} else {
Image pic = Toolkit.getDefaultToolkit().
getImage(imageURL);
m_icon = new ImageIcon(pic);
if (m_visualLabel != null) {
m_visualLabel.setIcon(m_icon);
}
}
// imageURL = ClassLoader.getSystemResource(animatedIconPath);
imageURL = this.getClass().getClassLoader().getResource(animatedIconPath);
if (imageURL == null) {
// System.err.println("Warning: unable to load "+animatedIconPath);
success = false;
} else {
Image pic2 = Toolkit.getDefaultToolkit().
getImage(imageURL);
m_animatedIcon = new ImageIcon(pic2);
}
m_iconPath = iconPath;
m_animatedIconPath = animatedIconPath;
return success;
}
/**
* Set the label for the visual. Informs any property change listeners
*
* @param text the label
*/
public void setText(String text) {
m_visualName = text;
// m_textLabel.setText(m_visualName);
m_pcs.firePropertyChange("label",null,null);
}
/**
* Get the visual's label
*
* @return a String
value
*/
public String getText() {
return m_visualName;
}
/**
* Set the static version of the icon
*
*/
public void setStatic() {
m_visualLabel.setIcon(m_icon);
}
/**
* Set the animated version of the icon
*
*/
public void setAnimated() {
m_visualLabel.setIcon(m_animatedIcon);
}
/**
* Returns the coordinates of the closest "connector" point to the
* supplied point. Coordinates are in the parent containers coordinate
* space.
*
* @param pt the reference point
* @return the closest connector point
*/
public Point getClosestConnectorPoint(Point pt) {
int sourceX = getParent().getX();
int sourceY = getParent().getY();
int sourceWidth = getWidth();
int sourceHeight = getHeight();
int sourceMidX = sourceX + (sourceWidth / 2);
int sourceMidY = sourceY + (sourceHeight / 2);
int x = (int)pt.getX();
int y = (int)pt.getY();
Point closest = new Point();
int cx = (Math.abs(x - sourceMidX) < Math.abs(y - sourceMidY)) ?
sourceMidX :
((x < sourceMidX) ? sourceX : sourceX + sourceWidth);
int cy = (Math.abs(y - sourceMidY) < Math.abs(x - sourceMidX)) ?
sourceMidY :
((y < sourceMidY) ? sourceY : sourceY + sourceHeight) ;
closest.setLocation(cx, cy);
return closest;
}
/**
* Returns the coordinates of the connector point given a compass point
*
* @param compassPoint a compass point
* @return a Point
value
*/
public Point getConnectorPoint(int compassPoint) {
int sourceX = getParent().getX();
int sourceY = getParent().getY();
int sourceWidth = getWidth();
int sourceHeight = getHeight();
int sourceMidX = sourceX + (sourceWidth / 2);
int sourceMidY = sourceY + (sourceHeight / 2);
switch (compassPoint) {
case NORTH_CONNECTOR : return new Point(sourceMidX, sourceY);
case SOUTH_CONNECTOR : return new Point(sourceMidX, sourceY+sourceHeight);
case WEST_CONNECTOR : return new Point(sourceX, sourceMidY);
case EAST_CONNECTOR : return new Point(sourceX+sourceWidth, sourceMidY);
default : System.err.println("Unrecognised connectorPoint (BeanVisual)");
}
return new Point(sourceX, sourceY);
}
/**
* Returns the static icon
*
* @return an ImageIcon
value
*/
public ImageIcon getStaticIcon() {
return m_icon;
}
/**
* Returns the animated icon
*
* @return an ImageIcon
value
*/
public ImageIcon getAnimatedIcon() {
return m_animatedIcon;
}
/**
* returns the path for the icon
*
* @return the path for the icon
*/
public String getIconPath() {
return m_iconPath;
}
/**
* returns the path for the animated icon
*
* @return the path for the animated icon
*/
public String getAnimatedIconPath() {
return m_animatedIconPath;
}
/**
* Turn on/off the connector points
*
* @param dc a boolean
value
*/
public void setDisplayConnectors(boolean dc) {
// m_visualHolder.setDisplayConnectors(dc);
m_displayConnectors = dc;
m_connectorColor = Color.blue;
repaint();
}
/**
* Turn on/off the connector points
*
* @param dc a boolean
value
* @param c the Color to use
*/
public void setDisplayConnectors(boolean dc,
Color c) {
setDisplayConnectors(dc);
m_connectorColor = c;
}
/**
* Add a listener for property change events
*
* @param pcl a PropertyChangeListener
value
*/
public void addPropertyChangeListener(PropertyChangeListener pcl) {
m_pcs.addPropertyChangeListener(pcl);
}
/**
* Remove a property change listener
*
* @param pcl a PropertyChangeListener
value
*/
public void removePropertyChangeListener(PropertyChangeListener pcl) {
m_pcs.removePropertyChangeListener(pcl);
}
public void paintComponent(Graphics gx) {
super.paintComponent(gx);
if (m_displayConnectors) {
gx.setColor(m_connectorColor);
int midx = (int)(this.getWidth() / 2.0);
int midy = (int)(this.getHeight() / 2.0);
gx.fillOval(midx-2, 0, 5, 5);
gx.fillOval(midx-2, this.getHeight()-5, 5, 5);
gx.fillOval(0, midy-2, 5, 5);
gx.fillOval(this.getWidth()-5, midy-2, 5, 5);
}
}
/**
* Overides default read object in order to reload icons.
* This is necessary because for some strange reason animated
* gifs stop being animated after being serialized/deserialized.
*
* @param ois an ObjectInputStream
value
* @exception IOException if an error occurs
* @exception ClassNotFoundException if an error occurs
*/
private void readObject(ObjectInputStream ois)
throws IOException, ClassNotFoundException {
try {
ois.defaultReadObject();
remove(m_visualLabel);
m_visualLabel = new JLabel(m_icon);
loadIcons(m_iconPath, m_animatedIconPath);
add(m_visualLabel, BorderLayout.CENTER);
Dimension d = m_visualLabel.getPreferredSize();
Dimension d2 = new Dimension((int)d.getWidth() + 10,
(int)d.getHeight() + 10);
setMinimumSize(d2);
setPreferredSize(d2);
setMaximumSize(d2);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}