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 package org.jrobin.inspector;
26
27 import org.jrobin.core.*;
28 import org.jrobin.graph.RrdGraphDef;
29 import org.jrobin.graph.RrdGraph;
30 import org.jrobin.graph.RrdGraphInfo;
31 import org.jrobin.data.LinearInterpolator;
32
33 import javax.swing.*;
34 import javax.swing.filechooser.FileFilter;
35 import java.awt.*;
36 import java.awt.event.*;
37 import java.io.IOException;
38 import java.io.File;
39 import java.io.RandomAccessFile;
40 import java.util.Date;
41
42 class GraphFrame extends JFrame {
43 private static final long serialVersionUID = 1L;
44 private static final Color COLOR = Color.RED;
45 private static final int WIDTH = 400, HEIGHT = 240;
46 private int deltaWidth = 0, deltaHeight = 0;
47
48 private Color color = COLOR;
49 private GraphPanel graphPanel = new GraphPanel();
50 private JComboBox graphCombo = new JComboBox();
51 private RrdGraph rrdGraph;
52
53 private String sourcePath;
54 private int dsIndex, arcIndex;
55
56 GraphFrame(String sourcePath, int dsIndex, int arcIndex) {
57 this.sourcePath = sourcePath;
58 this.dsIndex = dsIndex;
59 this.arcIndex = arcIndex;
60 fillGraphCombo();
61 constructUI();
62 pack();
63
64 Util.placeWindow(this);
65 setVisible(true);
66 }
67
68 private void createRrdGraph() {
69
70 try {
71 RrdDb rrdDb = new RrdDb(sourcePath, true);
72 RrdDef rrdDef;
73 long[] timestamps;
74 double[] values;
75 String dsName;
76 long t1, t2;
77 try {
78 Datasource ds = rrdDb.getDatasource(dsIndex);
79 Archive arc = rrdDb.getArchive(arcIndex);
80 Robin robin = arc.getRobin(dsIndex);
81 dsName = ds.getDsName();
82 t1 = arc.getStartTime();
83 t2 = arc.getEndTime();
84 long step = arc.getArcStep();
85 int count = robin.getSize();
86 timestamps = new long[count];
87 for (int i = 0; i < count; i++) {
88 timestamps[i] = t1 + i * step;
89 }
90 values = robin.getValues();
91 rrdDef = rrdDb.getRrdDef();
92 }
93 finally {
94 rrdDb.close();
95 }
96 RrdGraphDef rrdGraphDef = new RrdGraphDef();
97 rrdGraphDef.setTimeSpan(t1, t2);
98 rrdGraphDef.setImageFormat("png");
99 rrdGraphDef.setTitle(rrdDef.getDsDefs()[dsIndex].dump() + " " +
100 rrdDef.getArcDefs()[arcIndex].dump());
101 LinearInterpolator linearInterpolator = new LinearInterpolator(timestamps, values);
102 linearInterpolator.setInterpolationMethod(LinearInterpolator.INTERPOLATE_RIGHT);
103 rrdGraphDef.datasource(dsName, linearInterpolator);
104 rrdGraphDef.area(dsName, color, dsName + "\\r");
105 rrdGraphDef.comment("START: " + new Date(t1 * 1000L) + "\\r");
106 rrdGraphDef.comment("END: " + new Date(t2 * 1000L) + "\\r");
107 int width = graphPanel.getWidth(), height = graphPanel.getHeight();
108 rrdGraphDef.setWidth(width + deltaWidth);
109 rrdGraphDef.setHeight(height + deltaHeight);
110 rrdGraph = new RrdGraph(rrdGraphDef);
111 if (deltaWidth == 0 && deltaHeight == 0) {
112 RrdGraphInfo info = rrdGraph.getRrdGraphInfo();
113 deltaWidth = graphPanel.getWidth() - info.getWidth();
114 deltaHeight = graphPanel.getHeight() - info.getHeight();
115 if (deltaWidth != 0 && deltaHeight != 0) {
116 createRrdGraph();
117 }
118 }
119 }
120 catch (IOException e) {
121 Util.error(this, e);
122 }
123 catch (RrdException e) {
124 Util.error(this, e);
125 }
126 }
127
128 private void fillGraphCombo() {
129 try {
130 RrdDb rrdDb = new RrdDb(sourcePath, true);
131 try {
132 RrdDef rrdDef = rrdDb.getRrdDef();
133 final DsDef[] dsDefs = rrdDef.getDsDefs();
134 final ArcDef[] arcDefs = rrdDef.getArcDefs();
135 GraphComboItem[] items = new GraphComboItem[rrdDef.getDsCount() * rrdDef.getArcCount()];
136 int selectedItem = -1;
137 for (int i = 0, k = 0; i < rrdDef.getDsCount(); i++) {
138 for (int j = 0; j < rrdDef.getArcCount(); k++, j++) {
139 String description = dsDefs[i].dump() + " " + arcDefs[j].dump();
140 items[k] = new GraphComboItem(description, i, j);
141 if (i == dsIndex && j == arcIndex) {
142 selectedItem = k;
143 }
144 }
145 }
146 graphCombo.setModel(new DefaultComboBoxModel(items));
147 graphCombo.setSelectedIndex(selectedItem);
148 }
149 finally {
150 rrdDb.close();
151 }
152 }
153 catch (IOException e) {
154 Util.error(this, e);
155 }
156 catch (RrdException e) {
157 Util.error(this, e);
158 }
159 }
160
161 private void constructUI() {
162 setTitle(new File(sourcePath).getName());
163 JPanel content = (JPanel) getContentPane();
164 content.setLayout(new BorderLayout(0, 0));
165 content.add(graphCombo, BorderLayout.NORTH);
166 graphPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
167 content.add(graphPanel, BorderLayout.CENTER);
168 JPanel southPanel = new JPanel();
169 southPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
170 JButton colorButton = new JButton("Change graph color");
171 southPanel.add(colorButton);
172 colorButton.addActionListener(new ActionListener() {
173 public void actionPerformed(ActionEvent e) {
174 changeColor();
175 }
176 });
177 JButton saveButton = new JButton("Save graph");
178 saveButton.addActionListener(new ActionListener() {
179 public void actionPerformed(ActionEvent e) {
180 saveGraph();
181 }
182 });
183 southPanel.add(Box.createHorizontalStrut(3));
184 southPanel.add(saveButton);
185 content.add(southPanel, BorderLayout.SOUTH);
186
187 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
188 addWindowListener(new WindowAdapter() {
189 public void windowClosing(WindowEvent e) {
190 closeWindow();
191 }
192 });
193 addComponentListener(new ComponentAdapter() {
194 public void componentResized(ComponentEvent e) {
195 createRrdGraph();
196 graphPanel.repaint();
197 }
198 });
199 graphCombo.addItemListener(new ItemListener() {
200 public void itemStateChanged(ItemEvent e) {
201 if (e.getStateChange() == ItemEvent.SELECTED) {
202 GraphComboItem item = (GraphComboItem) e.getItem();
203 dsIndex = item.getDsIndex();
204 arcIndex = item.getArcIndex();
205 createRrdGraph();
206 graphPanel.repaint();
207 }
208 }
209 });
210 }
211
212 private void closeWindow() {
213 Util.dismissWindow(this);
214 }
215
216 private void changeColor() {
217 final JColorChooser picker = new JColorChooser(color);
218 ActionListener okListener = new ActionListener() {
219 public void actionPerformed(ActionEvent e) {
220 color = picker.getColor();
221 createRrdGraph();
222 repaint();
223 }
224 };
225 JColorChooser.createDialog(this, "Select color", true, picker, okListener, null).setVisible(true);
226 }
227
228 private void saveGraph() {
229 JFileChooser chooser = new JFileChooser();
230 FileFilter filter = new FileFilter() {
231 public boolean accept(File f) {
232 return f.isDirectory() || f.getAbsolutePath().toLowerCase().endsWith(".png");
233 }
234
235 public String getDescription() {
236 return "PNG images";
237 }
238 };
239 chooser.setFileFilter(filter);
240 int returnVal = chooser.showSaveDialog(this);
241 if (returnVal == JFileChooser.APPROVE_OPTION) {
242 try {
243 File selectedFile = chooser.getSelectedFile();
244 String path = selectedFile.getAbsolutePath();
245 if (!path.toLowerCase().endsWith(".png")) {
246 path += ".png";
247 selectedFile = new File(path);
248 }
249 if (selectedFile.exists()) {
250
251 String message = "File [" + selectedFile.getName() +
252 "] already exists. Do you want to overwrite it?";
253 int answer = JOptionPane.showConfirmDialog(this,
254 message, "File exists", JOptionPane.YES_NO_OPTION);
255 if (answer == JOptionPane.NO_OPTION) {
256 return;
257 }
258 }
259 String absolutePath = selectedFile.getAbsolutePath();
260 byte[] data = rrdGraph.getRrdGraphInfo().getBytes();
261 RandomAccessFile f = new RandomAccessFile(absolutePath, "rw");
262 try {
263 f.write(data);
264 }
265 finally {
266 f.close();
267 }
268 }
269 catch (IOException e) {
270 Util.error(this, "Could not save graph to file:\n" + e);
271 }
272 }
273 }
274
275 class GraphPanel extends JPanel {
276 private static final long serialVersionUID = 1L;
277 public void paintComponent(Graphics g) {
278 rrdGraph.render(g);
279 }
280 }
281
282 class GraphComboItem {
283 private String description;
284 private int dsIndex, arcIndex;
285
286 GraphComboItem(String description, int dsIndex, int arcIndex) {
287 this.description = description;
288 this.dsIndex = dsIndex;
289 this.arcIndex = arcIndex;
290 }
291
292 public String toString() {
293 return description;
294 }
295
296 int getDsIndex() {
297 return dsIndex;
298 }
299
300 int getArcIndex() {
301 return arcIndex;
302 }
303 }
304 }