/* */ 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 + ")"; } }