diff --git a/.gitignore b/.gitignore
index 0f182a0..d6ae612 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,36 @@
*.jar
*.war
*.ear
+# ===== Start Global/Eclipse.gitignore =====
+*.pydevproject
+.metadata
+.gradle
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# TeXlipse plugin
+.texlipse
+# ===== End Global/Eclipse.gitignore =====
+
diff --git a/Lab5/.classpath b/Lab5/.classpath
new file mode 100644
index 0000000..18d70f0
--- /dev/null
+++ b/Lab5/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Lab5/.project b/Lab5/.project
new file mode 100644
index 0000000..5b0ca70
--- /dev/null
+++ b/Lab5/.project
@@ -0,0 +1,17 @@
+
+
+ Lab5
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/Lab5/src/CarShape.java b/Lab5/src/CarShape.java
new file mode 100644
index 0000000..c40d0a0
--- /dev/null
+++ b/Lab5/src/CarShape.java
@@ -0,0 +1,54 @@
+import java.awt.*;
+import java.awt.geom.*;
+
+/**
+ A car shape.
+*/
+public class CarShape extends CompoundShape
+{
+ /**
+ 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)
+ {
+ 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);
+
+ add(body);
+ add(frontTire);
+ add(rearTire);
+ add(frontWindshield);
+ add(roofTop);
+ add(rearWindshield);
+ }
+}
diff --git a/Lab5/src/CompoundShape.java b/Lab5/src/CompoundShape.java
new file mode 100644
index 0000000..2e7d07d
--- /dev/null
+++ b/Lab5/src/CompoundShape.java
@@ -0,0 +1,43 @@
+import java.awt.*;
+import java.awt.geom.*;
+
+/**
+ A scene shape that is composed of multiple geometric shapes.
+*/
+public abstract class CompoundShape extends SelectableShape
+{
+ public CompoundShape()
+ {
+ path = new GeneralPath();
+ }
+
+ protected void add(Shape s)
+ {
+ path.append(s, false);
+ }
+
+ public boolean contains(Point2D aPoint)
+ {
+ return path.contains(aPoint);
+ }
+
+ public void translate(int dx, int dy)
+ {
+ path.transform(
+ AffineTransform.getTranslateInstance(dx, dy));
+ }
+
+ public void draw(Graphics2D g2)
+ {
+ g2.draw(path);
+ }
+
+ private GeneralPath path;
+}
+
+
+
+
+
+
+
diff --git a/Lab5/src/HouseShape.java b/Lab5/src/HouseShape.java
new file mode 100644
index 0000000..3a16bfd
--- /dev/null
+++ b/Lab5/src/HouseShape.java
@@ -0,0 +1,39 @@
+import java.awt.*;
+import java.awt.geom.*;
+
+/**
+ A house shape.
+*/
+public class HouseShape extends CompoundShape
+{
+ /**
+ 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)
+ {
+ 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);
+
+ add(base);
+ add(roofLeft);
+ add(roofRight);
+ }
+}
diff --git a/Lab5/src/SceneComponent.java b/Lab5/src/SceneComponent.java
new file mode 100644
index 0000000..4d7d796
--- /dev/null
+++ b/Lab5/src/SceneComponent.java
@@ -0,0 +1,89 @@
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.*;
+import javax.swing.*;
+import java.util.*;
+
+/**
+ A component that shows a scene composed of shapes.
+*/
+public class SceneComponent extends JComponent
+{
+ public SceneComponent()
+ {
+ shapes = new ArrayList();
+
+ addMouseListener(new
+ MouseAdapter()
+ {
+ public void mousePressed(MouseEvent event)
+ {
+ mousePoint = event.getPoint();
+ for (SceneShape s: shapes)
+ {
+ if (s.contains(mousePoint))
+ s.setSelected(!s.isSelected());
+ }
+ repaint();
+ }
+ });
+
+ addMouseMotionListener(new
+ MouseMotionAdapter()
+ {
+ public void mouseDragged(MouseEvent event)
+ {
+ Point lastMousePoint = mousePoint;
+ mousePoint = event.getPoint();
+ for (SceneShape s : shapes)
+ {
+ if (s.isSelected())
+ {
+ double dx = mousePoint.getX() - lastMousePoint.getX();
+ double dy = mousePoint.getY() - lastMousePoint.getY();
+ s.translate((int) dx, (int) dy);
+ }
+ }
+ repaint();
+ }
+ });
+ }
+
+ /**
+ Adds an 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 = shapes.get(i);
+ if (s.isSelected()) shapes.remove(i);
+ }
+ repaint();
+ }
+
+ public void paintComponent(Graphics g)
+ {
+ super.paintComponent(g);
+ Graphics2D g2 = (Graphics2D) g;
+ for (SceneShape s : shapes)
+ {
+ s.draw(g2);
+ if (s.isSelected())
+ s.drawSelection(g2);
+ }
+ }
+
+ private ArrayList shapes;
+ private Point mousePoint;
+}
diff --git a/Lab5/src/SceneEditor.java b/Lab5/src/SceneEditor.java
new file mode 100644
index 0000000..76cab27
--- /dev/null
+++ b/Lab5/src/SceneEditor.java
@@ -0,0 +1,62 @@
+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
+{
+ public static void main(String[] args)
+ {
+ JFrame frame = new JFrame();
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ final SceneComponent scene = new SceneComponent();
+
+ JButton houseButton = new JButton("House");
+ houseButton.addActionListener(new
+ ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ scene.add(new HouseShape(20, 20, 50));
+ }
+ });
+
+ JButton carButton = new JButton("Car");
+ carButton.addActionListener(new
+ ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ scene.add(new CarShape(20, 20, 50));
+ }
+ });
+
+ JButton removeButton = new JButton("Remove");
+ removeButton.addActionListener(new
+ ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ scene.removeSelected();
+ }
+ });
+
+ JPanel buttons = new JPanel();
+ buttons.add(houseButton);
+ buttons.add(carButton);
+ buttons.add(removeButton);
+
+ frame.add(scene, BorderLayout.CENTER);
+ frame.add(buttons, BorderLayout.NORTH);
+
+ frame.setSize(300, 300);
+ frame.setVisible(true);
+ }
+}
+
+
diff --git a/Lab5/src/SceneShape.java b/Lab5/src/SceneShape.java
new file mode 100644
index 0000000..d8db55e
--- /dev/null
+++ b/Lab5/src/SceneShape.java
@@ -0,0 +1,42 @@
+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(int dx, int dy);
+ /**
+ Tests whether this item contains a given point.
+ @param p a point
+ @return true if this item contains p
+ */
+ boolean contains(Point2D p);
+}
+
diff --git a/Lab5/src/SelectableShape.java b/Lab5/src/SelectableShape.java
new file mode 100644
index 0000000..ebea3d0
--- /dev/null
+++ b/Lab5/src/SelectableShape.java
@@ -0,0 +1,29 @@
+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;
+ }
+
+ public void drawSelection(Graphics2D g2)
+ {
+ translate(1, 1);
+ draw(g2);
+ translate(1, 1);
+ draw(g2);
+ translate(-2, -2);
+ }
+
+ private boolean selected;
+}