Contents:

SceneEditor.java


import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;

/**
   A program that allows users to edit a scene composed
   of items.
*/
public class SceneEditor extends JApplet
{
    JPanel buttons;
    ScenePanel panel;
    public void make_editor()
    {
	panel = new ScenePanel();
	JButton houseButton = new JButton("House");
	houseButton.addActionListener(new
				      ActionListener()
	{
	    public void actionPerformed(ActionEvent event)
	    {
		panel.add(new HouseShape(20, 20, 50));
	    }
	});

	JButton carButton = new JButton("Car");
	carButton.addActionListener(new
				    ActionListener()
	{
	    public void actionPerformed(ActionEvent event)
	    {
		panel.add(new CarShape(20, 20, 50));
	    }
	});

	JButton removeButton = new JButton("Remove");
	removeButton.addActionListener(new
				       ActionListener()
	{
	    public void actionPerformed(ActionEvent event)
	    {
		panel.removeSelected();
	    }
	});

	buttons = new JPanel();
	buttons.add(houseButton);
	buttons.add(carButton);
	buttons.add(removeButton);
   }
    public void init()
    {
	make_editor();
	Container contentPane = getContentPane();
	contentPane.add(panel, BorderLayout.CENTER);
	contentPane.add(buttons, BorderLayout.NORTH);
    }
   public static void main(String[] args)
   {
      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      Container contentPane = frame.getContentPane();
      SceneEditor scene = new SceneEditor();
      scene.make_editor();

      
      contentPane.add(scene.panel, BorderLayout.CENTER);
      contentPane.add(scene.buttons, BorderLayout.NORTH);

      frame.setSize(300, 300);
      frame.setVisible(true);
   }
}


ScenePanel.java


import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.util.*;

/**
   A panel that shows a scene composed of shapes.
*/
public class ScenePanel extends JPanel
{
   public ScenePanel()
   {
      shapes = new ArrayList<SceneShape>();

      addMouseListener(new
         MouseAdapter()
         {
            public void mousePressed(MouseEvent event)
            {
               mousePoint = event.getPoint();
               for (int i = 0; i < shapes.size(); i++)
               {
                  SceneShape s = (SceneShape) shapes.get(i);
                  if (s.contains(mousePoint))
                     s.setSelected(!s.isSelected());
               }
               repaint();
            }
         });

      addMouseMotionListener(new
         MouseMotionAdapter()
         {
            public void mouseDragged(MouseEvent event)
            {
               Point lastMousePoint = mousePoint;
               mousePoint = event.getPoint();
               for (int i = 0; i < shapes.size(); i++)
               {
                  SceneShape s = (SceneShape) shapes.get(i);
                  if (s.isSelected())
                     s.translate(
                        mousePoint.getX() - lastMousePoint.getX(),
                        mousePoint.getY() - lastMousePoint.getY());
               }
               repaint();
            }
         });
   }

   /**
      Adds a shape to the scene.
      @param s the shape to add
   */
   public void add(SceneShape s)
   {
      shapes.add(s);
      repaint();
   }

   /**
      Removes all selected shapes from the scene.
   */
   public void removeSelected()
   {
      for (int i = shapes.size() - 1; i >= 0; i--)
      {
         SceneShape s = (SceneShape) shapes.get(i);
         if (s.isSelected()) shapes.remove(i);
      }
      repaint();
   }

   public void paintComponent(Graphics g)
   {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      for (int i = 0; i < shapes.size(); i++)
      {
         SceneShape s = (SceneShape) shapes.get(i);
         s.draw(g2);
         if (s.isSelected())
            s.drawSelection(g2);
      }
   }

   private ArrayList<SceneShape> shapes;
   private Point mousePoint;
}                               


SelectableShape.java


import java.awt.*;
import java.awt.geom.*;

/**
   A shape that manages its selection state.
*/
public abstract class SelectableShape implements SceneShape
{
   public void setSelected(boolean b)
   {
      selected = b;
   }

   public boolean isSelected()
   {
      return selected;
   }

   private boolean selected;
}


SceneShape.java


import java.awt.*;
import java.awt.geom.*;

/**
   A shape that is a part of a scene.
*/
public interface SceneShape
{
   /**
      Draws this item.
      @param g2 the graphics context
   */
   void draw(Graphics2D g2);
   /**
      Draws the selection adornment of this item.
      @param g2 the graphics context
   */
   void drawSelection(Graphics2D g2);
   /**
      Sets the selection state of this item.
      @param b true if this item is selected
   */
   void setSelected(boolean b);
   /**
      Gets the selection state of this item.
      @return true if this item is selected
   */
   boolean isSelected();
   /**
      Translates this item by a given amount.
      @param dx the amount to translate in x-direction
      @param dy the amount to translate in y-direction
   */
   void translate(double dx, double dy);
   /**
      Tests whether this item contains a given point.
      @param p a point
      @return true if this item contains p
   */
   boolean contains(Point2D p);
}


