Course Links

Exercises

Resources

External

Class Specifics: MapViewer

The MapViewer class will be responsible for displaying a particular view of a particular MapGrid. Thus it must have a field to keep track of the MapGrid to be displayed, and additional fields holding the parameters describing how the map will be drawn within the viewpoint. These will consist of a magnification or scale specifying the size (in pixels) of the square that should be drawn for each grid element, and an offset specifying where the upper left corner of the map grid squares should be drawn relative to the viewport window. The offset could be stored as two int fields, or the more ambitious can store it using the core Java class Point. The dimensions of the viewer window may be set to a constant as is done in Lab 2 for class WidgetCanvas, or you may make these into modifiable fields as well. Look below for more details on how to use these parameters when drawing the map.

Once the fields are defined, you should turn to the constructors, accessors, and manipulators. The constructor need only take a MapGrid as an argument, and set reasonable values for the viewpoint fields (for example, origin at (0,0) and magnification 10). If you wish, you may define a second constructor with arguments that set all the fields to arbitrary values, and/or a copy constructor. There should also be standard accessors and manipulators for all fields (except perhaps the MapGrid itself).

As mentioned in class, because the MapViewer class needs to display things in a graphics window, it must be a subclass of Java's JComponent class. For proper behavior, it will need to override the paintComponent() method inherited from the parent class. Your version of the method should display the current view of the map, as described in further detail below. Also, don't forget to call setMinimumSize() and setPreferredSize() in the constructor. The display dimensions specified for these can be some fixed constsant, say 300 by 500 pixels. They must be given in the form of a Java Dimension object.

(One other note: Just as there are methods you must override when you inherit from an existing class, there are others you should be careful not to. JComponent already has methods named getX(), getY(), getHeight(), and getWidth(). If you accidentally override any of these with your own versions, you will probably get very interesting and hard-to-understand bugs!)

You may use the JCircle class from lecture as a rough guide for what the MapViewer class should do, although MapViewer will differ in details and complexity. As subclasses of JComponent both classes must define their own paintComponent() methods. But the paintComponent() method will draw the series of colored squares from a MapGrid instead of a simple circle. The easiest way to draw the map is to simply to draw every square of the grid, starting from the offset position. (For example, if the magnification is 10 and the offset is (0,0), then the upper left square of the map will extend from (0,0) to (10,10). But if the offset is (-15,25) then the square should be drawn from (-15,25) to (-5,35) instead. The square immediately to its right will extend from (-5,25) to (5,35), etc.)

To carry out the drawing you will make two nested loops, one over the rows and the other over columns, and inside the inner loop you will draw one rectangle of the appropriate color, and compute its coordinates from the loop indices, the offsets, and the magnification. Areas that do not fall within the coordinates of the viewing window will not be visible, but it doesn't cause trouble if your program attempts to draw them. (Note that this is not necessarily the most efficient approach, but we are making it easy on ourselves. You may try to improve the efficiency when you have the basic program working.) Conversely, your program should still be able to operate if the offset is such that an area beyond the map's edge will appear in the window. You can leave this undefined area painted in some uniform color.

The diagrams below illustrate the behavior of the viewer. The map coordinates are shown because paintComponent() will need them to draw the squares correctly.

This shows the situation with an offset of (0,0) and a magnification of 6. (Click for high-resolution.) The red dashed line shows the outline of a 42x36 pixel viewing area. Coordinates are shown at the corner point of each map square, for selected squares. The square boundaries are shown here for clarity; the actual viewer window will display something like the image below:


This shows the situation with an offset of (0,0) and a magnification of 4. (Click for high-resolution.) The viewing area is the same as before. Only the portion below will be visible in the viewer window.


This shows the situation with an offset of (-15,-6) and a magnification of 6. (Click for high-resolution.) The red dashed line shows the outline of the viewing area, and the purple arrow shows the offset of the map origin relative to the viewport origin. Compare the coordinates in the first example with the one here: the offset is added to the coordinates of all the squares. Only the portion below will be visible in the viewer window.


This shows the situation with an offset of (12,-32) and a magnification of 6. (Click for high-resolution.) In this case, part of the viewer window has no map data. You may show undefined areas in white, black gray, or any other color you wish, but your viewer will ideally handle situations like this without any trouble. ("Here there be Dragons" text is strictly optional.) The viewer window display for this situation is shown below.

(A question: Which MapGrid should be drawn? It should be the one that was supplied when you invoked the constructor -- you will store it in a field of the MapViewer class. You can use its accessors to find out what color each square should be drawn in.)