Computer Science 252
Problem Solving with Java
Spring 2014, The College of Saint Rose
RecScribbler Demo
A working demo of RecScribbler will appear below. Click inside the applet to interact with it.
RecScribbler BlueJ Project
Click here to download a BlueJ project for RecScribbler.
RecScribbler Source Code
The Java source code for RecScribbler is below. Click on a file name to download it.
import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; 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 all of the Scribbles which are * stored in another recursive structure. We also added * setColor and clear capabilities. * * Jim Teresco, CSC 252, The College of Saint Rose, Fall 2013 * Based on similar example from Williams College CS 134. * * $Id: RecScribbler.java 2249 2013-11-07 16:20:52Z terescoj $ */ public class RecScribbler 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; private static final int COLORING = 3; // the current scribble private Scribble currentScribble; // the list of all Scribble objects private ScribbleList allScribbles; // stores last point for drawing or dragging private Location lastPoint; // the scribble that has been selected for moving, if any // is null if not private Scribble draggingScribble; // the scribble we selected for other actions (coloring) private Scribble selectedScribble; // buttons that allow user to select modes private JButton setDraw, setMove, setColor, clearButton; // the current mode -- drawing by default private int chosenAction = DRAWING; // our Random private Random r; public void begin() { // create the user interface components Container contentPane = getContentPane(); setDraw = new JButton("Draw"); setMove = new JButton("Move"); setColor = new JButton("Set Color"); clearButton = new JButton("Clear"); JPanel buttonPanel = new JPanel(); buttonPanel.add(setDraw); buttonPanel.add(setMove); buttonPanel.add(setColor); buttonPanel.add(clearButton); contentPane.add(buttonPanel, BorderLayout.SOUTH); // add listeners setDraw.addActionListener(this); setMove.addActionListener(this); setColor.addActionListener(this); clearButton.addActionListener(this); contentPane.validate(); // make the current scribble empty currentScribble = new Scribble(null, null); // create our empty list allScribbles = new ScribbleList(null, null); // not dragging to start draggingScribble = null; // set up random r = new Random(); } 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 = allScribbles.whichContains(point); } else if (chosenAction == COLORING) { // find which one contains the point, if any selectedScribble = allScribbles.whichContains(point); if (selectedScribble != null) { Color c = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256)); selectedScribble.setColor(c); } } // 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 != null) { draggingScribble.move(point.getX() - lastPoint.getX(), point.getY() - lastPoint.getY()); } } // update for next move or draw lastPoint = point; } public void onMouseRelease(Location point) { if (chosenAction == DRAWING) { allScribbles = new ScribbleList(currentScribble, allScribbles); } draggingScribble = null; } public void actionPerformed(ActionEvent e) { if (e.getSource() == setDraw) { chosenAction = DRAWING; } else if (e.getSource() == setMove) { chosenAction = MOVING; } else if (e.getSource() == setColor) { chosenAction = COLORING; } else if (e.getSource() == clearButton) { // clear the canvas canvas.clear(); // replace our ScribbleList with an empty one allScribbles = new ScribbleList(null, null); } } }
import java.awt.*; import objectdraw.*; /* * A very basic recursive data structure to represent * a Scribble, augmented with contains, move, and isEmpty * methods. Now with setColor! * * Jim Teresco, CSC 252, The College of Saint Rose, Fall 2013 * Based on similar example from Williams College CS 134. * * $Id: Scribble.java 2249 2013-11-07 16:20:52Z 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); } // set the color of this Scribble public void setColor(Color c) { if (!isEmpty()) { first.setColor(c); rest.setColor(c); } } }
/** * A list of Scribbles! * * @author Jim Teresco and CSC 252 class, Fall 2013 */ import objectdraw.*; import java.awt.*; public class ScribbleList { private Scribble first; private ScribbleList rest; public ScribbleList(Scribble first, ScribbleList rest){ this.first = first; this.rest = rest; } // return the Scribble in the list that contains the given point // and null if no Scribble contains the point public Scribble whichContains(Location point) { // an empty ScribbleList can't have a Scribble // that contains the point if (first == null) return null; // does the first Scribble contain the point? if (first.contains(point)) return first; return rest.whichContains(point); } }