Computer Science 252
Problem Solving with Java
Spring 2014, The College of Saint Rose
SimpleRecScribbler Demo
A working demo of SimpleRecScribbler will appear below. Click inside the applet to interact with it.
SimpleRecScribbler BlueJ Project
Click here to download a BlueJ project for SimpleRecScribbler.
SimpleRecScribbler Source Code
The Java source code for SimpleRecScribbler is below. Click on a file name to download it.
import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JPanel; import objectdraw.*; /* * This program is another step toward a drawing program that will * be much more functional than our simple Scribble example. * Here, we construct a recursive data structure to represent * a Scribble, and can move and change the color of the * Scribbles. * * Jim Teresco, CSC 252, The College of Saint Rose, Fall 2013 * Based on similar example from Williams College CS 134. * * $Id: SimpleRecScribbler.java 2230 2013-10-27 02:26:10Z terescoj $ */ // A very simple drawing program. public class SimpleRecScribbler extends WindowController implements ActionListener { // user modes // using ints rather than boolean to allow for extension to // other modes private static final int DRAWING = 1; private static final int MOVING = 2; // the current scribble private Scribble currentScribble; // stores last point for drawing or dragging private Location lastPoint; // whether the most recent scribble has been selected for moving private boolean draggingScribble; // buttons that allow user to select modes private JButton setDraw, setMove; // the current mode -- drawing by default private int chosenAction = DRAWING; public void begin() { // create the user interface components Container contentPane = getContentPane(); setDraw = new JButton("Draw"); setMove = new JButton("Move"); JPanel buttonPanel = new JPanel(); buttonPanel.add(setDraw); buttonPanel.add(setMove); contentPane.add(buttonPanel, BorderLayout.SOUTH); // add listeners setDraw.addActionListener(this); setMove.addActionListener(this); contentPane.validate(); // make the current scribble empty currentScribble = new Scribble(null, null); } public void onMousePress(Location point) { if (chosenAction == DRAWING) { // start a new (empty) scribble for drawing currentScribble = new Scribble(null, null); } else if (chosenAction == MOVING) { // check if user clicked on current scribble draggingScribble = currentScribble.contains(point); } // remember point of press for drawing or moving lastPoint = point; } public void onMouseDrag(Location point) { if (chosenAction == DRAWING) { // add line segment to current scribble currentScribble = new Scribble(new Line(lastPoint, point, canvas), currentScribble); } else if (chosenAction == MOVING) { // move current scribble if dragging it if (draggingScribble) { currentScribble.move(point.getX() - lastPoint.getX(), point.getY() - lastPoint.getY()); } } // update for next move or draw lastPoint = point; } public void actionPerformed(ActionEvent e) { if (e.getSource() == setDraw) { chosenAction = DRAWING; } else if (e.getSource() == setMove) { chosenAction = MOVING; } } }
import java.awt.*; import objectdraw.*; /* * A very basic recursive data structure to represent * a Scribble, augmented with contains, move, and isEmpty * methods. * * Jim Teresco, CSC 252, The College of Saint Rose, Fall 2013 * Based on similar example from Williams College CS 134. * * $Id: Scribble.java 2230 2013-10-27 02:26:10Z terescoj $ */ // A class to represent a scribble public class Scribble { private Line first; // an edge line of the scribble private Scribble rest; // the rest of the scribble // Our constructor here doesn't actually do any of the // drawing - it takes a line that someone else created and // which is supposed to be part of the Scribble, and // a reference to another Scribble which represents // any previous Scribble. public Scribble(Line segment, Scribble theRest) { first = segment; rest = theRest; } // returns true iff the scribble contains the point // Note that things are slightly more complex than some // of our other recursive accessors as there are three // possibilities: 1) this Scribble is empty, in which // case it cannot contain the point, 2) first contains // the point, in which case the whole Scribble contains // the point, or 3) the answer depends on whether rest // (itself a Scribble, hence the recursive call) contains // the point public boolean contains(Location point) { if (isEmpty()) { return false; } else if (first.contains(point)) { return true; } else { return rest.contains(point); } } // the scribble is moved xOffset in the x direction // and yOffset in the y direction public void move(double xOffset, double yOffset) { if (!isEmpty()) { first.move(xOffset, yOffset); rest.move(xOffset, yOffset); } } // returns true iff the list is empty public boolean isEmpty() { return (first == null); } }