Handout P7

Contents:

Getting started

As usual, the source code that you need can be found by updating your cse331 directory from SVN.

Introduction

In this problem set, you will implement a graphical user interface for Husky Maps.

Preventing null pointer errors via type-checking (20 points)

The Nullness Checker gives you a compile-time guarantee that your code has no null pointer errors. Some students have been using it since PS2. Starting in PS7, all students will use it. Your code must pass the type-checker, and you will be marked down if your code works around the type-checker.

If you have been using the Nullness Checker all along, you just need to continue to write nullness annotations in the new code you write, and to ensure that the Nullness Checker issues no warnings about possible null pointer dereferences. You can skip to the next part of the problem set.

If you have not been using the Nullness Checker so far, then continue reading. Starting with PS7, the Nullness Checker will be automatically run on all your problem set code when you compile it with Ant (or when you run ant check-nullness). The Nullness Checker issues a warning in locations where your code might suffer a null pointer exception. If it issues no warning, then your code cannot suffer a null pointer exception; this is your goal.

To help the Nullness Checker to verify the correctness of your code (or to discover nullness-related errors!), you will need to go back to all your old problem sets and add nullness annotations. Once you have added annotations, you will ensure that the Nullness Checker issues no warnings about possible null pointer dereferences. You may need to fix errors or refactor your code to improve its design.

Adding the annotations should be a simple matter of searching your Javadoc for the word "null" (for instance, when you have written documentation that a parameter, return value, or field may be null) and then writing the appropriate annotation in those locations. If you didn't document your code sufficiently, then you will have to do some more work, but it's still a good idea to write annotations before you start to run the Nullness Checker. This approach has proven to be much more effective than simply running the checker over and over and trying to resolve its warnings one by one.

To get started, read the instructions from PS2, including the linked-to information: the CSE 331 Checker Framework handout and the relevant portions of the Checker Framework manual that are referenced from that handout.

Graphical User Interface (40 points)

