9 package micropolisj.gui;
12 import java.awt.event.*;
13 import java.awt.geom.Path2D;
18 import micropolisj.engine.*;
19 import static micropolisj.gui.ColorParser.parseColor;
26 JToggleButton tenYearsBtn;
27 JToggleButton onetwentyYearsBtn;
30 static enum TimePeriod
45 EnumMap<GraphData,JToggleButton> dataBtns =
new EnumMap<GraphData,JToggleButton>(GraphData.class);
47 static ResourceBundle strings =
MainWindow.strings;
48 static final int LEFT_MARGIN = 4;
49 static final int RIGHT_MARGIN = 4;
50 static final int TOP_MARGIN = 2;
51 static final int BOTTOM_MARGIN = 2;
52 static final int LEGEND_PADDING = 6;
56 super(
new BorderLayout());
58 assert engine != null;
62 JButton dismissBtn =
new JButton(strings.getString(
"dismiss_graph"));
63 dismissBtn.addActionListener(
new ActionListener() {
64 public void actionPerformed(ActionEvent evt) {
67 add(dismissBtn, BorderLayout.SOUTH);
69 JPanel b1 =
new JPanel(
new BorderLayout());
70 add(b1, BorderLayout.CENTER);
72 JPanel toolsPane =
new JPanel(
new GridBagLayout());
73 b1.add(toolsPane, BorderLayout.WEST);
75 GridBagConstraints c =
new GridBagConstraints();
76 c.gridx = c.gridy = 0;
78 c.fill = GridBagConstraints.BOTH;
79 c.insets =
new Insets(1,1,1,1);
80 tenYearsBtn =
new JToggleButton(strings.getString(
"ten_years"));
81 tenYearsBtn.setMargin(
new Insets(0,0,0,0));
82 tenYearsBtn.addActionListener(
new ActionListener() {
83 public void actionPerformed(ActionEvent evt) {
84 setTimePeriod(TimePeriod.TEN_YEARS);
86 toolsPane.add(tenYearsBtn, c);
89 onetwentyYearsBtn =
new JToggleButton(strings.getString(
"onetwenty_years"));
90 onetwentyYearsBtn.setMargin(
new Insets(0,0,0,0));
91 onetwentyYearsBtn.addActionListener(
new ActionListener() {
92 public void actionPerformed(ActionEvent evt) {
93 setTimePeriod(TimePeriod.ONETWENTY_YEARS);
95 toolsPane.add(onetwentyYearsBtn, c);
100 c.anchor = GridBagConstraints.NORTH;
118 toolsPane.add(
makeDataBtn(GraphData.POLLUTION), c);
120 graphArea =
new GraphArea();
121 b1.add(graphArea, BorderLayout.CENTER);
123 setTimePeriod(TimePeriod.TEN_YEARS);
124 dataBtns.get(GraphData.MONEY).setSelected(
true);
125 dataBtns.get(GraphData.POLLUTION).setSelected(
true);
130 if (engine != null) {
134 if (engine != null) {
161 String icon1name = strings.getString(
"graph_button."+graph.name());
162 String icon2name = strings.getString(
"graph_button."+graph.name()+
".selected");
164 ImageIcon icon1 =
new ImageIcon(getClass().getResource(
"/"+icon1name));
165 ImageIcon icon2 =
new ImageIcon(getClass().getResource(
"/"+icon2name));
167 JToggleButton btn =
new JToggleButton();
169 btn.setSelectedIcon(icon2);
171 btn.setBorderPainted(
false);
172 btn.setFocusPainted(
false);
173 btn.setContentAreaFilled(
false);
174 btn.setMargin(
new Insets(0,0,0,0));
176 btn.addActionListener(
new ActionListener() {
177 public void actionPerformed(ActionEvent evt) {
181 dataBtns.put(graph, btn);
188 for (GraphData g : GraphData.values()) {
189 for (
int pos = 0; pos < 240; pos++) {
190 max = Math.max(max, getHistoryValue(g, pos));
196 int getHistoryValue(GraphData graph,
int pos)
198 assert pos >= 0 && pos < 240;
200 case RESPOP:
return engine.
history.res[pos];
201 case COMPOP:
return engine.
history.com[pos];
202 case INDPOP:
return engine.
history.ind[pos];
203 case MONEY:
return engine.
history.money[pos];
204 case CRIME:
return engine.
history.crime[pos];
205 case POLLUTION:
return engine.
history.pollution[pos];
206 default:
throw new Error(
"unexpected");
210 void setTimePeriod(TimePeriod period)
212 tenYearsBtn.setSelected(period == TimePeriod.TEN_YEARS);
213 onetwentyYearsBtn.setSelected(period == TimePeriod.ONETWENTY_YEARS);
217 class GraphArea
extends JComponent
221 setBorder(BorderFactory.createLoweredBevelBorder());
225 public void paintComponent(Graphics gr1)
227 Graphics2D gr = (Graphics2D)gr1;
228 FontMetrics fm = gr.getFontMetrics();
230 gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
231 gr.setColor(Color.WHITE);
232 gr.fill(gr.getClipBounds());
235 int maxLabelWidth = 0;
236 for (GraphData gd : GraphData.values())
238 String labelStr = strings.getString(
"graph_label."+gd.name());
239 int adv = fm.stringWidth(labelStr);
240 if (adv > maxLabelWidth) {
245 int leftEdge = getInsets().left + LEFT_MARGIN;
246 int topEdge = getInsets().top + TOP_MARGIN + fm.getHeight()*2;
247 int bottomEdge = getHeight() - getInsets().bottom - getInsets().top - BOTTOM_MARGIN;
248 int rightEdge = getWidth() - getInsets().right - getInsets().left - RIGHT_MARGIN - maxLabelWidth - LEGEND_PADDING;
251 gr.setColor(Color.BLACK);
252 gr.drawLine(leftEdge,topEdge,rightEdge,topEdge);
253 gr.drawLine(leftEdge,bottomEdge,rightEdge,bottomEdge);
256 boolean isOneTwenty = onetwentyYearsBtn.isSelected();
257 int unitPeriod = isOneTwenty ? 12*Micropolis.CENSUSRATE : Micropolis.CENSUSRATE;
258 int hashPeriod = isOneTwenty ? 10*unitPeriod : 12*unitPeriod;
259 int startTime = ((engine.history.cityTime / unitPeriod) - 119) * unitPeriod;
261 double x_interval = (rightEdge - leftEdge) / 120.0;
262 for (
int i = 0; i < 120; i++) {
263 int t = startTime + i * unitPeriod;
264 if (t % hashPeriod == 0) {
266 int year = 1900+(t/(12*Micropolis.CENSUSRATE));
267 int numHashes = t/hashPeriod;
268 int x = (int)Math.round(leftEdge+i*x_interval);
269 int y = getInsets().top + TOP_MARGIN +
270 (numHashes % 2 == 0 ? fm.getHeight() : 0) +
272 gr.drawString(Integer.toString(year), x, y);
273 gr.drawLine(x,topEdge,x,bottomEdge);
277 int H = isOneTwenty ? 239 : 119;
278 final HashMap<GraphData, Path2D.Double> paths =
new HashMap<GraphData,Path2D.Double>();
279 double scale = Math.max(256.0, getHistoryMax());
280 for (GraphData gd : GraphData.values())
282 if (dataBtns.get(gd).isSelected()) {
284 Path2D.Double path =
new Path2D.Double();
285 for (
int i = 0; i < 120; i++) {
286 double xp = leftEdge + i * x_interval;
287 double yp = bottomEdge - getHistoryValue(gd,H-i) * (bottomEdge-topEdge) / scale;
298 GraphData [] myGraphs = paths.keySet().toArray(
new GraphData[0]);
299 Arrays.sort(myGraphs,
new Comparator<GraphData>() {
300 public int compare(GraphData a, GraphData b) {
301 double y0 = paths.get(a).getCurrentPoint().getY();
302 double y1 = paths.get(b).getCurrentPoint().getY();
303 return -Double.compare(y0,y1);
306 int lbottom = bottomEdge;
307 for (GraphData gd : myGraphs)
309 String labelStr = strings.getString(
"graph_label."+gd.name());
310 String colStr = strings.getString(
"graph_color."+gd.name());
311 Color col = parseColor(colStr);
312 Path2D.Double path = paths.get(gd);
315 gr.setStroke(
new BasicStroke(2));
318 int x = rightEdge + LEGEND_PADDING;
319 int y = (int)Math.round(path.getCurrentPoint().getY()+fm.getAscent()/2);
320 y = Math.min(lbottom, y);
321 lbottom = y - fm.getAscent();
324 gr.drawString(labelStr, x-1, y);
325 gr.drawString(labelStr, x, y-1);
327 gr.setColor(Color.BLACK);
328 gr.drawString(labelStr, x, y);