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.draw.graphs.AbstractPlot;
30 import org.opentrafficsim.draw.graphs.JFileChooserWithSettings;
31 import org.opentrafficsim.draw.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 @SuppressWarnings("synthetic-access")
215 @Override
216 public void actionPerformed(final ActionEvent e)
217 {
218 SwingPlot.this.detach.setEnabled(false);
219 JFrame window = new JFrame(getPlot().getCaption());
220 window.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
221 window.add(SwingPlot.this.chartPanel, BorderLayout.CENTER);
222 window.add(SwingPlot.this.statusLabel, BorderLayout.SOUTH);
223 window.addWindowListener(new WindowAdapter()
224 {
225 @Override
226 public void windowClosing(@SuppressWarnings("hiding") final WindowEvent e)
227 {
228 add(SwingPlot.this.chartPanel, BorderLayout.CENTER);
229 add(SwingPlot.this.statusLabel, BorderLayout.SOUTH);
230 SwingPlot.this.detach.setEnabled(true);
231 SwingPlot.this.getContentPane().validate();
232 SwingPlot.this.getContentPane().repaint();
233 }
234 });
235 window.pack();
236 window.setVisible(true);
237 SwingPlot.this.getContentPane().repaint();
238 }
239 });
240 popupMenu.add(this.detach);
241 addPopUpMenuItems(popupMenu);
242 }
243
244
245
246
247
248 protected final void setStatusLabel(final String label)
249 {
250 if (this.statusLabel != null)
251 {
252 this.statusLabel.setText(label);
253 }
254 }
255
256
257
258
259
260 protected void addPopUpMenuItems(final JPopupMenu popupMenu)
261 {
262
263 }
264
265
266
267
268
269 protected Optional<ChartMouseListener> getChartMouseListener()
270 {
271 return Optional.empty();
272 }
273
274
275
276
277
278 public AbstractPlot getPlot()
279 {
280 return this.plot;
281 }
282
283
284
285
286
287 public ChartPanel getChartPanel()
288 {
289 return this.chartPanel;
290 }
291
292 }