weka.gui.beans.BeanInstance.java Source code

Java tutorial

Introduction

Here is the source code for weka.gui.beans.BeanInstance.java

Source

/*
 *   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 3 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, see <http://www.gnu.org/licenses/>.
 */

/*
 *    BeanInstance.java
 *    Copyright (C) 2002-2012 University of Waikato, Hamilton, New Zealand
 *
 */

package weka.gui.beans;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.beans.Beans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.JComponent;

/**
 * Class that manages a set of beans.
 * 
 * @author <a href="mailto:mhall@cs.waikato.ac.nz">Mark Hall</a>
 * @version $Revision$
 * @since 1.0
 */
public class BeanInstance implements Serializable {

    /** for serialization */
    private static final long serialVersionUID = -7575653109025406342L;

    private static ArrayList<Vector<Object>> TABBED_COMPONENTS = new ArrayList<Vector<Object>>();

    /*
     * static { Vector initial = new Vector(); TABBED_COMPONENTS.add(initial); }
     */

    /**
     * Sets up just a single collection of bean instances in the first element of
     * the list. This is useful for clients that are using XMLBeans to load beans.
     */
    public static void init() {
        TABBED_COMPONENTS.clear();
        TABBED_COMPONENTS.add(new Vector<Object>());
    }

    /**
     * class variable holding all the beans
     */
    // private static Vector COMPONENTS = new Vector();

    public static final int IDLE = 0;
    public static final int BEAN_EXECUTING = 1;

    /**
     * Holds the bean encapsulated in this instance
     */
    private Object m_bean;
    private int m_x;
    private int m_y;

