001: import java.awt.*;
002: import java.awt.geom.*;
003: import java.io.*;
004: 
005: /**
006:    A serializable car shape.
007: */
008: public class Car implements Serializable
009: {
010:    /**
011:       Constructs a car.
012:       @param x the left of the bounding rectangle
013:       @param y the top of the bounding rectangle
014:       @param width the width of the bounding rectangle
015:    */
016:    public Car(int x, int y, int width)
017:    {
018:       body = new Rectangle(x, y + width / 6,
019:          width - 1, width / 6);
020:       roof = new Rectangle(x + width / 3, y,
021:          width / 3, width / 6);
022:       frontTire = new Ellipse2D.Double(x + width / 6, y + width / 3,
023:          width / 6, width / 6);
024:       rearTire = new Ellipse2D.Double(x + width * 2 / 3, y + width / 3,
025:          width / 6, width / 6);
026:    }
027: 
028:    private void writeObject(ObjectOutputStream out)
029:       throws IOException
030:    {
031:       out.defaultWriteObject();
032:       writeRectangularShape(out, frontTire);
033:       writeRectangularShape(out, rearTire);
034:    }
035: 
036:    /**
037:       A helper method to write a rectangular shape.
038:       @param out the stream onto which to write the shape
039:       @param s the shape to write
040:    */
041:    private static void writeRectangularShape(ObjectOutputStream out,
042:       RectangularShape s)
043:       throws IOException
044:    {
045:       out.writeDouble(s.getX());
046:       out.writeDouble(s.getY());
047:       out.writeDouble(s.getWidth());
048:       out.writeDouble(s.getHeight());
049:    }
050: 
051:    private void readObject(ObjectInputStream in)
052:       throws IOException, ClassNotFoundException
053:    {
054:       in.defaultReadObject();
055:       frontTire = new Ellipse2D.Double();
056:       readRectangularShape(in, frontTire);
057:       rearTire = new Ellipse2D.Double();
058:       readRectangularShape(in, rearTire);
059:    }
060: 
061:    /**
062:       A helper method to read a rectangular shape.
063:       @param in the stream from which to read the shape
064:       @param s the shape to read. The method sets the frame
065:       of this rectangular shape.
066:    */
067:    private static void readRectangularShape(ObjectInputStream in,
068:       RectangularShape s)
069:       throws IOException
070:    {
071:       double x = in.readDouble();
072:       double y = in.readDouble();
073:       double width = in.readDouble();
074:       double height = in.readDouble();
075:       s.setFrame(x, y, width, height);
076:    }
077: 
078:    /**
079:       Draws the car.
080:       @param g2 the graphics context
081:    */
082:    public void draw(Graphics2D g2)
083:    {
084:       g2.draw(body);
085:       g2.draw(roof);
086:       g2.draw(frontTire);
087:       g2.draw(rearTire);
088:    }
089: 
090:    public String toString()
091:    {
092:       return getClass().getName()
093:          + "[body=" + body
094:          + ",roof=" + roof
095:          + ",frontTire=" + formatRectangularShape(frontTire)
096:          + ",rearTire=" + formatRectangularShape(rearTire)
097:          + "]";
098:    }
099: 
100:    /**
101:       A helper method to format a rectangular shape.
102:       @param s the shape to format
103:       @return a formatted representation of the given shape
104:    */
105:    private static String formatRectangularShape(RectangularShape s)
106:    {
107:       return RectangularShape.class.getName()
108:          + "[x=" + s.getX()
109:          + ",y=" + s.getY()
110:          + ",width=" + s.getWidth()
111:          + ",height=" + s.getHeight()
112:          + "]";
113:    }
114: 
115: 
116:    private Rectangle body;
117:    private Rectangle roof;
118:    private transient Ellipse2D.Double frontTire;
119:    private transient Ellipse2D.Double rearTire;
120: }
121: 
122: