acm.graphics.GContainer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javakarel Show documentation
Show all versions of javakarel Show documentation
This the original Stanford Karel for Java, packaged for Maven. ACM Library is included. See also https://cs.stanford.edu/people/eroberts/karel-the-robot-learns-java.pdf
The newest version!
/*
* @(#)GContainer.java 1.99.1 08/12/08
*/
// ************************************************************************
// * Copyright (c) 2008 by the Association for Computing Machinery *
// * *
// * The Java Task Force seeks to impose few restrictions on the use of *
// * these packages so that users have as much freedom as possible to *
// * use this software in constructive ways and can make the benefits of *
// * that work available to others. In view of the legal complexities *
// * of software development, however, it is essential for the ACM to *
// * maintain its copyright to guard against attempts by others to *
// * claim ownership rights. The full text of the JTF Software License *
// * is available at the following URL: *
// * *
// * http://www.acm.org/jtf/jtf-software-license.pdf *
// * *
// ************************************************************************
// REVISION HISTORY
//
// -- V2.0 --
// Code cleanup 28-May-07 (ESR)
// 1. Factored out common implementation of GObjectList.
// 2. Moved GIterator code to this module.
package acm.graphics;
import acm.util.*;
import java.awt.*;
import java.io.*;
import java.util.*;
/* Interface: GContainer */
/**
* Defines the functionality of an object that can serve as the parent
* of a GObject
.
*/
public interface GContainer {
/* Constant: BACK_TO_FRONT */
/** Specifies that iterators should run from back to front */
public static final int BACK_TO_FRONT = 0;
/* Constant: FRONT_TO_BACK */
/** Specifies that iterators should run from front to back */
public static final int FRONT_TO_BACK = 1;
/* Method: add(gobj) */
/**
* Adds a new graphical object to this container.
*
* Example: gc.add(gobj);
* @param gobj The graphical object to add
*/
public void add(GObject gobj);
/* Method: add(gobj, x, y) */
/**
* Adds the graphical object to this canvas and sets its location
* to the point (x
, y
).
*
* Example: gc.add(gobj, x, y);
* @param gobj The graphical object to add
* @param x The new x-coordinate for the object
* @param y The new y-coordinate for the object
*/
public void add(GObject gobj, double x, double y);
/* Method: add(gobj, pt) */
/**
* Adds the graphical object to this canvas and sets its location to the specified point.
*
* Example: gc.add(gobj, pt);
* @param gobj The graphical object to add
* @param pt A GPoint
object giving the coordinates of the point
*/
public void add(GObject gobj, GPoint pt);
/* Method: remove(gobj) */
/**
* Removes a graphical object from this container.
*
* Example: gc.remove(gobj);
* @param gobj The graphical object to remove
*/
public void remove(GObject gobj);
/* Method: removeAll() */
/**
* Removes all graphical objects from this container.
*
* Example: gc.removeAll();
*/
public void removeAll();
/* Method: getElementCount() */
/**
* Returns the number of graphical objects stored in this GCanvas
.
*
* Example: int n = gc.getElementCount();
* @return The number of graphical objects in this GCanvas
*/
public int getElementCount();
/* Method: getElement(index) */
/**
* Returns the graphical object at the specified index, numbering from back
* to front in the the z dimension.
*
* Example: GObject gobj = gc.getElement(index);
* @param index The index of the component to return
* @return The graphical object at the specified index
*/
public GObject getElement(int index);
/* Method: getElementAt(x, y) */
/**
* Returns the topmost graphical object that contains the point
* (x
, y
), or null
if no such
* object exists.
*
* Example: GObject gobj = gc.getElementAt(x, y);
* @param x The x-coordinate of the point being tested
* @param y The y-coordinate of the point being tested
* @return The graphical object at the specified location, or null
* if no such object exists.
*/
public GObject getElementAt(double x, double y);
/* Method: getElementAt(pt) */
/**
* Returns the topmost graphical object that contains the specified point,
* or null
if no such object exists.
*
* Example: GObject gobj = gc.getElementAt(pt);
* @param pt The coordinates being tested
* @return The graphical object at the specified location, or null
* if no such object exists
*/
public GObject getElementAt(GPoint pt);
}
/* Package class: GObjectList */
/**
* This class implements a synchronized list of GObject
values
* that is shared by both GCompound
and GCanvas
.
* The list includes two sets of objects: one for the ordered list in the
* container and another for objects that are enabled to receive mouse
* events.
*/
class GObjectList implements Serializable {
/* Constructor: new GObjectList(container) */
/**
* Creates a new GObjectList
with no elements.
*
* @param container The GCanvas
or GCompound
that owns this list.
*/
public GObjectList(GContainer container) {
parent = container;
contents = new ArrayList();
if (parent instanceof GCanvas) enabledList = new ArrayList();
}
/* Method: add(gobj) */
/**
* Adds the specified GObject
to the end of the contents list,
* and includes it in the enabled list if mouse events are enabled.
*/
public synchronized void add(GObject gobj) {
if (gobj.getParent() != null) gobj.getParent().remove(gobj);
gobj.setParent(parent);
contents.add(gobj);
if (enabledList != null && gobj.areMouseListenersEnabled()) {
enabledList.add(gobj);
}
}
/* Method: remove(gobj) */
/**
* Removes the specified object from the list.
*/
public synchronized void remove(GObject gobj) {
contents.remove(gobj);
gobj.setParent(null);
if (enabledList != null) enabledList.remove(gobj);
}
/* Method: removeAll() */
/**
* Removes all objects from the list.
*/
public synchronized void removeAll() {
contents.clear();
if (enabledList != null) enabledList.clear();
}
/* Method: getElementCount() */
/**
* Returns the number of elements in the list.
*/
public int getElementCount() {
return contents.size();
}
/* Method: getElement(index) */
/**
* Returns the graphical object at the specified index, numbering from back
* to front in the the z dimension.
*/
public GObject getElement(int index) {
return contents.get(index);
}
/* Method: getElementAt(x, y, requireEnabled) */
/**
* Returns the topmost graphical object that contains the point
* (x
, y
), or null
if no such
* object exists.
*/
public synchronized GObject getElementAt(double x, double y, boolean requireEnabled) {
ArrayList list = (requireEnabled) ? enabledList : contents;
for (int i = list.size() - 1; i >= 0; i--) {
GObject gobj = list.get(i);
if (gobj.contains(x, y)) return gobj;
}
return null;
}
/* Method: sendToFront(gobj) */
/**
* Implements the sendToFront
function from the GContainer
* interface.
*/
public synchronized void sendToFront(GObject gobj) {
int index = contents.indexOf(gobj);
if (index >= 0) {
contents.remove(index);
contents.add(gobj);
}
}
/* Method: sendToBack(gobj) */
/**
* Implements the sendToBack
function from the GContainer
* interface.
*/
public synchronized void sendToBack(GObject gobj) {
int index = contents.indexOf(gobj);
if (index >= 0) {
contents.remove(index);
contents.add(0, gobj);
}
}
/* Method: sendForward(gobj) */
/**
* Implements the sendForward
function from the GContainer
* interface.
*/
public synchronized void sendForward(GObject gobj) {
int index = contents.indexOf(gobj);
if (index >= 0) {
contents.remove(index);
contents.add(Math.min(contents.size(), index + 1), gobj);
}
}
/* Method: sendBackward(gobj) */
/**
* Implements the sendBackward
function from the GContainer
* interface.
*/
public synchronized void sendBackward(GObject gobj) {
int index = contents.indexOf(gobj);
if (index >= 0) {
contents.remove(index);
contents.add(Math.max(0, index - 1), gobj);
}
}
/* Method: getBounds() */
/**
* Returns the bounding rectangle for the objects in the list.
*/
public synchronized GRectangle getBounds() {
GRectangle bounds = new GRectangle();
int nElements = contents.size();
for (int i = 0; i < nElements; i++) {
if (i == 0) {
bounds = new GRectangle(contents.get(i).getBounds());
} else {
bounds.add(contents.get(i).getBounds());
}
}
return bounds;
}
/* Method: contains(x, y) */
/**
* Checks to see whether a point is "inside" one of the objects on the list.
*/
public synchronized boolean contains(double x, double y) {
int nElements = contents.size();
for (int i = 0; i < nElements; i++) {
if (contents.get(i).contains(x, y)) return true;
}
return false;
}
/* Method: mapPaint(g) */
/**
* Paints all the elements of this container using the graphics context g
.
*/
public synchronized void mapPaint(Graphics g) {
int nElements = contents.size();
for (int i = 0; i < nElements; i++) {
contents.get(i).paintObject(g);
}
}
/* Method: areMouseListenersEnabled() */
/**
* Returns true
if mouse listeners have ever been assigned to
* this object or to any of the contained objects.
*/
public synchronized boolean areMouseListenersEnabled() {
int nElements = contents.size();
for (int i = 0; i < nElements; i++) {
GObject gobj = contents.get(i);
if (gobj.areMouseListenersEnabled()) return true;
}
return false;
}
/* Method: updateEnabledList() */
/**
* Reconstructs the enabledList list in the correct order.
*/
public synchronized void updateEnabledList() {
enabledList.clear();
int nElements = contents.size();
for (int i = 0; i < nElements; i++) {
GObject gobj = contents.get(i);
if (gobj.areMouseListenersEnabled()) enabledList.add(gobj);
}
}
/* Private instance variables */
private GContainer parent;
private ArrayList contents;
private ArrayList enabledList;
}
/* Package class: GIterator */
/**
* Implements an iterator class for any object that implements
* GContainer
(i.e., GCanvas
* and GCompound
). The usual method
* for using this class is to write something like
*
*
* for (Iterator<GObject> i = gc.iterator(direction); i.hasNext(); )
*
*
* where gc
is the graphic container. The enumeration supports
* traversal in two directions. By default, it starts with the front
* element and works toward the back (as would be appropriate, for
* example, when trying to find the topmost component for a mouse click).
* You can, however, also process the elements of the container from back
* to front (as would be useful when drawing elements of the container,
* when the front objects should be drawn last). To specify the direction
* of the traversal, specify either GContainer.FRONT_TO_BACK
or
* GContainer.BACK_TO_FRONT
in the iterator
call.
*/
class GIterator implements Iterator {
/* Constructor: GIterator(container, direction) */
/**
* Creates a new GIterator
that runs through the
* container in the specified direction (GContainer.FRONT_TO_BACK
* or GContainer.BACK_TO_FRONT
).
*
* Example: Iterator i = new GIterator(container, direction);
* @param container The GContainer
whose elements the iterator should return
* @param direction The direction in which to process the elements
*/
public GIterator(GContainer container, int direction) {
switch (direction) {
case GContainer.FRONT_TO_BACK: case GContainer.BACK_TO_FRONT:
dir = direction;
break;
default:
throw new ErrorException("Illegal direction for iterator");
}
cont = container;
index = 0;
nElements = container.getElementCount();
}
/* Method: hasNext() */
/**
* Returns true
if the iterator has more elements. Implements
* the hasNext
method for the Iterator
interface.
*
* Example: while (i.hasNext()) . . .
* @return true
if the iterator has more elements, false
otherwise
*/
public boolean hasNext() {
return index < nElements;
}
/* Method: next() */
/**
* Returns the next element from the iterator. Implements the next
* method for the Iterator
interface.
*
* Example: Object element = i.next();
* @return The next element from the iterator
*/
public GObject next() {
if (dir == GContainer.FRONT_TO_BACK) {
return cont.getElement(nElements - index++ - 1);
} else {
return cont.getElement(index++);
}
}
/* Method: nextElement() */
/**
* Returns the next element from the iterator as a GObject
. This
* method is callable only if the iterator is declared as a GIterator
.
*
* Example: GObject element = i.nextElement();
* @return The next element from the iterator as a GObject
*/
public GObject nextElement() {
return next();
}
/* Method: remove() */
/**
* Removes the current element from its container. Implements the remove
* method for the Iterator
interface.
*
* Example: i.remove();
*/
public void remove() {
if (dir == GContainer.FRONT_TO_BACK) {
cont.remove(cont.getElement(nElements - --index - 1));
} else {
cont.remove(cont.getElement(--index));
}
nElements--;
}
/* Private instance variables */
private GContainer cont;
private int dir;
private int index;
private int nElements;
}