    /**
     * Removes all beans from containing component
     * 
     * @param container a <code>JComponent</code> value
     */
    public static void removeAllBeansFromContainer(JComponent container, Integer... tab) {

        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);
        }

        if (container != null) {
            if (components != null) {
                for (int i = 0; i < components.size(); i++) {
                    Object tempInstance = components.elementAt(i);
                    Object tempBean = ((BeanInstance) tempInstance).getBean();
                    if (Beans.isInstanceOf(tempBean, JComponent.class)) {
                        container.remove((JComponent) tempBean);
                    }
                }
            }
            container.revalidate();
        }
    }

    /**
     * Adds all beans to the supplied component
     * 
     * @param container a <code>JComponent</code> value
     */
    public static void addAllBeansToContainer(JComponent container, Integer... tab) {
        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);
        }

        if (container != null) {
            if (components != null) {
                for (int i = 0; i < components.size(); i++) {
                    BeanInstance tempInstance = (BeanInstance) components.elementAt(i);
                    Object tempBean = tempInstance.getBean();
                    if (Beans.isInstanceOf(tempBean, JComponent.class)) {
                        container.add((JComponent) tempBean);
                    }
                }
            }
            container.revalidate();
        }
    }

    /**
     * Return the list of displayed beans
     * 
     * @param tab varargs parameter specifying the index of the collection of
     *          beans to return - if omitted then the first (i.e. primary)
     *          collection of beans is returned
     * 
     * @return a vector of beans
     */
    public static Vector<Object> getBeanInstances(Integer... tab) {
        Vector<Object> returnV = null;
        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }
        if (TABBED_COMPONENTS.size() > 0) {
            returnV = TABBED_COMPONENTS.get(index);
        }

        return returnV;
    }

    /**
     * Adds the supplied collection of beans at the supplied index in the list of
     * collections. If the index is not supplied then the primary collection is
     * set (i.e. index 0). Also adds the beans to the supplied JComponent
     * container (if not null)
     * 
     * @param beanInstances a <code>Vector</code> value
     * @param container a <code>JComponent</code> value
     */
    public static void setBeanInstances(Vector<Object> beanInstances, JComponent container, Integer... tab) {
        removeAllBeansFromContainer(container, tab);

        if (container != null) {
            for (int i = 0; i < beanInstances.size(); i++) {
                Object bean = ((BeanInstance) beanInstances.elementAt(i)).getBean();
                if (Beans.isInstanceOf(bean, JComponent.class)) {
                    container.add((JComponent) bean);
                }
            }
            container.revalidate();
            container.repaint();
        }

        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        if (index < TABBED_COMPONENTS.size()) {
            TABBED_COMPONENTS.set(index, beanInstances);
        }

        // COMPONENTS = beanInstances;
    }

    /**
     * Adds the supplied collection of beans to the end of the list of collections
     * and to the JComponent container (if not null)
     * 
     * @param beanInstances the vector of bean instances to add
     * @param container
     */
    public static void addBeanInstances(Vector<Object> beanInstances, JComponent container) {
        // reset(container);

        if (container != null) {
            for (int i = 0; i < beanInstances.size(); i++) {
                Object bean = ((BeanInstance) beanInstances.elementAt(i)).getBean();
                if (Beans.isInstanceOf(bean, JComponent.class)) {
                    container.add((JComponent) bean);
                }
            }
            container.revalidate();
            container.repaint();
        }

        TABBED_COMPONENTS.add(beanInstances);
    }

    /**
     * Remove the vector of bean instances from the supplied index in the list of
     * collections.
     * 
     * @param tab the index of the vector of beans to remove.
     */
    public static void removeBeanInstances(JComponent container, Integer tab) {

        if (tab >= 0 && tab < TABBED_COMPONENTS.size()) {
            System.out.println("Removing vector of beans at index: " + tab);
            removeAllBeansFromContainer(container, tab);
            TABBED_COMPONENTS.remove(tab.intValue());
        }
    }

    /**
     * Renders the textual labels for the beans.
     * 
     * @param gx a <code>Graphics</code> object on which to render the labels
     */
    public static void paintLabels(Graphics gx, Integer... tab) {
        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);
        }

        if (components != null) {
            gx.setFont(new Font(null, Font.PLAIN, 9));
            FontMetrics fm = gx.getFontMetrics();
            int hf = fm.getAscent();
            for (int i = 0; i < components.size(); i++) {
                BeanInstance bi = (BeanInstance) components.elementAt(i);
                if (!(bi.getBean() instanceof Visible)) {
                    continue;
                }
                int cx = bi.getX();
                int cy = bi.getY();
                int width = ((JComponent) bi.getBean()).getWidth();
                int height = ((JComponent) bi.getBean()).getHeight();
                String label = ((Visible) bi.getBean()).getVisual().getText();
                int labelwidth = fm.stringWidth(label);
                if (labelwidth < width) {
                    gx.drawString(label, (cx + (width / 2)) - (labelwidth / 2), cy + height + hf + 2);
                } else {
                    // split label

                    // find mid point
                    int mid = label.length() / 2;
                    // look for split point closest to the mid
                    int closest = label.length();
                    int closestI = -1;
                    for (int z = 0; z < label.length(); z++) {
                        if (label.charAt(z) < 'a') {
                            if (Math.abs(mid - z) < closest) {
                                closest = Math.abs(mid - z);
                                closestI = z;
                            }
                        }
                    }
                    if (closestI != -1) {
                        String left = label.substring(0, closestI);
                        String right = label.substring(closestI, label.length());
                        if (left.length() > 1 && right.length() > 1) {
                            gx.drawString(left, (cx + (width / 2)) - (fm.stringWidth(left) / 2),
                                    cy + height + (hf * 1) + 2);
                            gx.drawString(right, (cx + (width / 2)) - (fm.stringWidth(right) / 2),
                                    cy + height + (hf * 2) + 2);
                        } else {
                            gx.drawString(label, (cx + (width / 2)) - (fm.stringWidth(label) / 2),
                                    cy + height + (hf * 1) + 2);
                        }
                    } else {
                        gx.drawString(label, (cx + (width / 2)) - (fm.stringWidth(label) / 2),
                                cy + height + (hf * 1) + 2);
                    }
                }
            }
        }
    }

    /**
     * Returns a list of start points (if any) in the indexed flow
     * 
     * @param tab varargs integer index of the flow to search for start points.
     *          Defaults to 0 if not supplied.
     * @return a list of BeanInstances who's beans implement Startable
     */
    public static List<BeanInstance> getStartPoints(Integer... tab) {
        List<BeanInstance> startPoints = new ArrayList<BeanInstance>();

        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);

            for (int i = 0; i < components.size(); i++) {
                BeanInstance t = (BeanInstance) components.elementAt(i);
                if (t.getBean() instanceof Startable) {
                    startPoints.add(t);
                }
            }
        }

        return startPoints;
    }

    /**
     * Search for a named bean in the indexed flow
     * 
     * @param beanName the name of the bean to look for
     * @param tab varargs integer index of the flow to search in
     * @return a matching BeanInstance or null if no match was found
     */
    public static BeanInstance findInstance(String beanName, Integer... tab) {
        BeanInstance found = null;

        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);

            for (int i = 0; i < components.size(); i++) {
                BeanInstance t = (BeanInstance) components.elementAt(i);

                if (t.getBean() instanceof BeanCommon) {
                    String bN = ((BeanCommon) t).getCustomName();

                    if (bN.equals(beanName)) {
                        found = t;
                        break;
                    }
                }
            }
        }

        return found;
    }

    /**
     * Looks for a bean (if any) whose bounds contain the supplied point
     * 
     * @param p a point
     * @return a bean that contains the supplied point or null if no bean contains
     *         the point
     */
    public static BeanInstance findInstance(Point p, Integer... tab) {
        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);
        }

        Rectangle tempBounds = new Rectangle();
        for (int i = 0; i < components.size(); i++) {

            BeanInstance t = (BeanInstance) components.elementAt(i);
            JComponent temp = (JComponent) t.getBean();

            tempBounds = temp.getBounds(tempBounds);
            if (tempBounds.contains(p)) {
                return t;
            }
        }
        return null;
    }

    /**
     * Looks for all beans (if any) located within the supplied bounding box. Also
     * adjusts the bounding box to be a tight fit around all contained beans
     * 
     * @param boundingBox the bounding rectangle
     * @return a Vector of BeanInstances
     */
    public static Vector<Object> findInstances(Rectangle boundingBox, Integer... tab) {
        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);
        }

        Graphics gx = null;
        FontMetrics fm = null;

        int centerX, centerY;
        int minX = Integer.MAX_VALUE;
        int minY = Integer.MAX_VALUE;
        int maxX = Integer.MIN_VALUE;
        int maxY = Integer.MIN_VALUE;
        Vector<Object> result = new Vector<Object>();
        for (int i = 0; i < components.size(); i++) {
            BeanInstance t = (BeanInstance) components.elementAt(i);
            centerX = t.getX() + (t.getWidth() / 2);
            centerY = t.getY() + (t.getHeight() / 2);
            if (boundingBox.contains(centerX, centerY)) {
                result.addElement(t);

                // adjust bounding box stuff
                // int hf = 0;
                if (gx == null) {
                    gx = ((JComponent) t.getBean()).getGraphics();
                    gx.setFont(new Font(null, Font.PLAIN, 9));
                    fm = gx.getFontMetrics();
                    // hf = fm.getAscent();
                }
                String label = "";
                if (t.getBean() instanceof Visible) {
                    label = ((Visible) t.getBean()).getVisual().getText();
                }
                int labelwidth = fm.stringWidth(label);
                /*
                 * if (label.length() == 0) { heightMultiplier = 0; }
                 */
                int brx = 0;
                int blx = 0;
                if (centerX - (labelwidth / 2) - 2 < t.getX()) {
                    blx = (centerX - (labelwidth / 2) - 2);
                    brx = centerX + (labelwidth / 2) + 2;
                } else {
                    blx = t.getX() - 2;
                    brx = t.getX() + t.getWidth() + 2;
                }

                if (blx < minX) {
                    minX = blx;
                }
                if (brx > maxX) {
                    maxX = brx;
                }
                if (t.getY() - 2 < minY) {
                    minY = t.getY() - 2;
                }
                if (t.getY() + t.getHeight() + 2 > maxY) {
                    maxY = t.getY() + t.getHeight() + 2;
                }
            }
        }
        boundingBox.setBounds(minX, minY, maxX - minX, maxY - minY);

        return result;
    }

    /**
     * Creates a new <code>BeanInstance</code> instance.
     * 
     * @param container a <code>JComponent</code> to add the bean to
     * @param bean the bean to add
     * @param x the x coordinate of the bean
     * @param y the y coordinate of the bean
     */
    public BeanInstance(JComponent container, Object bean, int x, int y, Integer... tab) {
        m_bean = bean;
        m_x = x;
        m_y = y;
        addBean(container, tab);
    }

    /**
     * Creates a new <code>BeanInstance</code> instance given the fully qualified
     * name of the bean
     * 
     * @param container a <code>JComponent</code> to add the bean to
     * @param beanName the fully qualified name of the bean
     * @param x the x coordinate of the bean
     * @param y th y coordinate of the bean
     */
    public BeanInstance(JComponent container, String beanName, int x, int y, Integer... tab) {
        m_x = x;
        m_y = y;

        // try and instantiate the named component
        try {
            m_bean = Beans.instantiate(null, beanName);
        } catch (Exception ex) {
            ex.printStackTrace();
            return;
        }

        addBean(container, tab);
    }

    /**
     * Remove this bean from the list of beans and from the containing component
     * 
     * @param container the <code>JComponent</code> that holds the bean
     */
    public void removeBean(JComponent container, Integer... tab) {
        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);
        }

        for (int i = 0; i < components.size(); i++) {
            if (components.elementAt(i) == this) {
                System.out.println("Removing bean");
                components.removeElementAt(i);
            }
        }
        if (container != null) {
            container.remove((JComponent) m_bean);
            container.revalidate();
            container.repaint();
        }
    }

    public static void appendBeans(JComponent container, Vector<Object> beans, int tab) {
        if (TABBED_COMPONENTS.size() > 0 && tab < TABBED_COMPONENTS.size()) {
            Vector<Object> components = TABBED_COMPONENTS.get(tab);
            //

            for (int i = 0; i < beans.size(); i++) {
                components.add(beans.get(i));
                if (container != null) {
                    Object bean = ((BeanInstance) beans.elementAt(i)).getBean();
                    if (Beans.isInstanceOf(bean, JComponent.class)) {
                        container.add((JComponent) bean);
                    }
                }
            }

            if (container != null) {
                container.revalidate();
                container.repaint();
            }
        }
    }

    /**
     * Adds this bean to the global list of beans and to the supplied container.
     * The constructor calls this method, so a client should not need to unless
     * they have called removeBean and then wish to have it added again.
     * 
     * @param container the Component on which this BeanInstance will be displayed
     */
    public void addBean(JComponent container, Integer... tab) {

        int index = 0;
        if (tab.length > 0) {
            index = tab[0].intValue();
        }

        Vector<Object> components = null;
        if (TABBED_COMPONENTS.size() > 0 && index < TABBED_COMPONENTS.size()) {
            components = TABBED_COMPONENTS.get(index);
        }

        // do nothing if we are already in the list
        if (components.contains(this)) {
            return;
        }

        // Ignore invisible components
        if (!Beans.isInstanceOf(m_bean, JComponent.class)) {
            System.out.println("Component is invisible!");
            return;
        }

        components.addElement(this);

        // Position and layout the component
        JComponent c = (JComponent) m_bean;
        Dimension d = c.getPreferredSize();
        int dx = (int) (d.getWidth() / 2);
        int dy = (int) (d.getHeight() / 2);
        m_x -= dx;
        m_y -= dy;
        c.setLocation(m_x, m_y);
        // c.doLayout();
        c.validate();
        // bp.addBean(c);
        // c.repaint();
        if (container != null) {
            container.add(c);
            container.revalidate();
        }
    }

    /**
     * Gets the bean encapsulated in this instance
     * 
     * @return an <code>Object</code> value
     */
    public Object getBean() {
        return m_bean;
    }

    /**
     * Gets the x coordinate of this bean
     * 
     * @return an <code>int</code> value
     */
    public int getX() {
        return m_x;
    }

    /**
     * Gets the y coordinate of this bean
     * 
     * @return an <code>int</code> value
     */
    public int getY() {
        return m_y;
    }

    /**
     * Gets the width of this bean
     * 
     * @return an <code>int</code> value
     */
    public int getWidth() {
        return ((JComponent) m_bean).getWidth();
    }

    /**
     * Gets the height of this bean
     * 
     * @return an <code>int</code> value
     */
    public int getHeight() {
        return ((JComponent) m_bean).getHeight();
    }

    /**
     * Set the x and y coordinates of this bean
     * 
     * @param newX the x coordinate
     * @param newY the y coordinate
     */
    public void setXY(int newX, int newY) {
        setX(newX);
        setY(newY);
        if (getBean() instanceof MetaBean) {
            ((MetaBean) getBean()).shiftBeans(this, false);
        }
    }

    /**
     * Sets the x coordinate of this bean
     * 
     * @param newX an <code>int</code> value
     */
    public void setX(int newX) {
        m_x = newX;
        ((JComponent) m_bean).setLocation(m_x, m_y);
        ((JComponent) m_bean).validate();
    }

    /**
     * Sets the y coordinate of this bean
     * 
     * @param newY an <code>int</code> value
     */
    public void setY(int newY) {
        m_y = newY;
        ((JComponent) m_bean).setLocation(m_x, m_y);
        ((JComponent) m_bean).validate();
    }
}