1 package org.opentrafficsim.swing.graphs;
2
3 import java.awt.BorderLayout;
4 import java.awt.Dimension;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.awt.event.WindowAdapter;
8 import java.awt.event.WindowEvent;
9 import java.io.BufferedOutputStream;
10 import java.io.File;
11 import java.io.FileOutputStream;
12 import java.io.IOException;
13 import java.io.OutputStream;
14 import java.util.Optional;
15
16 import javax.swing.JFileChooser;
17 import javax.swing.JFrame;
18 import javax.swing.JLabel;
19 import javax.swing.JMenuItem;
20 import javax.swing.JPopupMenu;
21 import javax.swing.JTextField;
22 import javax.swing.SwingConstants;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24
25 import org.jfree.chart.ChartMouseListener;
26 import org.jfree.chart.ChartPanel;
27 import org.jfree.chart.JFreeChart;
28 import org.jfree.chart.plot.XYPlot;
29 import org.opentrafficsim.animation.graphs.AbstractPlot;
30 import org.opentrafficsim.animation.graphs.JFileChooserWithSettings;
31 import org.opentrafficsim.animation.graphs.PointerHandler;
32
33
34
35
36
37
38
39
40
41
42
43
44 public class SwingPlot extends JFrame
45 {
46
47 private static final long serialVersionUID = 20190823L;
48
49
50 @SuppressWarnings("checkstyle:visibilitymodifier")
51 protected final AbstractPlot<?> plot;
52
53
54 private JLabel statusLabel;
55
56
57 private JMenuItem detach;
58
59
60 private ChartPanel chartPanel;
61
62
63
64
65
66 public SwingPlot(final AbstractPlot<?> plot)
67 {
68 this.plot = plot;
69
70 this.statusLabel = new JLabel(" ", SwingConstants.CENTER);
71 add(this.statusLabel, BorderLayout.SOUTH);
72 setChart(plot.getChart());
73 }
74
75
76
77
78
79 protected void setChart(final JFreeChart chart)
80 {
81
82
83 this.chartPanel = new ChartPanel(chart)
84 {
85
86 private static final long serialVersionUID = 20181006L;
87
88 @Override
89 public void restoreAutoDomainBounds()
90 {
91 super.restoreAutoDomainBounds();
92 if (chart.getPlot() instanceof XYPlot)
93 {
94 SwingPlot.this.plot.setAutoBoundDomain(chart.getXYPlot());
95 }
96 }
97
98 @Override
99 public void restoreAutoRangeBounds()
100 {
101 super.restoreAutoRangeBounds();
102 if (chart.getPlot() instanceof XYPlot)
103 {
104 SwingPlot.this.plot.setAutoBoundRange(chart.getXYPlot());
105 }
106 }
107
108
109 @Override
110 public void doSaveAs() throws IOException
111 {
112
113
114
115 JLabel fontSizeLabel = new JLabel("font size");
116 JTextField fontSize = new JTextField("32");
117 fontSize.setToolTipText("Font size of title (other fonts are scaled)");
118 fontSize.setPreferredSize(new Dimension(40, 20));
119 JTextField width = new JTextField("960");
120 width.setToolTipText("Width [pixels]");
121 width.setPreferredSize(new Dimension(40, 20));
122 JLabel x = new JLabel("x");
123 JTextField height = new JTextField("540");
124 height.setToolTipText("Height [pixels]");
125 height.setPreferredSize(new Dimension(40, 20));
126
127
128 JFileChooser fileChooser = new JFileChooserWithSettings(fontSizeLabel, fontSize, width, x, height);
129 fileChooser.setCurrentDirectory(getDefaultDirectoryForSaveAs());
130 FileNameExtensionFilter filter =
131 new FileNameExtensionFilter(localizationResources.getString("PNG_Image_Files"), "png");
132 fileChooser.addChoosableFileFilter(filter);
133 fileChooser.setFileFilter(filter);
134
135 int option = fileChooser.showSaveDialog(this);
136 if (option == JFileChooser.APPROVE_OPTION)
137 {
138 String filename = fileChooser.getSelectedFile().getPath();
139 if (isEnforceFileExtensions())
140 {
141 if (!filename.endsWith(".png"))
142 {
143 filename = filename + ".png";
144 }
145 }
146
147
148 double fs;
149 try
150 {
151 fs = Double.parseDouble(fontSize.getText());
152 }
153 catch (NumberFormatException exception)
154 {
155 fs = 16.0;
156 }
157 int w;
158 try
159 {
160 w = Integer.parseInt(width.getText());
161 }
162 catch (NumberFormatException exception)
163 {
164 w = getWidth();
165 }
166 int h;
167 try
168 {
169 h = Integer.parseInt(height.getText());
170 }
171 catch (NumberFormatException exception)
172 {
173 h = getHeight();
174 }
175 OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(filename)));
176 out.write(SwingPlot.this.plot.encodeAsPng(w, h, fs));
177 out.close();
178 }
179 }
180 };
181 Optional<ChartMouseListener> chartListener = getChartMouseListener();
182 if (chartListener.isPresent())
183 {
184 this.chartPanel.addChartMouseListener(chartListener.get());
185 }
186
187
188 final PointerHandler ph = new PointerHandler()
189 {
190 @Override
191 public void updateHint(final double domainValue, final double rangeValue)
192 {
193 if (Double.isNaN(domainValue))
194 {
195 setStatusLabel(" ");
196 }
197 else
198 {
199 setStatusLabel(SwingPlot.this.plot.getStatusLabel(domainValue, rangeValue));
200 }
201 }
202 };
203 this.chartPanel.addMouseMotionListener(ph);
204 this.chartPanel.addMouseListener(ph);
205 add(this.chartPanel, BorderLayout.CENTER);
206 this.chartPanel.setMouseWheelEnabled(true);
207
208
209 JPopupMenu popupMenu = this.chartPanel.getPopupMenu();
210 popupMenu.add(new JPopupMenu.Separator());
211 this.detach = new JMenuItem("Show in detached window");
212 this.detach.addActionListener(new ActionListener()
213 {
214 @Override
215 public void actionPerformed(final ActionEvent e)
216 {
217 SwingPlot.this.detach.setEnabled(false);
218 JFrame window = new JFrame(getPlot().getCaption());
219 window.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
220 window.add(SwingPlot.this.chartPanel, BorderLayout.CENTER);
221 window.add(SwingPlot.this.statusLabel, BorderLayout.SOUTH);
222 window.addWindowListener(new WindowAdapter()
223 {
224 @Override
225 public void windowClosing(final WindowEvent e)
226 {
227 add(SwingPlot.this.chartPanel, BorderLayout.CENTER);
228 add(SwingPlot.this.statusLabel, BorderLayout.SOUTH);
229 SwingPlot.this.detach.setEnabled(true);
230 SwingPlot.this.getContentPane().validate();
231 SwingPlot.this.getContentPane().repaint();
232 }
233 });
234 window.pack();
235 window.setVisible(true);
236 SwingPlot.this.getContentPane().repaint();
237 }
238 });
239 popupMenu.add(this.detach);
240 addPopUpMenuItems(popupMenu);
241 }
242
243
244
245
246
247 protected void setStatusLabel(final String label)
248 {
249 if (this.statusLabel != null)
250 {
251 this.statusLabel.setText(label);
252 }
253 }
254
255
256
257
258
259 protected void addPopUpMenuItems(final JPopupMenu popupMenu)
260 {
261
262 }
263
264
265
266
267
268 protected Optional<ChartMouseListener> getChartMouseListener()
269 {
270 return Optional.empty();
271 }
272
273
274
275
276
277 public AbstractPlot<?> getPlot()
278 {
279 return this.plot;
280 }
281
282
283
284
285
286 public ChartPanel getChartPanel()
287 {
288 return this.chartPanel;
289 }
290
291 }