-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExtension_NameSurferGraph.java
More file actions
246 lines (206 loc) · 7.14 KB
/
Extension_NameSurferGraph.java
File metadata and controls
246 lines (206 loc) · 7.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*
* Name: Rachel Sun
* File: NameSurferGraph.java
* ---------------------------
* This class represents the canvas on which the graph of
* names is drawn. This class is responsible for updating
* (redrawing) the graphs whenever the list of entries changes
* or the window is resized.
*/
import acm.graphics.*;
import java.awt.event.*;
import java.util.*;
import java.awt.*;
public class Extension_NameSurferGraph extends GCanvas implements NameSurferConstants, ComponentListener {
// Define an array list that will be used to store the entries.
ArrayList<Extension_NameSurferEntry> entryList = new ArrayList<Extension_NameSurferEntry>();
/*
* The constructor creates a new NameSurferGraph (GCanvas).
*/
public Extension_NameSurferGraph() {
addComponentListener(this);
}
/*
* Method clear empties the record in the arrayList entryList, and
* simultaneously update (clear) the graph.
*/
public void clear() {
entryList.clear();
this.update();
}
/*
* Method addEntry takes a NameSurferEntry and records it into the arrayList
* entryList. By doing so this particular entry will be ready to be put on
* canvas.
*/
public void addEntry(Extension_NameSurferEntry entry) {
// Add this entry to the array list.
entryList.add(entry);
// Update graph.
this.update();
}
/*
* Method removeEntry takes in an entry and remove it from the arrayList.
*/
public void removeEntry(Extension_NameSurferEntry entry) {
entryList.remove(entry);
this.update();
}
public boolean graphExist(String nameEntry) {
for (int i = 0; i < entryList.size(); i++) {
if (nameEntry.toLowerCase().equals(entryList.get(i).getName().toLowerCase())) {
return true;
}
}
return false;
}
/*
* Method drawGraph defines how a single entry is displayed on the graph. It
* is to be called by the update method every time the graph is updated.
*/
private void drawGraph(int entryListIndex) {
// The method takes in an arrayList index,
// and gets that entry first.
Extension_NameSurferEntry entry = entryList.get(entryListIndex);
// For convenience, make variables to store the size,
// dimensions of the graph, label, line, etc.
int top = GRAPH_MARGIN_SIZE;
int bottom = this.getHeight() - GRAPH_MARGIN_SIZE;
int yRange = bottom - top;
double interval = this.getWidth() / NDECADES;
// Loop and get the rank for every decade in entry.getRank,
// and display them proportionately on the graph.
// Also, draw lines to connect these points that stand for
// the ranks.
// Here let i starts at 1.
for (int i = 1; i < NDECADES; i++) {
String nameNRank = ""; // the string for the i'th rank.
String _nameNRank = "";// the string for the (i-1)'th rank.
// The rank at i'th decade.
// If it's 0, meaning it's not ranking in the first 1000,
// the rank should go to the bottom of the graph
// instead of to the top.
// The label should also show asterisk instead of the number
// of the rank.
int value = entry.getRank(i);
if (value == 0) {
value = MAX_RANK;
nameNRank = entry.getName() + " *";
} else {
nameNRank = entry.getName() + " " + Integer.toString(value);
}
// Similar for the rank at (i-1)'th decade.
int _value = entry.getRank(i - 1);
if (_value == 0) {
_value = MAX_RANK;
_nameNRank = entry.getName() + " *";
} else {
_nameNRank = entry.getName() + " " + Integer.toString(_value);
}
// Once the values of the two decades are determined,
// mark them as points on the graph
// and connect them with lines.
double xi = interval * i;
double yi = top + yRange * (value * 1.00 / MAX_RANK);
double _xi = interval * (i - 1);
double _yi = top + yRange * (_value * 1.00 / MAX_RANK);
// For each rank looped, make a line between it
// and the previous decade.
GLine graphLine = new GLine(_xi, _yi, xi, yi);
// Also make labels to show on each decade point.
GLabel nameNRankLabel = new GLabel(nameNRank);
GLabel _nameNRankLabel = new GLabel(_nameNRank);
// Define a color loop that helps change colors
// of the consecutive entries.
Color c = null;
switch (entryListIndex % 4) {
case 0:
c = Color.BLACK;
break;
case 1:
c = Color.RED;
break;
case 2:
c = Color.BLUE;
break;
case 3:
c = Color.MAGENTA;
break;
default:
c = Color.BLACK;
break;
}
// Set both the label and the lines into that one
// same color.
graphLine.setColor(c);
nameNRankLabel.setColor(c);
this.add(graphLine);
// For the labels, when i = 1, it also needs to
// display the label of the (i-1)'th rank.
// IDT is the indent (defined as constant) to make
// the interface a better looking one.
if (i == 1) {
_nameNRankLabel.setColor(nameNRankLabel.getColor());
this.add(_nameNRankLabel, _xi + IDT, _yi - IDT);
}
this.add(nameNRankLabel, xi + IDT, yi - IDT);
}
}
public void noRecord() {
GLabel noRecord = new GLabel("Record not found. Please try a new search.");
noRecord.setColor(Color.RED);
this.add(noRecord, (this.getWidth() - noRecord.getWidth()) * 0.5,
(this.getHeight() + noRecord.getAscent()) * 0.5);
}
public void recordExists() {
GLabel recordExists = new GLabel("Record already graphed. Please try a new search.");
recordExists.setColor(Color.RED);
this.add(recordExists, (this.getWidth() - recordExists.getWidth()) * 0.5,
this.getHeight() * 0.5 + recordExists.getAscent() * 2);
}
/*
* Method update makes sure that: (1) new entries will be added to the
* screen while the old ones remain. (2) when the size of the window
* changes, all the display changes.
*/
public void update() {
// On every update, clear canvas and re-put the background grids.
this.removeAll();
this.drawBackground();
// Re-add all the graphs in the arrayList entryList.
for (int i = 0; i < entryList.size(); i++) {
drawGraph(i);
}
}
/*
* Method drawBackground puts up the grids and year labels.
*/
private void drawBackground() {
double interval = this.getWidth() / NDECADES;
for (int i = 0; i < NDECADES - 1; i++) {
GLine line = new GLine(interval * (i + 1), 0, interval * (i + 1), this.getHeight());
this.add(line);
}
for (int i = 0; i < NDECADES; i++) {
int decade = START_DECADE + 10 * i;
String decadeStr = Integer.toString(decade);
GLabel decadeLabel = new GLabel(decadeStr);
add(decadeLabel, IDT + interval * i, this.getHeight() - IDT);
}
GLine upperMargin = new GLine(0, GRAPH_MARGIN_SIZE, this.getWidth(), GRAPH_MARGIN_SIZE);
GLine bottomMargin = new GLine(0, this.getHeight() - GRAPH_MARGIN_SIZE, this.getWidth(),
this.getHeight() - GRAPH_MARGIN_SIZE);
this.add(upperMargin);
this.add(bottomMargin);
}
/* Implementation of the ComponentListener interface */
public void componentHidden(ComponentEvent e) {
}
public void componentMoved(ComponentEvent e) {
}
public void componentResized(ComponentEvent e) {
update();
}
public void componentShown(ComponentEvent e) {
}
}