CS251 Lab2

Implementing Undo/Redo in a Graphical Editor

Goal

You will use double linked lists to implement Undo/Redo in a graphical program.

Step 1. Downloading Initial Files

Download the file lab2-src.tar.Z Then uncompress it and untar it.
uncompress lab2-src.tar.Z
tar -xvf lab2-src.tar
The directory lab2-src that is created contains the test files and the classes you will use for this project.

Compile and run BoilerDraw:

cd lab2-src
javac BoilerDrawMain.java
java BoilerDrawMain

Step 2. Understanding Boiler Draw

The sources provided are from BoilerDraw, a graphical editor. Run the program and play wit it to be familiar with the different options. You don't need to understand the internals of this program to do this project.

The BoilerDraw class is the core of the graphical editor. The input (mouse and keyboard)  that BoilerDraw receives come from BoilerMain. For this project the input is being filtered by a class BoilerDrawUndoListener. This is the class that you will modify to implement undo/redo.

(Mouse/Keyboard) --> BoilerDrawMain ---> BoilerDrawUndoListener ---> BoilerDraw --> Display

When the mouse is pressed or when the pulldown menu options are selected, BoilerDrawMain calls the following methods in BoilerDrawUndoListener.

interface BoilerDrawListener{
public void mouseDragged( int x, int y );   // Mouse is been dragged
public void mousePressed( int x, int y );    // Mouse is being pressed
public void mouseReleased( int x, int y );  // Mouse was Released
public void menuOption( String option );  // A pull down menu option has been selected
public void openFile( String fileName );    // A file "fileName" is being opened
public void saveFile( String fileName );     // The current figure is being stored as fileName
public void addText( String text );             // The string in "text" has been typed

};

Currently, BoilerDrawUndoListener prints a message in each of this methods and then calls the same method on BoilerDraw. See how BoilerDrawUndoListener.java is currently implemented.

You will modify the BoilerDrawUndoListener class to log these methods in a double linked list and then replay them when undo/redo is executed. By passing a menuOption("New") to the BoilerDraw object you can clear the current figure that is being displayed.

Step 3. Implementing Undo/Redo

There is already a class List in the lab2-src directory that you may use to implement the double linked list to log the input. You may modify it if necessary. Add the double linked list as a member variable to BoilerDrawUndoListener. You may subclass the ListNode class to represent the events that need to be logged. Each node in the list may store mouse coordinates, if the mouse was dragged/pressed/released, if a pull-down menu option was selected, text was added, or a file was opened.

Every time the methods described above are called in BoilerDrawUndoListener, you will log the method in the double linked list and call the corresponding method to BoilerDraw. Also, you will add a "current" index that will point to the last event logged in the list.

When the menuOption method is called with option="Undo", it will clear the screen by calling the method menuOption("New") in BoilerDraw and then it will decrement current, and replay all the methods logged up to current.

If menuOption method is called with option="Redo", it will clear the screen, increment current, and then it will replay the methods up to the current one. If Undo/Redo cannot be executed any more because the end or the beginning of the list have been reached, the Undo/Redo operation will be silently ignored.

Important: When the mouse is pressed and released you will see that mousePressed() is called once, mouseDragged() is called  lots of times and then mouseReleased() is called once. You should log the entire mousePressed/mouseDragged()/mouseReleased() cycle as a single event in the log. You will need to store: x0,y0 of the point where mousePressed was called; x1, y1 of the point where mouseDragged was first called; x2, y2 of the point where mouseDragged was last called, and x3, y3 of the point where mouseReleased() was called. You don't need to store the intermediate points where mouseDragged was called. To replay the mouse event, BoilerDrawUndoListener will execute:

_bDraw.mousePressed(x0,y0);
_bDraw.mouseDragged(x1,y1);
_bDraw.mouseDragged(x2,y2);
_bDraw.mouseReleased(x3,y3);
Make sure that the Undo/Redo operations work correctly.

You don't need to log the saveFileOperation.

Testing your project

We have provided a set of tests in the distributed files so you can test your implementation. Make sure that your implementation passes these tests before you turn in your project.

Before you start running the tests you have to implement in your BoilerDrawUndoListener a new pull-down menu option, besides Redo and Undo, that is called "Reset Undo". When "Reset Undo" is selected, your BoilerDrawUndoListener will clean the screen by passing "New" to BoilerDraw and also it is going to clear your undo list and current pointer. This new option is important since it will run before every test starts to reset the state of your BoilerDrawUndoListener and BoilerDraw.

Now to run the tests select the pull-down menu "Test" and select "Run one". You may run tests undo-1.tst to undo1-0.tst or redo-1.tst to redo-10.tst .The output of the tests is printed to the console where BoilerDrawMain was started.

To run all the tests at once select "Run set" and select "test-undo-all.tsts".

Additionally, make sure that if mouseDragged is called only once or none at all during a mouse movement cycle, then make sure that during replay in undo/redo only call that number of time mouseDragged was called. That may make a difference in the test output.

Turning in project

Follow these instructions to turnin lab2:
  1. Login to lore.cs.purdue.edu
  2. Remove the .class files
  3. Change above the directory to lab2-src.
  4. Type "turnin -c cs251 -p lab2 lab2-src" (Example: "turnin -c cs251 -p lab2 lab2-src")
  5. Type  "turnin -c cs251 -p lab2 -v" to make sure you have submitted the right files (Example: "turnin -c cs251 -p lab2 -v")
The deadline for this lab is Thursday September 17th, 11:59pm.