The learning goals for this assignment are:
We will provide a way for the user to zoom out of the current page in the content area, to see all the pages in the journal, and select one to zoom back in to it. This will work much like the Exposé feature in the Mac OS X interface (see here if you're unfamiliar with this feature).
When the user clicks one of these pages, a reverse animation should be done that zooms you in to the selected page, which then works normally again.
Sweating the details is important in an animation like this. Remember that one of the uses of animation is to allow the user to maintain a sense of context during a change in the interface. Because of this, you want to ensure that there's consistency between the page that's being viewed when the transition starts, and where that page ends up when the transition finishes: as the currently viewed page begins to shrink during the switch into page overview mode, it should shrink *into* its final position in the grid so that the user can follow it visually.
Start by creating a new component that will act as a container (parent) for all of the individual page components in your application. As a container, this component will have references to all of the individual page components contained within it (and so can selectively render them, pass tweaked Graphics objects to them, etc.). In the "default" mode, this container will display only the current page--much like a container with CardLayout will only show one component at a time. (Start by making sure that introducing this new parent doesn't "break" anything: displaying a single page, resizing, doing next/prev/delete should all still work before you continue.)
When Overview Mode is activated, the desired visual effect is that the container should cycle through an animation that zooms out, rendering all of the pages as they shrink and move into their final positions in the grid. You might consider doing this by setting an "overview mode" flag in the container that tells it not to paint "normally," and then spinning off an updater thread that periodically updates whatever variables need to be updated as you cycle through the animation. Override your paintChildren() method to look at these variables to determine which mode it's in and how far it is through the animation. To render the thumbnails, I'd suggest creating a Graphics2D object that's scaled with the current value (you can call scale() on the Graphics2D object), and then iterate over each of the child page components, passing the Graphics2D object to their paint() method to have them each draw themselves.
Listen for mouse clicks in the container to figure out when a click is made; translate that to the bounds of the shrunken pages in the grid, and then start the animation to bring the selected page to the foreground. After this zoom-out transition, you can go back to the "default" mode where you just show the one current page. Note that while in the zoomed out view, page components don't need to be responsive to drawing or text input or any of the normal things they do when they're filling the screen.
Hint: Since you're essentially controlling the layout (size and position) of the child page components explicitly, you'll want to make sure that you turn off the LayoutManager for your container by setting it to null, since you don't want to be competing with it for how to set the children's layout.Hint: For the basic container architecture, I'd suggest starting by subclassing JComponent. Any time your application creates a new page component, it should call add() to add it to the container's list of children (note that this is the *same* method that normally gets called to add children to *any* component).
Hint: Having repaint problems? Are your changes not getting reflected on screen? Be sure to call revalidate() anytime the set of children changes, or your size changes.
The way this should work is that a quick click on the next/previous buttons should cause a single page to flip. Holding down the next/previous buttons, however, should cause multiple pages to begin flipping, continuing at some rate until the button is released.
The page flips themselves should be animated in such a way that they resemble physical pages. How you do this is up to you; for example, you might consider pages that are peeled back by their corners, pulled across from their sides, or that flip up or down like an old-style Rolodex (transforming/skewing as they go).
You might consider some additional twists on this, such as using a "swipe" gesture to turn pages, or allowing the user to "grab" the page with the mouse to pull it back, with the page following the mouse as it moves.One way to implement this is to render the current and next pages to BufferedImages (just create a BufferedImage and have the components paint() themselves into it). Once you have an image of the components you can again spin off a thread to step through the animation of the page flip; in the paintChildren() method you can render these using whatever visual effect you have chosen, complete the animation, and then simply display the new page in the "default" mode. In the Swing Hacks book, Hack #8 (Animate Transitions Between Tabs) is a reasonably good model for how you might structure the page flipping behavior.
Depending on the complexity of this and how many features you add, up to +10 points in total.
Here are the details for how to turn in the assignment. We'll be using this structure for all of the turn-ins:
1. Create an executable JAR file named courier.jar that contains your runnable application. (See here for details on how to create executable JAR files.) We should be able to run your program by typing "java -jar courier.jar" on the command line; please be sure that your application runs correctly using ONLY this command, and that it doesn't require any additional CLASSPATH or other environment variables, no additional parameters, no classfiles or images located outside the JAR file, etc.
2. Create a new directory using your last name as the name of the directory.
3. Put the courier.jar file into the top level of this directory, and all of your source files into a "source" subdirectory inside this directory.
4. Put a README.txt file into the top level of this directory. This file should contain your name and email address, the version of Java you used (Java 1.6.x only, please) as well as any special info we might need to know about your program (let us know if you did extra credit, for example).
5. ZIP this directory and submit via T-Square (instructions are here).
Please take care to remove any platform dependencies, such as hardcoded Windows path names or dependence on a particular look-and-feel that may not exist on all platforms. Also, if you use any images in your application, please make sure that you include these in your JAR file and that your code will refer to them and load them properly when they're in this JAR file (see this page for some details on how to include and load images from within a JAR file).
Grading for this assignment, and future assignments, will roughly follow this breakdown: