To create a UI that sustains an interactive framerate by adapting what is drawn.
Write a Java program using JFC and the Swing components that allows you to browse a collection of images. Your program should allow you to do a few basic things:
A set of rectangles on a helix. The closer ones are solid,
the farther ones are hollow. The code is here in Helix.java |
The same helix, but with the rectangles much smaller and
the center points connected to show the spiral. |
When the user clicks and drags with the mouse (i.e., moves the mouse with the button pressed), the helix should spin and/or slide along it's axis (toward the upper right, toward the lower left). This allows you to browse the images in the directories based on their age.
The goal of the assignment is to ensure the program is running at interactive speeds at all times. Therefore, when the program starts, the user should immediately be able to start dragging and spinning the helix, and the helix should be animated at a high frame rate, regardless of the number and size of the images.
Your program should consist of a set of java files which should be commented with your name (the name you are registered under!) and ID number. The java file should implement a class "A3" (so the TA can save it as "A3.java", compile it and execute it using the command "java A3".) The files should be emailed to cs4470@cc.gatech.edu.
The time the mail is received will be used to determine whether or not the program is late, so be sure to allow a couple of minutes for the mail system to transmit your file if you are working right up to the deadline.
IMPORTANT: If the TA has to edit your files you will lose points. Similarly, the TA should be able to execute the class "A3", so using any other class as your main class will result in lost points.
This program is due on or before Friday, October 20th. This means it must be received by 11:59pm EDT on Friday to not be considered late.
Your program should create a default window of 640x480 pixels, and handle window resizing properly. The example Helix.java program shows how to align the principle axis of the helix along the window diagonal when the window resizes. The program should also not let you complete scroll the helix off the screen (the Helix.java program does that, too).
The principle tasks you need to do can be broken into two things: loading and manipulation.
The program should remain interactive when directories are being loaded:
When the helix is being manipulated, the program should remain interactive. You will degrade the helix display to do this.
To load objects quickly, you should have a thread traversing the directories. When it finds an image, it should create a new object which contains the information about that image (such as the filename, the time stamp to be used for sorting, size, etc.) as well as an Image object. Your program should use the ImageObserver Interface of the component used to display the helix to be notified as to when the object is loaded, when it's size is known, etc. Until the information is known, you should display as much as is possible: the filename, then an empty rectangle of the appropriate size, then the image.
As you load images, you should add them to the array of objects and ensure that it is sorted by timestamp, from newest to oldest. The Helix.java contains an example of how you use a custom comparator to sort an array of objects based on some data in the object.
Images are to be displayed as thumbnails. The size of the largest dimension is determined by the program (the imageSize variable, described below). You should determine how big each image should be, preserving the aspect ratio while setting the bigger dimension to the specified size.
Remember, only the main swing thread is allowed to change or otherwise manipulate the Swing objects. If there is something you want to do to the components from another thread, use the SwingUtilities package, in particular the "invokeLater()" method which provides a way of having the Swing thread run some arbitrary piece of code. This might be a good way to insert new files in the component without needing to use semaphores, for example.
Your program should constantly check how long the redraw's are taking and adjust accordingly. As you slide up and down the image helix, things may go slower or faster depending on the size of the images (if they are long and thin, and thus take less pixels, things might speed up). HINT: you should keep track of how you were drawing things when a drag ends, and start drawing that way the next time the user clicks and drags. That way, they will not see a jerk at the beginning when the first few refreshes are slow.
IMPORTANT: when the user is not dragging, all of the images on the spiral should be redrawn. This includes handling the case that they have the mouse held down, but are not moving.
In Helix.java, you will notice a number of variables that define the size and shape of the image helix. They are:
You should create a control panel that allows you to change these variables while the program is running. Together, they adjust the number of images displayed, and control the size of each image. You control panel should also have two additional entries:
There are a couple of possible extra credit for this assignment:
- The mouse interaction in Helix.java uses the X and Y motion to directly control the rotation and translation of the helix. It would be more intuitive if the motion was controlled by motion perpendicular to the helix (for rotation) and parallel to the helix (for the translational slide). Implement this for 1 point.
- Image selection. Add the following functionality. If the user holds down the control key while moving the mouse around on the screen, you should figure out which image they are over, and display a larger version of the image, plus all the information you have about that image, in the upper left corner of the display. You should draw a transparent square as the background for this information, and then place the rest of the information (the image, and the text describing it) in the square. You should draw this after the helix, so that if the helix and this area overlap, the helix is behind, and it shows through the transparent background. This is worth 2 points.