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; +}