|
CSE 143 Spring 2001
Homework 5
Due: Electronic submission by 10 pm, Wednesday May
16. Paper receipt and written report due in quiz section on
Thursday May 17.
|
Overview
For this homework you will develop your drawing program from Homework
4 into a graphic editor that allows you to move your shapes, grow or
shrink them, and change their color. With the addition of the ability to
load and store your drawings in a file, you will be able to create
masterpieces of abstract art.
As with all assignments, please read the instructions all the way
through before beginning. Read them once again before you turn
in your assignment, to be sure you've left nothing out.
Concepts
This assignment builds on the last one. The goal is to
- gain more experience with class hierarchies,
- learn how to use linked lists, and
- build a more realistic graphics application.
This assignment is open-ended. There are some minimum requirements,
which are described here. But you are encouraged to use your imagination
and creativity to produce a great graphics editor.
Program Specification
As before, when the program starts, it opens a graphic window,
displays menus and enters an infinite loop, waiting for mouse clicks
and processing them. For this assignment, however, the menu structure should be
more complex, allowing the user to create and edit much more complicated
pictures.
Conceptually, there are two menus. The action menu should
provide at least the following
functions: pick, move, resize or delete an existing shape; add a new rectangle
or oval; and load or store the current drawing in
a text file. The menu should have a button for each of these functions. The
other menu, the color menu is a palette of
colors that allows the user to change the color of existing or new shapes. Your program must implement these
operations, and you are encouraged to add others.
As in homework 4, the program should react differently depending on whether
the mouse click occurred inside the action menu, the color menu, or
elsewhere in the window. When the user clicks on a button in the
action menu, that button is selected. The program needs to remember
the most recently selected button, as it affects processing of mouse clicks outside of the menus.
Action menu functions
First, some terminology. In graphics applications it is common to speak
about the bounding box of a shape. The bounding box is
the smallest rectangle that completely contains the given shape. For
a rectangle it is the rectangle itself; for a circle it is a square
with the same center as the circle and sides the same size as
the circle's diameter, etc.
This notion should be used a couple of ways in this program. First,
when the user creates a new shape (oval or rectangle or other), the new shape should be specified
by two mouse clicks that locate two diagonal corners of the shape's bounding
box.
Second, a key operation is picking an existing object. If the user has
selected the pick menu button, then the next click in the drawing window should
select the closest shape, subject to a couple of rules:
- The only shapes on the screen that can be selected by a pick are ones
whose bounding box contains the coordinates of the mouse click or are within
10 pixels of it (i.e., the click has to be near a shape to select it).
- Of the shapes that are close enough to the mouse click, the one that is
picked is the one whose center
is closest to the location of the mouse click.
If none of the shapes satisfy these conditions, the previously picked shape
remains "selected." If there are no shapes at all, then no shape is picked, of
course.
Your program will need to maintain (remember) the "user interface
state". This state
includes which button is selected from the action menu and the shape in the
drawing, if any, that is currently "selected." The UI state should also include any
additional information that you need in order to process mouse clicks
correctly. In most cases, the program remains in a particular state
until a different action menu button is selected.
For example, when
the user clicks on the "pick" button, the program
enters the state in which mouse clicks outside the menus pick the
nearest shape, as described above.
Here is a brief description of the action menu buttons that you are required to
implement:
- pick button is described above.
- move button allows the user to move the current shape.
When the program is in the move state, a mouse click outside the
menus indicates the new location for the center of the currently
selected shape. The coordinates of the shape should be updated and
the window redrawn to reflect the move.
- resize button allows the user to resize the current shape.
When the program is in the resize state, mouse clicks outside the
menus specify alternately the new lower left or upper right corners of
the current shape's bounding box. The coordinates and/or size of the
shape should be updated and the window redrawn.
- delete button removes the current shape from the drawing.
The window should be redrawn and there is no "current" selected shape
(we just deleted it!).
- rectangle button allows the addition of new shapes
to the drawing. When the program is in the "add a new rectangle" state,
each pair of mouse clicks in the drawing area adds a new rectangle to the
picture. The clicks specify opposite corners of the rectangle.
This differs from homework 4 in that there are two clicks, not one, and they
specify the corners, not the center of the rectangle.
- oval button adds a new oval to the drawing the same as with the
rectangle: each pair of mouse clicks specifies the corners of the bounding box
of the new oval.
- load from file button prompts the user for a file name,
loads a new drawing from that file and displays it in the window.
The format of the text file is similar to the one used in
Homeworks 1 and 2. For each shape in the scene, the file should contain the name
of the shape, coordinates of two corners of its bounding box, and its color,
represented as an integer (use the values found in GP142). For example, if there is a magenta rectangle in your
drawing with corners at (100,150) and (20,30), then the file should
contain a corresponding line that looks like:
rectangle 100 150 20 30 6
(6 is the numeric color corresponding to magenta in GP142). Exact details
of the file format are up to you. When a drawing is loaded from a file,
the new drawing should completely replace the existing drawing.
- store to file button prompts the user for a file name and
stores the drawing in that file. The format should be same as used in
your load command, so that storing and later loading from the same file
preserves the drawing.
You will need to make your own decisions about how the program behaves
in cases that are not specified above. For example, you may choose to
enter the "pick" state after deleting the current shape or after a
file load or store operation.
Color menu functions
Clicking on a particular color in the color menu should change the color of the
current shape to the selected color. Redraw the window to reflect the change.
Sample program
We have implemented a prototype program that demonstrates how some of
the required operations might work. You can download file hw5sample.exe
and use it to get some ideas about what your program could or should do.
PLEASE NOTE: This program is incomplete - it doesn't implement resize
for shapes, nor does it handle load
and store from a file, for example. It also has oddities in the user
interface that you might not want in your own program. Remember, this
sample is to help give you some intuition about how the user interaction should
work. Please do not try to reverse engineer it and make your program
behave exactly the same way, particularly in cases where this assignment doesn't
specify particular behavior.
Implementation Requirements
There are few specific implementation requirements for this assignment.
The two main ones are:
- You must implement a Shape class hierarchy similar to the one in homework
4. There should be a base class Shape, which must be an abstract class
this time. In other words, operations that are defined in Shape, like
draw(), that are part of the Shape interface but are not implemented in
class Shape should be pure virtual functions. You should derive
classes from Shape for specific shapes like Rectangles and Circles.
You do not need to print shape names or coordinates on the screen (although
you might want to print to the text window below the graphics window if it
helps you debug your program).
- You must implement a ShapeList class to store a list of pointers to the
currently allocated Shapes in the drawing. This class must use
a linked list as the underlying representation. As a matter of good
design, the individual Shapes should not contain pointers to other Shapes;
the linked list should be a separate data structure that contains pointers
to the Shapes.
This program will be more significantly more complex than homework 4, so good
modularity and careful class design, as well as good program organization and
coding style, will be more important than ever in getting it to work with a
minimum amount of pain.
Implementation Hints
Hint #1: Design first, code later.
Hint #2: See hint #1.
Take some time to think about what needs to be done to implement the various
program operations. What information do you need to create a new
shape? How are you going to look through the list of shapes and select the
one closest to a "pick" mouse click? What happens if shapes
overlap? What order should you draw them on the screen to be sure they
overlap properly? What do the interfaces to classes Shape and ShapeList
look like? What operations need to be provided? What parameters do
you need in constructors and other functions? How are you going to save
the information in a ShapeList to a file and reload it later? Sketch out
ideas on paper or on a whiteboard; think about tradeoffs; explore alternatives
before you commit yourself to detailed coding and testing of a particular
design.
Some additional random hints:
- Use your solution to homework 4 for ideas, but don't feel committed to
particular design decisions you made there if they don't apply in this new
setting.
- The only required class hierarchy is the Shape classes, but think about
things like menu buttons, user interface states and other things.
Maybe there are groups of related classes lurking here that should be
arranged as a class hierarchy.
- Be sure you create a single GP142Display object in your main
program and pass references to that object to functions that need to draw
something. Don't make copies (including call-by-value copies) of this
object, or strange things will happen.
- The GP142 package contains a constant named Rectangle, so it's best not to
use this name for your rectangle class. Sorry.
Testing
You should run your program to be sure it works properly.
Be sure to test each method that your classes implement; you
may need to write some additional code for that.
In particular, be sure to test your code that saves the drawing shapes to a
file and reloads them.
Extensions
This is your chance to do something exciting and creative. There are
lots of possible extensions to this project, and a small amount of extra credit
will be awarded for additional work. Here, in no particular order, are
some ideas that might help you think of something.
- Additional shapes (triangles, diamonds, ...)
- Filled shapes (draw the shape with the final argument of DrawRectangle,
etc., set to 0)
- Lines, arrows, curves, arcs, ...
- More complicated transformations (rotate, flip, ...)
- Move shapes to the front or the back of the drawing
- Select multiple shapes and group them into a single, selectable shape
- Better user interface (highlight selected menu items, dancing dotted lines
around selected shapes, ...)
- File merge - load shape information from a file and add it to the existing
drawing.
Use your imagination and have fun!!
Report
Your report should (briefly!) describe your program, what works and what
doesn't, and, in particular, how to use any new features you've
implemented. Describe decisions you made in interpreting the
requirements. Also describe your design, how it evolved, what changes you
made between the initial design and the final program, etc. Finally, what
did you learn from this project?
Electronic Submission
When you've finished your program, turn in the source program (.cpp
and .h files only) using the turnin form.
As before, do not turn in the GP142 files. Print out the receipt
that appears, staple it and your written report together, and hand it
in during quiz section.