Saint Louis University |
Computer Science 290
|
Dept. of Math & Computer Science |
Topic: Improved SceneEditor
Related Reading: Ch. 6 of text
Due:
Tuesday, 18 November 2008, 11:59pm
For this assignment, we make several improvements to the SceneEditor project from Chapter 6 of the text.
For this assignment, you may work in pairs (if you are having trouble finding a partner, please contact me as soon as possible).
Please make sure you adhere to the policies on academic integrity in this regard.
Our goal is to make the following four improvements to the SceneEditor application (based upon the scene3 implementation from the textbook).
Rather than displaying basic outlined forms for the shapes, we wish to allow concrete shape classes to use a combination of both outlined and filled shapes. For example, the car should be displayed with filled body and tires, but the outlined roof.
Rather than highlighting selected shapes using the template pattern in the book, we would like to display control points at the corners of a selected shape's bounding box (we use circles of radius 2 for our highlights).
The book has an aggravating user interface in the following respect. If you click and drag on a previously selected shape, that shape is not translated because the initial mouse click has the effect of deselecting the shape prior to the mouse drag.
We prefer the following behavior. A standard mouse click should toggle the selected state, as with the original program. If a mouse press/drag begins on an unselected shape, the shape should become selected and immediately dragged. However if a mouse press/drag begins on a selected shape, we wish to have that shape remain selected and consequentially dragged.
We want to allow the user to resize a selected shape by dragging any of the control points. For example, if the user clicks and drags the top-right control point, the shape should resize automatically so that the top-right corner of the bounding box aligns with the moving mouse pointer (the bottom-left corner in this case should remain fixed).
For the regular assignment, you may assume that the user will never drag the moving corner beyond the extent of the opposite fixed corner. That is, if the top-right corner is being moved, the user is presumed to keep it above and to the right of the bottom-left corner. (see extra credit description for more robust behavior).
Since a picture is worth a thousand words, we offer the following demonstration of all four improvements.
We address each of the four desired improvements.
We have already implemented the first improvement to allow a mix of filled and outlined components for a shape. To do this, we have had to modify the CompoundShape class as well as minor modifications to both the CarShape and HouseShape classes.
Within the CompoundShape class we still maintain the private GeneralPath instance for the outlined versions of all shapes. But we have added an additional Area instance for the filled shapes. We have modified the add method to include a boolean flag as a second parameter to designate whether each new piece should be filled. In either case it is added to the GeneralPath, yet in the filled case it is also added to the Area instance.
Please note that when a translate occurs, it is necessary to transform the path and the area. Similarly, within draw we must draw the path and the area.
You can determine the bounding box for a shape by calling the getBounds2D() method upon the underlying GeneralPath instance. Note: you need not worry about the Area instance for the bounding box as our model ensures that the GeneralPath has the full extent.
Make sure you first understand the cause of the problem. Only then should you decide how to redesign the logic to support the new semantics.
This is definately the most complicated part of the project. Yet it is possible to support resizing without making any changes to the concrete classes. This is because the underlying GeneralPath and Area objects support arbitrary affine transformations. An example of that appears in the existinging CompoundShape.translate method.
Note that the AffineTransform class provides a getScaleInstance to perform scaling. However the scale is performed relative to the origin of the coordinate system as a fixed point. If you try to use that transformation by itself, you will not get the desired effect in general. Objects would appear to drift away from the origin when enlarged.
Instead, you will need to carefully combine transformations. Specifically, the corner opposite to the one being dragged should appear fixed for this operation. You can accomplish this by first translating the shape so that the opposite corner lies at the origin. Then you can safely perform the scale, and finally do another translation so that the origin returns to the original position of the fixed corner.
Although we have based on project on the version of the code given by our textbook's author, we wish to have you begin with our modified code. This version includes the implementation for Improvement A.
Download files here or get them at turing.slu.edu:/public/goldwasser/290/assignments/scene4
Please submit the source code for your entire project, either as individual .java files or exported together into a single .jar file. If submitting the jar file, make sure that it contains the source code (not just the .class files).
Also submit a "readme" text file that details your design decisions for the project and an overview of the team members' contributions to the project.
Try the following on our demonstration. Grab and drag the top-right corner of a shape and pull it downward so that it goes even lower than the bottom edge of that shape. Our software allows such a drag and in essence inverts the displayed shape with the "top" appearing below the "bottom". We similarly perform left-to-right flips if a left control point is pulled to the right of the right edge or vice versa.
For extra credit, support such functionality with your own project.