The complete specification of assignment #6 can be found as part of the stream at iTunes.
Complete the implementation of NameSurferGraph class
In addition to creating the background grid, the update method in NameSurferGraph also has to plot the actual data values. The NameSurferGraph class includes two methods for specifying what entries are displayed on the screen. The addEntry method adds a new NameSurferEntry to a list of values that are currently on the display. The clear method deletes all of the entries in that list so as to clear the graph.
There are a couple of points that you should keep in mind while implementing this part of the program:
- To make the data easier to read, the lines on the graph are shown in different colors. In the sample applet on the web site, the first data entry is plotted in black, the second in red, the third in blue, and the fourth in magenta. After that, the colors cycle around again through the same sequence.
- The fact that rank 1 is at the top of the window and rank 1000 is at the bottom means that it can sometimes seem confusing that rank 0—which means that the name does not appear in the top 1000 values for that year—appears at the bottom. To reduce the apparent discontinuity between rank 1 and rank 0, the entries for names that are absent from the data for a decade are listed with an asterisk instead of a numeric rank.
The name-surfer class needs an update to call the methods of the graph class when actions occur:
public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if ((source == nameField) || (source == graphButton)) { graph.addEntry(dataBase.findEntry(nameField.getText())); } else if (source == clearButton) { graph.clear(); } }
The graph class needs an instance variable to hold the chosen name entries:
private ArrayList<NameSurferEntry> data = new ArrayList<NameSurferEntry>();
It gets filled with entries from the main class when the entry is valid and does not already exisit.
public void addEntry(NameSurferEntry entry) { if (entry == null) return; if (data.contains(entry)) return; data.add(entry); System.out.println(entry); update(); }
And gets cleared completely when the clear button is hid:
public void clear() { data.clear(); update(); }
The update method loops over all entries to display them:
public void update() { removeAll(); drawGrid(); Iterator<NameSurferEntry> it = data.iterator(); while (it.hasNext()) { drawEntry(it.next()); } }
To draw an entry, its name is printed with the rank or with an star when there is no rank, the graph itself is drawn as consecutive lines:
private void drawEntry(NameSurferEntry entry) { String name = entry.getName(); int rank = entry.getRank(0); double dx = getWidth() * 1.0 / NDECADES; double x0 = 0; double y0 = yValue(rank); Color color = COLORS[data.indexOf(entry) % N_COLORS]; drawLabel(name, rank, x0, y0, color); for (int i = 1; i < NDECADES; i++) { rank = entry.getRank(i); double x1 = x0 + dx; double y1 = yValue(rank); GLine line = new GLine(x0, y0, x1, y1); line.setColor(color); add(line); x0 = x1; y0 = y1; drawLabel(name, rank, x0, y0, color); } } private double yValue(int rank) { if (rank == 0) rank = MAX_RANK; return (getHeight() - 2 * GRAPH_MARGIN_SIZE) * rank / MAX_RANK + GRAPH_MARGIN_SIZE; } private void drawLabel(String name, int rank, double x, double y, Color color) { String text = name; if (rank == 0) { text += " *"; } else { text += " " + rank; } GLabel label = new GLabel(text, x + LABEL_OFFSET, y - LABEL_OFFSET); label.setColor(color); add (label); }
… and again constants:
private static final int LABEL_OFFSET = 3; private static final Color[] COLORS = {Color.BLACK, Color.RED, Color.BLUE, Color.MAGENTA}; private static final int N_COLORS = 4;
The code for this assignment is available on github.