All Downloads are FREE. Search and download functionalities are using the official Maven repository.

acm.program.GraphicsProgram Maven / Gradle / Ivy

Go to download

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!
/*
 * @(#)GraphicsProgram.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 30-Jan-07 (ESR)
//   1. Renamed instance variable "listener" to "eventListener" to avoid
//      warning messages from some compilers.
//   2. Removed unnecessary startHook code.

package acm.program;

import acm.graphics.*;
import acm.util.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
import java.util.*;

/**
 * This class is a standard subclass of Program
 * whose principal window is used for drawing graphics.
 */
public abstract class GraphicsProgram extends Program {

/* Constructor: GraphicsProgram() */
/**
 * Creates a new graphics program.
 *
 * Example: GraphicsProgram program = new GraphicsProgram();
 */
	protected GraphicsProgram() {
		eventListener = new GProgramListener(this);
		gc = createGCanvas();
		gc.addMouseListener(eventListener);
		if (eventListener.needsMouseMotionListeners()) {
			gc.addMouseMotionListener(eventListener);
		}
		add(gc, CENTER);
		validate();
	}

/* Method: run() */
/**
 * Specifies the code to be executed as the program runs.
 * The run method is required for applications that have
 * a thread of control that runs even in the absence of user actions,
 * such as a program that uses console interation or that involves
 * animation.  GUI-based programs that operate by setting up an initial
 * configuration and then wait for user events usually do not specify a
 * run method and supply a new definition for init
 * instead.
 */
	public void run() {
		/* Empty */
	}

/* Method: init() */
/**
 * Specifies the code to be executed as startup time before the
 * run method is called.  Subclasses can override this
 * method to perform any initialization code that would ordinarily
 * be included in an applet init method.  In general,
 * subclasses will override init in GUI-based programs
 * where the program simply sets up an initial state and then waits
 * for events from the user.  The run method is required
 * for applications in which there needs to be some control thread
 * while the program runs, as in a typical animation.
 *
 * Example: program.init();
 */
	public void init() {
		/* Empty */
	}

/* Method: getGCanvas() */
/**
 * Returns the GCanvas object used by this program.
 *
 * Example: GCanvas gc = getGCanvas();
 * @return The GCanvas object used by the program
 */
	public GCanvas getGCanvas() {
		return gc;
	}

/* Method: add(gobj) */
/**
 * Adds a new graphical object to this container.
 *
 * Example: add(gobj);
 * @param gobj The graphical object to add
 */
	public void add(GObject gobj) {
		gc.add(gobj);
	}

/* Method: add(gobj, x, y) */
/**
 * Adds the graphical object to the canvas and sets its location
 * to the point (xy).
 *
 * Example: 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 final void add(GObject gobj, double x, double y) {
		gobj.setLocation(x, y);
		add(gobj);
	}

/* Method: add(gobj, pt) */
/**
 * Adds the graphical object to the canvas and sets its location to the specified point.
 *
 * Example: add(gobj, pt);
 * @param gobj The graphical object to add
 * @param pt The new coordinates of the point
 */
	public final void add(GObject gobj, GPoint pt) {
		gobj.setLocation(pt);
		add(gobj);
	}

/* Method: add(comp, x, y) */
/**
 * Adds the component to the canvas and sets its location
 * to the point (xy).
 *
 * Example: add(comp, x, y);
 * @param comp The component to add
 * @param x The new x-coordinate for the object
 * @param y The new y-coordinate for the object
 */
	public final void add(Component comp, double x, double y) {
		comp.setLocation(GMath.round(x), GMath.round(y));
		gc.add(comp);
	}

/* Method: add(comp, pt) */
/**
 * Adds the component to the canvas and sets its location to the specified point.
 *
 * Example: add(comp, pt);
 * @param comp The component to add
 * @param pt A GPoint object giving the coordinates of the point
 */
	public final void add(Component comp, GPoint pt) {
		add(comp, pt.getX(), pt.getY());
	}

/* Method: remove(gobj) */
/**
 * Removes a graphical object from this container.
 *
 * Example: remove(gobj);
 * @param gobj The graphical object to remove
 */
	public void remove(GObject gobj) {
		gc.remove(gobj);
	}

/* Method: removeAll() */
/**
 * Removes all graphical objects from this container.  Note that this
 * definition overrides the Container version of
 * removeAll, which is replaced by
 * removeAllComponents.
 *
 * Example: removeAll();
 */
	public void removeAll() {
		gc.removeAll();
	}

/* Method: getElementCount() */
/**
 * Returns the number of graphical objects stored in this GCanvas.
 *
 * Example: int n = getElementCount();
 * @return The number of graphical objects in this GCanvas
 */
	public int getElementCount() {
		return gc.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 = getElement(index);
 * @param index The index of the component to return
 * @return The graphical object at the specified index
 */
	public GObject getElement(int index) {
		return gc.getElement(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 = program.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) {
		return gc.getElementAt(x, y);
	}

/* Method: getElementAt(pt) */
/**
 * Returns the topmost graphical object that contains the specified point,
 * or null if no such object exists.
 *
 * Example: GObject gobj = program.getElementAt(pt);
 * @param pt The coordinates being tested
 * @return The graphical object at the specified location, or null
 *         if no such object exists
 */
	public final GObject getElementAt(GPoint pt) {
		return getElementAt(pt.getX(), pt.getY());
	}

/* Method: iterator() */
/**
 * Returns an Iterator that cycles through the elements within
 * this container in the default direction, which is from back to front.
 * You can also run the iterator in the opposite direction by using the
 * iterator(
 * direction) form of this method.
 *
 * 

Applets that want to run in browsers, however, should avoid using * this method, because Iterator is not supported on 1.1 browsers. * For maximum portability, you should rely instead on the * getElementCount * and getElement methods, * which provide the same functionality in a browser-compatible way. * * Example: Iterator i = iterator(); * @return An Iterator ranging over the elements of the * container from back to front */ public Iterator iterator() { return gc.iterator(); } /* Method: iterator(direction) */ /** * Returns an Iterator that cycles through the elements * within this container in the specified direction, which must be one * of the constants FRONT_TO_BACK * or BACK_TO_FRONT * from the GContainer interface.

* * for (Iterator<GObject> i = iterator(direction); i.hasNext(); ) * *

Applets that want to run in browsers, however, should avoid using * this method, because Iterator is not supported on 1.1 browsers. * For maximum portability, you should rely instead on the * getElementCount * and getElement methods, * which provide the same functionality in a browser-compatible way. * * Example: Iterator i = iterator(direction); * @param direction direction no idea * @return An Iterator ranging over the elements of the * container in the specified direction */ public Iterator iterator(int direction) { return gc.iterator(direction); } /* Method: addMouseListeners() */ /** * Adds the program as both a MouseListener and MouseMotionListener * to the canvas. * * Example: addMouseListeners(); */ public void addMouseListeners() { gc.addMouseListener(this); gc.addMouseMotionListener(this); } /* Method: addMouseListeners(listener) */ /** * Adds the specified listener as a MouseListener and/or * MouseMotionListener, as appropriate, to the canvas. * * Example: addMouseListeners(listener); * @param listener A listener object that is either a MouseListener, a * MouseMotionListener, or both */ public void addMouseListeners(EventListener listener) { boolean ok = false; if (listener instanceof MouseListener) { gc.addMouseListener((MouseListener) listener); ok = true; } if (listener instanceof MouseMotionListener) { gc.addMouseMotionListener((MouseMotionListener) listener); ok = true; } if (!ok) throw new ErrorException("addMouseListeners: Illegal listener"); } /* Method: addKeyListeners() */ /** * Adds the program as a KeyListener to the canvas. * * Example: addKeyListeners(); */ public void addKeyListeners() { gc.addKeyListener(this); } /* Method: addKeyListeners(listener) */ /** * Adds the specified listener as a KeyListener to the canvas. * * Example: addKeyListeners(listener); * @param listener A KeyListener object */ public void addKeyListeners(KeyListener listener) { gc.addKeyListener(listener); } /* Method: waitForClick() */ /** * Waits for a mouse click in the window before proceeding. * * Example: waitForClick(); */ public void waitForClick() { eventListener.waitForClick(); } /* Method: repaint() */ /** * Signals a need to repaint this window. * */ public void repaint() { gc.repaint(); super.repaint(); } /* Method: removeAllComponents() */ /** * Removes all components from this container. * * Example: removeAllComponents(); * */ public void removeAllComponents() { super.removeAll(); } /* Override method: setBackground(bg) */ /** * Sets the background color of the GCanvas. * * Example: setBackground(bg); * @param bg The new background color * */ public void setBackground(Color bg) { super.setBackground(bg); if (gc != null) gc.setBackground(bg); } /* Static method: startGraphicsProgram(gobj, args) */ /** * Creates a GraphicsProgram containing the specified GObject * and then starts it. This code is called only by the start method in * GObject. * * Example: startGraphicsProgram(gobj, args); * @param gobj The object to be inserted into the GraphicsProgram * @param args The array of arguments * */ public static void startGraphicsProgram(GObject gobj, String[] args) { GraphicsProgram program = new GObjectProgram(); program.setStartupObject(gobj); program.start(args); } /* Inherited method: print(value) */ /** * @inherited Program#void print(String value) * Displays the argument value on the console, leaving the cursor at the end of * the output. */ /* Inherited method: println() */ /** * @inherited Program#void println() * Advances the console cursor to the beginning of the next line. */ /* Inherited method: println(value) */ /** * @inherited Program#void println(String value) * Displays the argument value on the console and then advances the cursor * to the next line. */ /* Inherited method: readLine() */ /** * @inherited Program#String readLine() * Reads and returns a line of input from the console. */ /* Inherited method: readLine(prompt) */ /** * @inherited Program#String readLine(String prompt) * Prompts the user for a line of input. */ /* Inherited method: readInt() */ /** * @inherited Program#int readInt() * Reads and returns an integer value from the user. */ /* Inherited method: readInt(prompt) */ /** * @inherited Program#int readInt(String prompt) * Prompts the user to enter an integer. */ /* Inherited method: readDouble() */ /** * @inherited Program#double readDouble() * Reads and returns a double-precision value from the user. */ /* Inherited method: readDouble(prompt) */ /** * @inherited Program#double readDouble(String prompt) * Prompts the user to enter a double-precision number, which is * returned as the value of this method. */ /* Inherited method: readBoolean() */ /** * @inherited Program#boolean readBoolean() * Reads and returns a boolean value (true or false). */ /* Inherited method: readBoolean(prompt) */ /** * @inherited Program#boolean readBoolean(String prompt) * Prompts the user to enter a boolean value. */ /* Inherited method: readBoolean(prompt, trueLabel, falseLabel) */ /** * @inherited Program#boolean readBoolean(String prompt, String trueLabel, String falseLabel) * Prompts the user to enter a boolean value, which is matched against the * labels provided. */ /* Inherited method: getConsole() */ /** * @inherited Program#IOConsole getConsole() * Returns the console associated with this program. */ /* Inherited method: getDialog() */ /** * @inherited Program#IODialog getDialog() * Returns the dialog used for user interaction. */ /* Inherited method: getReader() */ /** * @inherited Program#BufferedReader getReader() * Returns a BufferedReader whose input comes from the console. */ /* Inherited method: getWriter() */ /** * @inherited Program#PrintWriter getWriter() * Returns a PrintWriter whose output is directed to the console. */ /* Inherited method: setTitle(title) */ /** * @inherited Program#void setTitle(String title) * Sets the title of this program. */ /* Inherited method: getTitle() */ /** * @inherited Program#String getTitle() * Gets the title of this program. */ /* Inherited method: pause(milliseconds) */ /** * @inherited Program#void pause(double milliseconds) * Delays the calling thread for the specified time, which is expressed in * milliseconds. */ /* Factory method: createGCanvas() */ /** * Creates the GCanvas used by the GraphicsProgram. Subclasses can * override this method to create their own GCanvas types. * * Example: GCanvas gc = program.createGCanvas(); * @return The GCanvas to be inserted into the program * */ protected GCanvas createGCanvas() { return new GCanvas(); } /* Protected method: endHook() */ /** * Ensures that the window is repainted at the end of the program. */ protected void endHook() { gc.repaint(); } /* Protected method: isStarted() */ /** * Checks to see whether this program has started, usually by checking to see * whether some pane exists. Subclasses can override this method to ensure * that their structures are visible before proceeding. * */ protected boolean isStarted() { if (gc == null || !super.isStarted()) return false; Dimension size = gc.getSize(); return (size != null) && (size.width != 0) && (size.height != 0); } /* Private instance variables */ private GCanvas gc; private GProgramListener eventListener; } /* Package class: GProgramListener */ /** * The GProgramListener class implements the waitForClick * method and the objectdraw-style listener model. */ class GProgramListener implements MouseListener, MouseMotionListener { /* Constructor: GProgramListener() */ /** * Creates the GProgramListener. */ public GProgramListener(GraphicsProgram program) { myProgram = program; try { Class programClass = program.getClass(); Class[] types = { Class.forName("acm.graphics.GPoint") }; try { mousePressedHook = programClass.getMethod("mousePressed", types); } catch (NoSuchMethodException ex) { /* Empty */ } try { mouseReleasedHook = programClass.getMethod("mouseReleased", types); } catch (NoSuchMethodException ex) { /* Empty */ } try { mouseClickedHook = programClass.getMethod("mouseClicked", types); } catch (NoSuchMethodException ex) { /* Empty */ } try { mouseMovedHook = programClass.getMethod("mouseMoved", types); } catch (NoSuchMethodException ex) { /* Empty */ } try { mouseDraggedHook = programClass.getMethod("mouseDragged", types); } catch (NoSuchMethodException ex) { /* Empty */ } } catch (Exception ex) { throw new ErrorException(ex); } } /* Method: needsMouseMotionListeners() */ /** * Returns true if this listener has to respond to mouse motion events as well. */ public boolean needsMouseMotionListeners() { return mouseMovedHook != null || mouseDraggedHook != null; } /* Method: mouseClicked() */ /** * Called by the event-handling system when the mouse is clicked in the canvas. */ public void mouseClicked(MouseEvent e) { if (mouseClickedHook != null) { Object[] args = { new GPoint(e.getX(), e.getY()) }; try { mouseClickedHook.invoke(myProgram, args); } catch (Exception ex) { throw new ErrorException(ex); } } signalClickOccurred(); } /* Method: mousePressed() */ /** * Called by the event-handling system when the mouse button is pressed. */ public void mousePressed(MouseEvent e) { if (mousePressedHook != null) { Object[] args = { new GPoint(e.getX(), e.getY()) }; try { mousePressedHook.invoke(myProgram, args); } catch (Exception ex) { throw new ErrorException(ex); } } } /* Method: mouseReleased() */ /** * Called by the event-handling system when the mouse button is released. */ public void mouseReleased(MouseEvent e) { if (mouseReleasedHook != null) { Object[] args = { new GPoint(e.getX(), e.getY()) }; try { mouseReleasedHook.invoke(myProgram, args); } catch (Exception ex) { throw new ErrorException(ex); } } } /* Method: mouseEntered() */ /** * Called by the event-handling system when the mouse enters the component. */ public void mouseEntered(MouseEvent e) { /* Empty */ } /* Method: mouseExited() */ /** * Called by the event-handling system when the mouse leaves the component. */ public void mouseExited(MouseEvent e) { /* Empty */ } /* Method: mouseMoved() */ /** * Called by the event-handling system when the mouse moves. */ public void mouseMoved(MouseEvent e) { if (mouseMovedHook != null) { Object[] args = { new GPoint(e.getX(), e.getY()) }; try { mouseMovedHook.invoke(myProgram, args); } catch (Exception ex) { throw new ErrorException(ex); } } } /* Method: mouseDragged() */ /** * Called by the event-handling system when the mouse is dragged with the button down. */ public void mouseDragged(MouseEvent e) { if (mouseDraggedHook != null) { Object[] args = { new GPoint(e.getX(), e.getY()) }; try { mouseDraggedHook.invoke(myProgram, args); } catch (Exception ex) { throw new ErrorException(ex); } } } /* Method: waitForClick() */ /** * Waits for a mouse click in the window before proceeding. * * Example: waitForClick(); */ public synchronized void waitForClick() { clickFlag = false; while (!clickFlag) { try { wait(); } catch (InterruptedException ex) { /* Empty */ } } } /* Private method: signalClickOccurred() */ /** * Notifies any waiting objects that a click has occurred. */ private synchronized void signalClickOccurred() { clickFlag = true; notifyAll(); } /* Private instance variables */ private GraphicsProgram myProgram; private Method mousePressedHook; private Method mouseReleasedHook; private Method mouseClickedHook; private Method mouseMovedHook; private Method mouseDraggedHook; private boolean clickFlag; } /* Package class: GObjectProgram */ /** * This class is used to launch a program containing a single GObject * instance at its center. */ class GObjectProgram extends GraphicsProgram { /* Hook method: runHook() */ /** * Calls the run method in the graphical object. */ protected void runHook() { GObject gobj = (GObject) getStartupObject(); GDimension size = gobj.getSize(); add(gobj, (getWidth() - size.getWidth()) / 2, (getHeight() - size.getHeight()) / 2); try { Class gobjClass = gobj.getClass(); String className = gobjClass.getName(); className = className.substring(className.lastIndexOf(".") + 1); setTitle(className); Method run = gobjClass.getMethod("run", new Class[0]); if (run == null) throw new ErrorException(className + " has no run method"); run.invoke(gobj, new Object[0]); } catch (Exception ex) { throw new ErrorException(ex); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy