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 Photo Album
application.
The assignment is to augment the Light Table to add "magnets" that attract
photos with certain tags on them. Different magnets attract
different tags, so by placing magnets in the Light Table you can "pull out"
photos 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 Light Table,
to provide the user with a novel way of finding photos 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 a "Vacation" magnet on the Light Table, it will
pull to it all photo thumbnails that have that tag. If you then drop a "Family"
magnet on the Light Table, 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: photos 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
Light Table.
- Some kind of control for removing said magnet from the Light Table.
- Some technique (probably dragging) to move the magnet around.
You'll also have to implement the code that moves thumbnails 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' Light Tables. Obviously, if you have magnets moving photos all
over the place, it may not make sense to also use the Light Table for
reordering photos 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 Light Table functionality:
- You could have an explicit mode switch in your UI that lets you toggle
between normal Light Table mode and magnet mode. When you're in normal mode
you can't place magnets or do anything with magnets, but the basic
Light Table functionality should work. In magnet mode, all of the magnet
functionality is enabled, but dragging photos may not reorder them (in fact,
it's ok if thumbnails 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, photos jump back
to their normal order and standard Light Table mode is enabled.
- You could also do this as a separate view that doesn't reuse the
Light Table window at all.
The basic gist of the above is that the original Light Table 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 sorting 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
Light Table window, although they can be simple labels or the like. If your
Light Table/thumbnail code has assumptions that only thumbnails can be stored
in the Light Table, 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 Light Table.
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 Light Table 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 photo 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 midpoint 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 you can use any development environment you choose, you are not
allowed to use "GUI builder" type tools (like JBuilder or Eclipse GUI
Builder).
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 "j
ava PhotoAlbum". 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 (described below) 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 I might need in order to run your code (command line
arguments, etc.)
4. ZIP this directory and submit it via T-Square (instructions are here).
If you do any extra credit work, be sure to let us know about it in the
README file so that we don't miss it!!
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 ZIP file and that your
code will refer to them and load them properly when from 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.