View Javadoc

1   /* ============================================================
2    * JRobin : Pure java implementation of RRDTool's functionality
3    * ============================================================
4    *
5    * Project Info:  http://www.jrobin.org
6    * Project Lead:  Sasa Markovic (saxon@jrobin.org);
7    *
8    * (C) Copyright 2003, by Sasa Markovic.
9    *
10   * Developers:    Sasa Markovic (saxon@jrobin.org)
11   *
12   *
13   * This library is free software; you can redistribute it and/or modify it under the terms
14   * of the GNU Lesser General Public License as published by the Free Software Foundation;
15   * either version 2.1 of the License, or (at your option) any later version.
16   *
17   * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18   * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19   * See the GNU Lesser General Public License for more details.
20   *
21   * You should have received a copy of the GNU Lesser General Public License along with this
22   * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23   * Boston, MA 02111-1307, USA.
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  		//createRrdGraph();
64  		Util.placeWindow(this);
65  		setVisible(true);
66  	}
67  
68  	private void createRrdGraph() {
69  		//System.out.println("Creating graph...");
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(); // recursion is divine!
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 		// EVENT HANDLERS
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 					// ask user to overwrite
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 }