// AnimationObject.java // This file provides some of the supporting classes for the applet // whose main class, Animate, is given in the file Animate.java. // S. Tanimoto, 10 April 1999. // The top-level class in this file is AnimationObject, which represents // a drawing that can be animated by the Animate class. The AnimationObject // class provides not only for the storage of the dots of the drawing, // the painting of them, but also provides a button for selecting the // object show that it can be given a trajectory by drawing in the // AnimationCanvas which is back in the Animate.java file. // AnimationObject includes the following inner classes: // 1. DrawPanel, a panel that holds the select button and the DrawCanvas; // 2. DrawCanvas, a canvas where the user can paint the drawing of this // animation object. // There are also inner classes that define mouse and button handlers. import java.applet.*; import java.util.*; import java.awt.*; import java.awt.event.*; public class AnimationObject { public DrawPanel dp; // Used for laying out the object. public Vector trajectory; // Path this object follows during animation. Color trajectoryColor; // Color for trajectory during animation setup. public Point currentLocation; // Updated during animation. boolean animating = false; // True during animation repainting only. // Minimum mouse movement to register a new dot while user is drawing: private static final int SMIDGEON = 5; // The radius of the paintbrush, in pixels: private static final int BRUSH_RADIUS = 5; public static AnimationObject currentAO; // ref. to selected instance. static DrawPanel selectedDrawPanel; // ref. to panel of sel. inst. public static DrawPanel getSelectedDrawPanel() { // accessor method. return selectedDrawPanel; } public AnimationObject() { // Constructor. dp = new DrawPanel(this); // Make a panel. dp.init(); // Initialize it. trajectory = new Vector(); // Create an empty trajectory. } public void setTrajectoryColor(Color c) { trajectoryColor = c; } public Color getTrajectoryColor() { return trajectoryColor; } // The following is called by class AnimationCanvas's paint method, // which is given in the file Animate.java. public void paintOnAnimationCanvas(Graphics animationGraphics) { animating = true; dp.theDrawCanvas.paint(animationGraphics); // Use local paint method to paint this object's dots on // the animation canvas's Graphics animationGraphics. animating = false; } class DrawPanel extends Panel { DrawCanvas theDrawCanvas; Button selectMeButton; AnimationObject myAO; // Ref back to the anim. obj. that contains this. DrawPanel(AnimationObject ao) { // Constructor myAO = ao; // records ref. to anim. obj. theDrawCanvas = new DrawCanvas(this); // Create canvas. selectMeButton = new Button("Select me!"); // Make its button. } void init() { // Lay out the DrawPanel instance. setLayout(new BorderLayout()); theDrawCanvas.init(); add(theDrawCanvas); add(selectMeButton, BorderLayout.NORTH); selectMeButton.addActionListener(new SelectMeActionListener()); } } class DrawCanvas extends Canvas { Vector inkTrail; // Holds the dots of the drawing. int lastX, lastY; // Used while user is drawing. boolean initialized = false; DrawPanel myDP; // Ref. back to DrawPanel that contains this. DrawCanvas(DrawPanel myDP) { // Constructor this.myDP = myDP; // records ref. to DrawPanel. } void init() { if (initialized) return; // Avoid reinitialization initialized = true; inkTrail = new Vector(); // Stores the brush positions. lastX = -1000; // some value out of range of the panel. lastY = -1000; DrawCanvasMouseHandler mmh = new DrawCanvasMouseHandler(); addMouseListener(mmh); addMouseMotionListener(mmh); setSize(100, 100); // Canvas needs to share space with others. // BTW, you can actually draw outside this provided dragging // begins within the canvas. The external dots can be seen // during animation. }; public void paint(Graphics g) { // Note we might be painting on the DrawCanvas or on the AnimationCanvas, // depending upon where this is called from. int locX = 0, locY = 0; // Use these whether or not we are animating. if (myDP.myAO.animating && (! (currentLocation == null))) { // The values of locX and locY become significant during animation: locX = myDP.myAO.currentLocation.x; locY = myDP.myAO.currentLocation.y; } else { // If we're not animating, then we're showing the drawing on // the DrawCanvas, and the background needs to be set to // show whether this animation object is selected or not. if (dp == selectedDrawPanel) setBackground(Color.yellow); else setBackground(Color.blue); } g.setColor(Color.black); // Ink will be black. // OK, now let's paint all the dots. // Which canvas they end up on depends on what graphics // object g was passed in with the call to this method. for (Enumeration dots = inkTrail.elements(); dots.hasMoreElements(); ) { Point dot = (Point) dots.nextElement(); int x = dot.x + locX; int y = dot.y + locY; g.fillOval(x - BRUSH_RADIUS, y - BRUSH_RADIUS, 2 * BRUSH_RADIUS, 2 * BRUSH_RADIUS); } } public class DrawCanvasMouseHandler extends MouseAdapter implements MouseMotionListener { public void mousePressed(MouseEvent e) { // Always draw something when mouse is first pressed. // Force this by setting lastX and lastY to values way // out of the canvas and then calling mouseDragged. lastX = -1000; lastY = -1000; mouseDragged(e); } public void mouseReleased(MouseEvent e) { } public void mouseMoved(MouseEvent e) { } public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); // If mouse has moved enough, then add a new point: if ( Math.abs(x - lastX) > SMIDGEON || Math.abs(y - lastY) > SMIDGEON) { inkTrail.addElement(new Point(e.getX(), e.getY())); lastX = x; lastY = y; // Remember this for next time. repaint(); } } } } class SelectMeActionListener implements ActionListener { // Handles the "Select me!" button. public void actionPerformed(ActionEvent e) { currentAO = dp.myAO; // Register the selected anim. obj. DrawPanel lastSelectedDrawPanel = selectedDrawPanel; selectedDrawPanel = dp; // Register the dp of the new selection. // Rerender as unselected the previously selected DrawPanel, if any: if (! (lastSelectedDrawPanel == null)) lastSelectedDrawPanel.theDrawCanvas.repaint(); dp.theDrawCanvas.repaint(); // Rerender the newly selected DrawPanel. } } }