HouseShape.java


import java.awt.*;
import java.awt.geom.*;

/**
   A house shape.
*/
public class HouseShape extends SelectableShape
{
   /**
      Constructs a house shape.
      @param x the left of the bounding rectangle
      @param y the top of the bounding rectangle
      @param width the width of the bounding rectangle
   */
   public HouseShape(int x, int y, int width)
   {
      this.x = x;
      this.y = y;
      this.width = width;
   }

   public void draw(Graphics2D g2)
   {
      Rectangle2D.Double base 
         = new Rectangle2D.Double(x, y + width, width, width);

      // the left bottom of the roof
      Point2D.Double r1
         = new Point2D.Double(x, y + width);
      // the top of the roof
      Point2D.Double r2
         = new Point2D.Double(x + width / 2, y);
      // the right bottom of the roof
      Point2D.Double r3
         = new Point2D.Double(x + width, y + width);

      Line2D.Double roofLeft
         = new Line2D.Double(r1, r2);
      Line2D.Double roofRight
         = new Line2D.Double(r2, r3);

      g2.draw(base);
      g2.draw(roofLeft);
      g2.draw(roofRight);
   }
   
   public void drawSelection(Graphics2D g2)
   {
      Rectangle2D.Double base 
         = new Rectangle2D.Double(x, y + width, width, width);
      g2.fill(base);
   }

   public boolean contains(Point2D p)
   {
      return x <= p.getX() && p.getX() <= x + width 
         && y <= p.getY() && p.getY() <= y + 2 * width;
   }

   public void translate(double dx, double dy)
   {
      x += dx;
      y += dy;
   }

   private int x;
   private int y;
   private int width;
}


CarShape.java


import java.awt.*;
import java.awt.geom.*;

/**
   A car shape.
*/
public class CarShape extends SelectableShape
{
   /**
      Constructs a car shape.
      @param x the left of the bounding rectangle
      @param y the top of the bounding rectangle
      @param width the width of the bounding rectangle
   */
   public CarShape(int x, int y, int width)
   {
      this.x = x;
      this.y = y;
      this.width = width;
   }

   public void draw(Graphics2D g2)
   {
      Rectangle2D.Double body
         = new Rectangle2D.Double(x, y + width / 6, 
            width - 1, width / 6);
      Ellipse2D.Double frontTire
         = new Ellipse2D.Double(x + width / 6, y + width / 3, 
            width / 6, width / 6);
      Ellipse2D.Double rearTire
         = new Ellipse2D.Double(x + width * 2 / 3, 
            y + width / 3,
            width / 6, width / 6);

      // the bottom of the front windshield
      Point2D.Double r1
         = new Point2D.Double(x + width / 6, y + width / 6);
      // the front of the roof
      Point2D.Double r2
         = new Point2D.Double(x + width / 3, y);
      // the rear of the roof
      Point2D.Double r3
         = new Point2D.Double(x + width * 2 / 3, y);
      // the bottom of the rear windshield
      Point2D.Double r4
         = new Point2D.Double(x + width * 5 / 6, y + width / 6);
      Line2D.Double frontWindshield
         = new Line2D.Double(r1, r2);
      Line2D.Double roofTop
         = new Line2D.Double(r2, r3);
      Line2D.Double rearWindshield
         = new Line2D.Double(r3, r4);

      g2.draw(body);
      g2.draw(frontTire);
      g2.draw(rearTire);
      g2.draw(frontWindshield);
      g2.draw(roofTop);
      g2.draw(rearWindshield);
   }
   
   public void drawSelection(Graphics2D g2)
   {
      Rectangle2D.Double body
         = new Rectangle2D.Double(x, y + width / 6, 
            width - 1, width / 6);
      g2.fill(body);
   }

   public boolean contains(Point2D p)
   {
      return x <= p.getX() && p.getX() <= x + width 
         && y <= p.getY() && p.getY() <= y + width / 2;
   }

   public void translate(double dx, double dy)
   {
      x += dx;
      y += dy;
   }

   private int x;
   private int y;
   private int width;
}


Maintained by John Loomis, updated Mon Feb 26 09:09:46 2007