The goal of this lab is to practice object-oriented design on a problem that will help you review the object-oriented features of Java and prepare for an exploration of object-oriented design techniques. A second purpose of this lab is to practice using subversion.
Object-oriented design is concerned with the relationship among classes and other types--- which classes implement which interfaces, which classes serve as components to other classes (by means of instance variables), and (as we will learn about soon) which classes share code by inheritance or composition.
You will practice doing object-oriented design (and think about how revision control works) by designing your own simple revision control system. You will write a program that presents the user with a simple text area to edit. The user can "commit" changes made to the text area; these changes are saved in memory and assigned a version number; and the user can then go back to them later.
The user interface is a window that looks like this:
The "current" and "max" indicator at the top should display the version number of the currently displayed version (besides any changes that have been made since the last commit or recall) and the highest version number that has been assigned, respectively. When the program starts up, these should read "Current: 0" and "Max: 0", not "Current" and "Max" as the image shows.
When the user enters some text and then presses the "commit" button, the current and max counters should increment. Suppose the user then enters more text and presses "commit" again. If the user then presses the "<" button, the text should then revert to its state when the "commit" button was pressed the first time. Pressing the ">" button will change the text to what it was when "commit" was pressed the second time. In this way the user can shuffle though versions. Pressing "<" when the current indicator is 0 does nothing, and pressing ">" when the current indicator is equal to the max does nothing.
That specification would be adequate (and the problem very easy) if all the revisions were made in a linear fashion, and the user commited changes made only on the latest version-- in which case we would have an organization like
But what should happen if the user flips back to an earlier version, makes changes, and commits? Should the new version simply be put at the end of the chain, even though it does not descend from the latest version? Should the new version replace the version that used to come after the version that was edited, and the rest of the chain be lost?
Instead of the two options mentioned, your program should consider the series of versions to branch at this point. The new version will receive the next verions number (ie, the max version plus one), but instead of conceptually coming after the most recent version, it will be considered to branch off from the version it was derived from.
Suppose the user takes the collection of versions illustrated above, and then navigates back to version 3, makes a change, and commits (creating version 6). Then he or she makes another change (to the new version 6) and commits it as version 7. Then he or she navigates to 4, changes and commits, navigates back to 6 and makes to changes in a row, and navigates to version 5 to make and commit a final change. That would result in the following tree of versions.
At this point, your version navigation feature should work as follows: When at version 6, pressing the "<" button will bring up version 3, the parent. Pressing ">" (at version 6) would bring up verion 9, the most recent decendant. To move among "sibling" versions, the user would use the "-" button; so, pressing the "-" button at version 6 would bring up version 4, and pressing "-" again would bring back version 6. If there are more than two siblings, the "-" should move from the most recent to the oldest, in a circular manner.
After making a new directory for this lab, use subversion to checkout code for this project.
cp -r ~tvandrun/Public/cs245/lab4/* .
Then open Eclipse and make a new workspace and project for this. I will walk you through this on the big screen.
You will find four sets of classes:
Look at the file
interface describes how to
interact with the window that the user sees.
ConcreteVCWindow is a class that implements this
interface, and it has a no-parameter constructor.
ConcreteVCWindow$SuperButton is a helper class.
I have not given you the source code for these, because you won't need them.
Look at the file
You'll see it has a main method which makes a new window
and a new controller.
It also creates action listeners for the buttons.
Look at one of the action listener classes (they're all about the same). You'll see they simply call an appropriate method on the controller object.
Finally, look at
This is a class you will modify.
This defines the object that needs to keep track of the various
versions and update the window appropriately.
Compile and run
You'll see a window appears on the screen, and you can type in it,
but nothing happens when you click on the buttons.
You'll be implementing the features of the buttons as you go along.
The first feature you will implement in the system is the ability to commit a version. When the user clicks the commit button, the text currently on the textfield should be stored (in computer memory; we won't be doing file I/O in this lab), that version should be given a new version number, and the "max" and "current" version indicators should be incremented.
Write a class to represent versions of the text. Think about what information would need to be stored in a version object, and write a constructor. Don't worry about methods yet, you'll write those as we go along.
Controller will need an instance variable to refer to the current
version and it will need a counter to keep track of the latest version number.
Finally, fill in the
commit() method in
so that it makes a new version and updates the indicators on the window.
Test to make sure this is working before moving on.
Now that the program has the ability to label the versions, we want to be able to retrieve an earlier version. Pressing the "previous" button should bring back the version that the current version was based on.
What information should your version class have in order for that to be retrieved? What method would the class need so that the controller can retrieve the previous version?
Implement this change in your version class and
previous() method in
Make sure all the instance variables of your
version class are private.
If the user tries to move to the "previous" version of version 1, nothing should happen (but the program shouldn't crash). Also, make sure that if the user navigates to an older version, edits, and commits, that the new version is given the next version number and is hooked properly into the chain of versions. At this point in development, it's ok if the later versions get lost; you'll fix that in the next step 4.
Test this feature before moving on.
Now update your version class and fill in the
Controller so that we can move
to the next version.
Now update the program so that if someone edits and commits based on an earlier version, the later versions are no longer lost, and the "-" button can be used to navigate among siblings, as described above.
Update the program so that the user can jump
directly to a version by giving its number.
(Hint: use an