You were asked to mock-up a graphical user interface for Husky Maps in Problem Set 6. In this problem set, you will implement your GUI (taking into account your TA's feedback and comments).

It is possible that you might have designed a very fancy and comprehensive user interface in Problem Set 6. You are allowed to implement that GUI (or perhaps an improved version after taking into account comments from your TA), or a simpler interface. Your GUI must support at least the following minimal set of features:

  1. Selecting a Tiger database directory
  2. Entering zipcodes for filtering
  3. Entering addresses
  4. Selecting direction type
  5. Displaying directions
  6. Drawing a map of the route
  7. Toggling the display of street names on the map.

Loading a database

The user should be able to select any TigerDB — i.e., the user should be able to specify any directory. You might consider using a JFileChooser.

It is a good idea, though not required, to use a separate thread for loading the database, so that the GUI does not become unresponsive while the database is loading.

Route map

In addition to the features that you incorporated into your GUI design in Problem Set 6, Husky Maps will also display a map of the generated route and connecting roads (to provide context); the user will be able to toggle the display of street names on the map.

Scaling the map

The user must be able to resize the map — perhaps by resizing the Husky Maps application window that contains it. When you start Husky Maps, the default map view must be 600 pixels wide and 400 pixels high.

In the map display, the route should be scaled to be as large as possible, then centered in the display. The scaling should be uniform in the x and y directions, and should leave a 5% buffer on each side of the route between the route and the window edge. Here are two diagrams demonstrating route positioning:

bounding boxes example

Here is another way to state the requirement. First, find the bounding box of your route. The bounding is a rectangle that the route fits inside, and that the route touches on all 4 sides (possibly in the middle of a side, possibly at a corner). Now, scale the route (grow or shrink it, keeping its aspect ratio) until the bounding box edges that are closest to the map view edges are exactly 5% away. In the other direction, the bounding box edges might be 5% away (if the bounding box has exactly the same aspect ratio as the window), but they are likely to be further away.

Context: nearby roads

To provide the user with context, the map will display all roads that are accessible from the path without traveling off the edge of the map. As shown in the diagram below, the route should be shown in green while other streets are shown in black.

route map is in green

Hint: Note that some road segments are only partially drawn because the road goes off the visible part of the map. This is very easy to handle: your code can just draw the entire segment, and the Swing components will only display the visible portion.

The roads shown in blue below are not drawn because they are only accessible by traveling outside the displayed region. (This restriction simplifies your algorithm.)

roads in blue are not drawn

Modifications to Problem Set 6

To implement the map, we suggest that you modify your Directions and DirectionsFinder classes as follows:

You may also need to make other changes. Be sure to write specifications for any functions and classes you write. Whenever you change your code, you should also run regression tests.

Street type

The width of the streets should correspond to the type of street segment. Primary highways should be drawn thicker than secondary highways, which are drawn thicker than local roads, which are drawn thicker than unknown roads. Be sure to document how the various types of roads are displayed.

Street name

By default, your GUI should display each street name that appears in the route. Do not display street names for streets that are not part of the route. For each set of contiguous street segments with the same name, display the street name once (think GeoFeature). Draw the street name horizontally, centered in the bounding box of the GeoFeature.

The user can toggle the display of street names (it starts in the "on" state). Optionally, you could also permit the user to display names for streets in the context.

GUI launch requirements

Your GUI should be named ps7/GraphicUI.java, so that the command java ps7.GraphicUI (with the appropriate classpath) launches Husky Maps's graphical user interface. Your program may interpret additional command-line parameters, but the system must run when invoked without any additional command-line parameters.

GUI launch when using ssh to log into attu

If you log into attu via ssh, but when you try to run your GUI on attu you get a message similar to

Exception in thread "AWT-EventQueue-0" java.awt.HeadlessException:
No X11 DISPLAY variable was set, but this program performed an operation which requires it.

then you need to enable X11 forwarding for your ssh session. If you are are using Linux, this can be done using the -X switch when starting ssh:

ssh -X YourUserName@attu.cs.washington.edu

If you are using Windows, you will need to obtain special software such as Cygwin, Reflection X, or X-Win32. Cygwin is available for free. A very old version of Reflection X is free to members of CSE. X-Win32 is free to members of UW, and is the best choice. The latter two are available from UW CSE Support.

Swing widget requirement

Use only components from the Swing widget set for this assignment. You are also allowed to use components from AWT, on which Swing is built, but should try to stick to Swing when possible.

For such a simple GUI, programming from scratch in Java is a very reasonable choice (and the only one officially supported by the course staff). Alternately, you are allowed to use NetBeans (or some other visual GUI builder) to auto-generate the code for your GUI. If you do so, you should state clearly in your documentation what GUI builder was used, you must check the GUI builder source file(s) (for example, the NetBeans .form file) into SVN, and you must document those source files to enable another developer to understand or modify them.

Optional features

After you have completely implemented, tested, and documented the required functionality, you might wish to implement some of these features (or others of your own devising):

If any of these features are added, they cannot affect the behavior of the ps6.TextUI class. Therefore, in order to demonstrate them, you could:

Work on optional features will gain special credit. Such credit will be held in reserve and applied when we compute your final grade after we have ranked the students in the class. This will ensure that students who do not choose to work on optional features will not be penalized in any way, but students who do are rewarded appropriately. Please remember to document the optional features that you implement clearly. If you should implement a feature that is not visually obvious, it is possible that your TA might miss it and not award you credit for it.

You may complete these features anytime up until you submit PS8, if you tell your TA about them.

Assessment of pluggable type-checking (12 points)

Like any tool, pluggable type-checking has its strengths and weaknesses, and should only be used in appropriate ways and situations.

Please answer the following questions in a file named assessment.txt in your answers/ directory. There are no wrong or right answers, but we expect your answers to be thoughtful. If you used the Nullness Checker throughout the quarter, then your answers should reflect the whole quarter. If you started using the Nullness Checker just with this problem set, then your answers will reflect just this problem set. In this entire question, “change” means a change to code, not merely adding an annotation.

  1. Did you use the Nullness Checker starting with PS2 or with PS7?
  2. Did the Nullness Checker reveal null pointer errors in your code? If so, describe at least one of them. Why did testing fail to reveal this error?
  3. Describe the largest or most difficult change that you made, as a result of running the checker, that improved your design or your code. How long did it take you to make the change? Would it have been easy to choose a nullness-correct design in the first place, if you had been thinking about nullness-correctness from the beginning? Be concrete — name the class and method(s). You may paste code but are not required to do so.
  4. Describe the largest or most difficult change that you made, as a result of running the checker, that degraded your design or your code. How long did it take you to make the change? Why did you have to make this change? As in the previous part, be concrete.
  5. Describe the most frequent change that you made — where you had to do the same thing repeatedly in different parts of your code. Give a single example, by pasting from your source code. How often did you have to make such a change?
    Or, state that no such pattern existed.
  6. What missing feature or behavioral difference, either in the checker or its set of annotations, would have made your task easier?
  7. Suppose your goal was to improve your code. Is obtaining a static guarantee of no null pointer errors the best use of time? If not, what would be? For example, do you think you would have obtained better code by spending the same amount of time on other tasks such as writing tests, reasoning about the code, rewriting some of it, writing more assertions, playing with the software to see if the directions it produces are suspicious, etc.?
  8. Briefly describe a defect (bug) that you have encountered in the class that caused you difficulty. It should not be nullness-related. Would this defect be amenable to discovery via type-checking? (Some are, and some are not.) Explain why or why not.

Collaboration (1 point)

Please answer the following questions in a file named collaboration.txt in your answers/ directory.

The standard collaboration policy applies to this problem set.

State whether or not you collaborated with other students. If you did collaborate with other students, put their names and a brief description of how you collaborated.

Reflection (2 points)

Please answer the following questions in a file named reflection.txt in your answers/ directory.

  1. How many hours did you spend on each problem of this problem set? (Only include time when you are completely focused on CSE 331. For example, if you worked an hour in your noisy dorm lounge, or you were periodically reading email or IMs, don't count that hour.)
  2. In retrospect, what could you have done better to reduce the time you spent solving this problem set?
  3. What could the CSE 331 staff have done better to improve your learning experience in this problem set?
  4. What do you know now that you wish you had known before beginning the problem set?

What to turn in

The following files should be checked into SVN before you run ant validate:

Additionally, your code should pass the Nullness Checker.

Hints

If you're having trouble, the forums are a good place to look for help.

Errata

(None yet.)

Q & A

This section will list clarifications and answers to common questions about problem sets. We'll try to keep it as up-to-date as possible, so this should be the first place to look (after carefully re-reading the problem set handout and the specifications) when you have a problem.