/*
*/
package cs3744.gui;
import cs3744.gui.event.VTEvent;
import cs3744.gui.event.VTKeyEvent;
import cs3744.gui.event.VTKeyListener;
import cs3744.gui.event.VTMouseEvent;
import cs3744.gui.event.VTMouseListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
/**
* A component is an object having a graphical representation that can be
* displayed on the screen and that can interact with the user.
* Examples of components are the buttons, checkboxes, and scrollbars of
* a typical graphical user interface.
* The VTComponent class is the abstract superclass of
* the nonmenu-related VTGUI components.
* Class Component can also be extended directly to create a lightweight
* component.
* A lightweight component is a component that is not associated with
* a native opaque window.
*
* @author Denis Gracanin
* @version 2.0
*/
public abstract class VTComponent implements Serializable {
private VTColor background, foreground;
private boolean visible;
private VTPoint location;
private VTDimension size;
private VTComponent parent;
private String name;
private VTFont font;
private ArrayList listenersVTKey;
private ArrayList listenersVTMouse;
private boolean valid;
/**
* Constructs a new component.
*
* Class VTComponent can be extended directly to create
* a lightweight component that does not utilize an opaque native window.
* A lightweight component must be hosted by a native container somewhere
* higher up in the component tree
* (for example, by a VTFrame object).
*/
public VTComponent() {
background = VTColor.GRAY;
foreground = VTColor.BLACK;
visible = true;
location = new VTPoint(0, 0);
size = new VTDimension(0, 0);
parent = null;
name = "";
font = new VTFont();
listenersVTKey = new ArrayList();
listenersVTMouse = new ArrayList();
valid = true;
}
/**
* Gets the background color of this component.
*
* @return this component's background color;
* if this component does not have a background color,
* the background color of its parent is returned.
*/
public VTColor getBackground() {
if (background != null) {
return background;
} else if (parent != null) {
return parent.getBackground();
} else {
return null;
}
}
/**
* Sets the background color of this component.
*
* @param background the color to become this component's color;
* if this parameter is null, then this component
* will inherit the background color of its parent.
*/
public void setBackground(VTColor background) {
this.background = (background == null ? parent.getBackground() : background);
}
/**
* Gets the foreground color of this component.
*
* @return this component's foreground color;
* if this component does not have a foreground color,
* the foreground color of its parent is returned.
*/
public VTColor getForeground() {
if (foreground != null) {
return foreground;
} else if (parent != null) {
return parent.getForeground();
} else {
return null;
}
}
/**
* Sets the foreground color of this component.
*
* @param foreground
* the color to become this component's foreground color;
* if this parameter is null then this component will inherit
* the foreground color of its parent.
*/
public void setForeground(VTColor foreground) {
this.foreground = foreground;
}
/**
*Gets the location of this component in the form of a point specifying
* the component's top-left corner.
* The location will be relative to the window's coordinate space.
*
* @return an instance of VTPoint representing the top-left
* corner of the component's bounds in the coordinate space of
* the component's parent.
*/
public VTPoint getLocation() {
return location;
}
/**
* Moves this component to a new location.
* The top-left corner of the new location is specified by
* point p.
* Point p is given in the window's coordinate space.
*
* @param location
*/
public void setLocation(VTPoint location) {
this.location = location;
}
/**
* Gets the parent of this component.
*
* @return the parent container of this component.
*/
public VTComponent getParent() {
return parent;
}
void setParent(VTComponent parent) {
this.parent = parent;
}
/**
* Returns the size of this component in the form of
* a VTDimension object.
* The height field of the VTDimension object
* contains this component's height, and the width field of
* the VTDimension object contains this component's width.
*
* @return a VTDimension object that indicates the size of
* this component.
*/
public VTDimension getSize() {
return size;
}
/**
* Resizes this component so that it has width d.width and
* height d.height.
*
* @param size the dimension specifying the new size of this component.
*/
public void setSize(VTDimension size) {
this.size = size;
}
/**
* Determines whether this component should be visible when its parent
* is visible.
* Components are initially visible, with the exception of top level
* components such as VTFrame objects.
*
* @return true if the component is visible,
* false otherwise.
*/
public boolean isVisible() {
return visible;
}
/**
* Shows or hides this component depending on the value of parameter
* visible.
*
* @param visible if true, shows this component; otherwise,
* hides this component.
*/
public void setVisible(boolean visible) {
this.visible = visible;
}
/**
* Gets the name of the component.
*
* @return this component's name.
*/
public String getName() {
return name;
}
/**
* Sets the name of the component to the specified string.
*
* @param name the string that is to be this component's name.
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the font of this component.
*
* @return this component's font; if a font has not been set for this
* component, the font of its parent is returned
*/
public VTFont getFont() {
if (font != null) {
return font;
} else if (parent != null) {
return parent.getFont();
} else {
return null;
}
}
/**
* Sets the font of this component.
*
* @param font the font to become this component's font;
* if this parameter is null then this component will inherit
* the font of its parent.
*/
public void setFont(VTFont font) {
this.font = font;
}
/**
* Paints this component.
*
* This method is called when the contents of the component
* should be painted;
* such as when the component is first being shown or is damaged
* and in need of repair.
*
* For performance reasons, VTComponents with zero width or
* height aren't considered to need painting when they are first shown,
* and also aren't considered to need repair.
*
* @param drawable the graphics context to use for painting.
*/
public void paint(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
int width = drawable.getWidth();
int height = drawable.getHeight();
if (height <= 0 || width <= 0) {
return;
}
float x = (float) location.getX() / width;
float y = (float) (height - location.getY()) / height;
float w = (float) size.getWidth() / width;
float h = (float) size.getHeight() / height;
gl.glColor3f(background.getRed(), background.getGreen(), background.getBlue());
gl.glBegin(GL2.GL_POLYGON);
gl.glVertex3f(x, y, 0.0f);
gl.glVertex3f(x, y - h, 0.0f);
gl.glVertex3f(x + w, y - h, 0.0f);
gl.glVertex3f(x + w, y, 0.0f);
gl.glEnd();
}
/**
* Prompts the layout manager to lay out this component.
* This is usually called when the component (more specifically, container)
* is validated.
*/
public void doLayout() {
valid = true;
}
/**
*
* @param l
*/
public void addVTKeyListener(VTKeyListener l) {
if (l != null) {
listenersVTKey.add(l);
}
}
/**
*
* @param l
*/
public void removeVTKeyListener(VTKeyListener l) {
if (l != null) {
listenersVTKey.remove(l);
}
}
/**
*
* @return
*/
public VTKeyListener[] getVTKeyListeners() {
return listenersVTKey.toArray(new VTKeyListener[0]);
}
/**
*
* @param l
*/
public void addVTMouseListener(VTMouseListener l) {
if (l != null) {
listenersVTMouse.add(l);
}
}
/**
*
* @param l
*/
public void removeVTMouseListener(VTMouseListener l) {
if (l != null) {
listenersVTMouse.remove(l);
}
}
/**
*
* @return
*/
public VTMouseListener[] getVTMouseListeners() {
return listenersVTMouse.toArray(new VTMouseListener[0]);
}
/**
*
* @param e
*/
public void dispatchEvent(VTEvent e) {
processEvent(e);
}
/**
*
* @param e
*/
protected void processEvent(VTEvent e) {
if (e instanceof VTKeyEvent && !(((VTKeyEvent) e).isConsumed())) {
processVTKeyEvent((VTKeyEvent) e);
}
else if (e instanceof VTMouseEvent && !(((VTMouseEvent) e).isConsumed())) {
processVTMouseEvent((VTMouseEvent) e);
}
}
/**
*
* @param e
*/
protected void processVTMouseEvent(VTMouseEvent e) {
if (contains(e.getX(), e.getY())) {
e.setSource(this);
Iterator iterator = listenersVTMouse.iterator();
while (iterator.hasNext()) {
((VTMouseListener) iterator.next()).mouseClicked(e);
}
e.consume();
}
}
/**
*
* @param e
*/
protected void processVTKeyEvent(VTKeyEvent e) {
}
/**
*
* @param x
* @param y
* @return
*/
public boolean contains(int x, int y) {
if (location.getX() <= x
&& x < location.getX() + size.getWidth()
&& location.getY() <= y
&& y < location.getY() + size.getHeight()) {
return true;
} else {
return false;
}
}
/**
*
*/
public void invalidate() {
valid = false;
if (parent != null) {
parent.invalidate();
}
}
/**
*
* @return
*/
public boolean isValid() {
return valid;
}
/**
* Returns a string representation of the object in the form of
* VTComponent(location - size).
*
* @return a string representation of the object.
*/
@Override
public String toString() {
return "VTComponent(" + location + " - " + size + ")";
}
}