HOMEWORK 5: Animation in the Interface
This is an INDIVIDUAL assignment.
Objective
In this assignment you'll learn how to do animation in Swing-based GUIs,
by adding some animated sorting and searching features to the Notebook
application.
The assignment is to augment the PageSorter to add "magnets" that attract
pages with certain tags on them. Different magnets attract
different tags, so by placing magnets in the sorter you can "pull out"
pages of interest. Thumbnails should smoothly move toward the magnets
that attract them.
The learning goals for this assignment are:
- Experience building threaded animation loops in Swing.
- Experience integrating animated components into a Swing application.
- Experience with exploiting principles of good animation in an interactive
tool.
Description
In this homework we'll add some basic animation functions to the PageSorter,
to provide the user with a novel way of finding pages that have certain
tags.
The basic idea is that we'll introduce the concept of "magnets" to the
interface. Magnets are simply on-screen objects that are set to
attract thumbnails with certain tags.
For example, if you drop an "Action Item" magnet on the PageSorter, it will
pull to it all thumbnails that have that tag. If you then drop an "Appointment"
magnet on the PageSorter, thumbnails that have bothtags will move
halfway between the magnets, while thumbnails that have only one will move
to that magnet.
You should be able to drag magnets around the screen to have the thumbnails
follow appropriately.
As an aside, this interaction technique basically gives you a physical model for
simple basic boolean searches. Placing multiple magnets near each other
represents an OR operation: pages that have either of the
magnets' tags are attracted to that spot. Likewise, placing magnets apart from each other lets you
do AND operations: thumbnails that have both tags move to the center
between the two magnets, as they're attracted equally to both.
You could easily imagine extensions to this such as NOT operations implemented
as magnets that repel certain tags.
Although our tags are simple booleans (the tag is either there or it
isn't), rather than scalars (which would mean they have some value), you
could do some cool things with scalar tags. For example, thumbnails that
have "more" of a certain property might be attracted more strongly (and
move more quickly) toward a magnet that attracts that property.
You'll have to extend your interface slightly to provide mechanisms for
adding, removing, and moving the magnets:
- Some kind of control for placing a magnet of a certain type on the
PageSorter.
- Some kind of control for removing said magnet from the PageSorter.
- Some technique (probably dragging) to move the magnet around.
You'll also have to implement the code that moves pages around
in response to the placement of magnets. See below for some details on how
you might go about doing this.
NOTE: My intention with this assignment is just to have people focus on
doing animation in Swing, so I don't want to break the existing behavior
of folks' PageSorters. Obviously, if you have magnets moving pages all
over the place, it may not make sense to also use the PageSorter for
reordering pages at the same time. So, for this assignment, you're allowed to follow any
of the strategies below for how to make sure the animation doesn't
conflict with the basic PageSorter functionality:
- You could have an explicit mode switch in your UI that lets you toggle
between normal PageSorter mode and magnet mode. When you're in normal mode
you can't place magnets or do anything with magnets, but the basic
PageSorter functionality should work. In magnet mode, all of the magnet
functionality is enabled, but dragging pages may not reorder them (in fact,
it's ok if pages aren't draggable at all in magnet mode).
- You could have an "implicit" mode, where once any magnet is placed
magnet mode is enabled; once the last magnet is removed, pages jump back
to their normal order and standard PageSorter mode is enabled.
- You could also do this as a separate view that doesn't reuse the
PageSorter window at all.
The basic gist of the above is that the original PageSorter functionality
has to keep working, but that you can add modes or separate windows if you
choose, to make it easier to keep the basic sorter functionality from
conflicting with the magnet functionality.
Implementing the Animation
This section provides some implementation tips for getting things working.
Please also check the slides for tips on Swing threading, etc.
The basic UI controls for adding, moving, and removing magnets should
hopefully be straightforward. Magnets should appear graphically on the
PageSorter window, although they can be simple labels or the like. If your
PageSorter/thumbnail code has assumptions that only thumbnails can be stored
in the PageSorter, you may have to tweak things a bit to remove this
assumption, to allow for the magnets. The code to move the magnets should
be very similar to the code you use to drag thumbnails in the sorter.
Doing the animation itself will be slightly trickier, but hopefully not a
lot of work. The way I'd suggest doing it is the following:
- Build yourself a little notification system so you can learn when
magnets are placed on the sorter or moved. You could simply add a listener
for ComponentEvents to the magnets to learn about magnets'
change in visibility or location.
- Everytime there's a change, you want to fire off some animation
thread(s) to update the positions of all of the affected page thumbnails.
There will likely be several substeps to this process.
- First, figure out where all thumbnails are now and where they need
to be in relation to the magnets. This will probably just result in
a HashMap or something that has the ultimate positions for each
thumbnail. For each component, figure this out by looking at its
tags, then seeing if there are magnets that attract those tags. The
target location should be the centroid of all of the magnets' locations that
have those tags.
- For each thumbnail whose desired location is not its current
location, fire off an animation thread that starts moving it. The duration
of the animation is up to you, but I'd make it long enough that it's
clear what's going on.
- If a magnet moves while an animation is already in progress,
you have a couple of options. First, you can just drop the thumbnails
where they are, recompute the new desired locations, and then start new
threads that move them from their current position to the new target.
Second, if each thread is pulling its destination out of some data
structure, you can just update the target location in that data structure. In
either case, your UI should behave nicely when magnets move while an
animation is in effect--you should be able to drag a magnet around
the screen and have thumbnails follow behind it.
Remember that updates to Swing components--like changing their locations--must
be done on the event dispatch thread. So you'll most likely be using a
javax.swing.Timer to do the updates.
Extra Credit
As usual, there are a lot of ways to make this fancier than described.
- Implement some of the "good animation principles" we descibed in class,
such as slow-in/slow-out, anticipation/follow-through, motion blur, or squash-and-stretch.
+1 for slow-in/slow-out or anticipation/follow-through, +2 for motion blur, +3 for
squash-and-stretch.
- The basic magnet model outlined above only supports OR boolean operations
directly; AND is a hack since it involves placing two magnets.
Add fancier magnets for AND (which would be a magnet that only attracts
thumbnails with multiple tags) and NOT (which would be a magnet that
repels thumbnails with a certain property). +3 points.
- A downside of the basic magnet approach is that all of the thumbnails that match
a certain magnet pile up on top of each other, meaning that you can't see
them easily. Implement some sort of "pile" appearance where thumbnails
cluster on each other, but it's still clear that there are multiple
thumbnails. +2 points.
As usual, if you do something else that's above and beyond the call of duty,
let us know in your README file and we may assign some extra credit for
it.
Deliverable
This is an INDIVIDUAL assignment; while you may ask others for help on Java
or Swing details, please write the code on your own.
While this assignment is significantly more difficult than the previous
one, most of the parts should be fairly straightforward. Start with the
basic PLAF component architecture and get that working in your
application first; one easy way to do this is to implement the UI
class's paint method so that it only draws the page background. This way
you'll be able to see your component show up and know it's working
correctly. After this do the stroke processing (it's the next
easiest), followed by the text processing (slightly more complicated).
Finally, once all of this is working, it should be fairly
straightforward to keep a list of notepage components in your
application and make the New/Delete/Next/Previous controls work.
To turn in the assignment, please follow the same process as last time:
0. Make sure your program is runnable from the command line using the command "java NotebookApp" when run from inside your project directory (described below). Use exactly this name (with no package) to make things easier on me and the TAs.
1. Create a new directory using your last name as the name of the directory.
2. Compile your application and place both the sources and classfiles into this directory (they can be at the top-level or in a subdirectory, whatever you want).
3. Put a README.txt file into the top level of the directory. This file should contain your name and email address, the version of Java you used (1.5.x or 1.6.x, please) as well as any special info we migiht need in order to run your code.
4. 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 depencence 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 ZIP file and that your code will refer to them
and load them properly when from inside the directory that's created when
I unZIP your code.
Grading for this assignment, and future assignments, will roughly follow
this breakdown:
- 60% functionality
- 40% good architectural design, coding style, commenting
Please let the TA or me know if you have any questions.