/*
* 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.
*/
/*
* BeanInstance.java
* Copyright (C) 2002 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.Vector;
import java.util.ArrayList;
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: 7155 $
* @since 1.0
*/
public class BeanInstance
implements Serializable {
/** for serialization */
private static final long serialVersionUID = -7575653109025406342L;
private static ArrayList<Vector> TABBED_COMPONENTS =
new ArrayList<Vector>();
/* 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());
}
/**
* 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 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.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 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 getBeanInstances(Integer... tab) {
Vector 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 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 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 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);
}
}
}
}
}
/**
* 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 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 findInstances(Rectangle boundingBox, Integer... tab) {
int index = 0;
if (tab.length > 0) {
index = tab[0].intValue();
}
Vector 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 startX, startY, endX, endY;
startX = (int)boundingBox.getX();
startY = (int)boundingBox.getY();
endX = (int)boundingBox.getMaxX();
endY = (int)boundingBox.getMaxY();
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
Vector result = new Vector();
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);
int heightMultiplier = (labelwidth > t.getWidth())
? 2
: 1;
/*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 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 ((BeanInstance)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 beans, int tab) {
if (TABBED_COMPONENTS.size() > 0 && tab < TABBED_COMPONENTS.size()) {
Vector 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 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();
}
}