/* * 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.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.RenderingHints; 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 <a href="mailto:mhall@cs.waikato.ac.nz">Mark Hall</a> * @version $Revision: 7154 $ * @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); } } public Image scale(double percent) { if (m_icon != null) { Image pic = m_icon.getImage(); double width = m_icon.getIconWidth(); double height = m_icon.getIconHeight(); width *= percent; height *= percent; pic = pic.getScaledInstance((int)width, (int)height, Image.SCALE_SMOOTH); return pic; } return null; } /** * 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 <code>String</code> 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 <code>String</code> value */ public String getText() { return m_visualName; } /** * Set the static version of the icon * */ public void setStatic() { setDisplayConnectors(false); //m_visualLabel.setIcon(m_icon); } /** * Set the animated version of the icon * */ public void setAnimated() { setDisplayConnectors(true); //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 <code>Point</code> 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 <code>ImageIcon</code> value */ public ImageIcon getStaticIcon() { return m_icon; } /** * Returns the animated icon * * @return an <code>ImageIcon</code> 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 <code>boolean</code> 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 <code>boolean</code> 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 <code>PropertyChangeListener</code> value */ public void addPropertyChangeListener(PropertyChangeListener pcl) { m_pcs.addPropertyChangeListener(pcl); } /** * Remove a property change listener * * @param pcl a <code>PropertyChangeListener</code> value */ public void removePropertyChangeListener(PropertyChangeListener pcl) { m_pcs.removePropertyChangeListener(pcl); } public void paintComponent(Graphics gx) { ((Graphics2D)gx).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 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 <code>ObjectInputStream</code> 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(); } } }