001 /** 002 ############################################################################## 003 ## ## 004 ## EnvInfo ## 005 ## ## 006 ## Copyright (C) 2009 Frederic Roudaut <frederic.roudaut@free.fr> ## 007 ## ## 008 ## This class is an adaption of the one done by Nicolas Richasse for his ## 009 ## Java Iperf frontend. ## 010 ## ## 011 ## ## 012 ## This program is free software: you can redistribute it and/or modify ## 013 ## it under the terms of the GNU General Public License as published by ## 014 ## the Free Software Foundation, either version 3 of the License, or ## 015 ## (at your option) any later version. ## 016 ## ## 017 ## This program is distributed in the hope that it will be useful, ## 018 ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## 019 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## 020 ## GNU General Public License for more details. ## 021 ## ## 022 ## You should have received a copy of the GNU General Public License ## 023 ## along with this program. If not, see <http://www.gnu.org/licenses/>. ## 024 ## ## 025 ## ## 026 ############################################################################## 027 **/ 028 029 package com.envInfo; 030 031 import java.awt.BorderLayout; 032 import java.awt.Color; 033 import java.awt.GridLayout; 034 import java.text.SimpleDateFormat; 035 import java.util.Date; 036 import java.util.HashMap; 037 038 import javax.swing.JLabel; 039 import javax.swing.JPanel; 040 041 import org.jfree.chart.ChartPanel; 042 import org.jfree.chart.JFreeChart; 043 import org.jfree.chart.axis.AxisLocation; 044 import org.jfree.chart.axis.NumberAxis; 045 import org.jfree.chart.axis.ValueAxis; 046 import org.jfree.chart.plot.CombinedDomainXYPlot; 047 import org.jfree.chart.plot.XYPlot; 048 import org.jfree.chart.renderer.xy.XYItemRenderer; 049 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; 050 import org.jfree.data.xy.XYSeries; 051 import org.jfree.data.xy.XYSeriesCollection; 052 053 054 /** 055 * Class used to draw the JVM Memory status charts. 056 * <br/><br/> 057 * This class is an adaption of the one done by Nicolas Richasse for his 058 * Java Iperf frontend. 059 * 060 **/ 061 public class MemoryChartPanel extends AbstractChartPanel 062 implements Runnable 063 { 064 065 private static final long serialVersionUID = 1L; 066 067 /** 068 * Class representing a single series of Memory data. 069 * 070 **/ 071 private class SeriesData 072 { 073 public String seriesId; 074 public String memoryLegend; 075 public JLabel seriesLabel; 076 public XYSeries memorySeries; 077 public Color seriesColor; 078 public String printfMemoryValueExpression; 079 080 /** 081 * Constructor. 082 * @param seriesId ID. 083 * @param memoryLegend Memory Legend. 084 * @param seriesColor Color for the chart. 085 * @param printfMemoryValueExpression Content to print under the Chart. 086 * 087 **/ 088 public SeriesData (String seriesId, String memoryLegend, Color seriesColor, 089 String printfMemoryValueExpression) 090 { 091 this.seriesId = seriesId; 092 this.memoryLegend = memoryLegend; 093 this.memorySeries = new XYSeries(memoryLegend); 094 this.seriesLabel = new JLabel(memoryLegend); 095 this.seriesColor = seriesColor; 096 this.printfMemoryValueExpression = printfMemoryValueExpression; 097 seriesLabel.setForeground(seriesColor); 098 } 099 } 100 101 private int proportion; 102 private CombinedDomainXYPlot graphSet; 103 private XYItemRenderer memoryRenderer; 104 private XYSeriesCollection memoryCollection; 105 private JPanel panelTextStats = new JPanel(new GridLayout(0, 4)); 106 private JLabel labelDate = new JLabel(" "); 107 private double delayInSeconds; 108 private SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss"); 109 private HashMap<String, SeriesData> seriesData = new HashMap<String, SeriesData>(); 110 private Thread timeThread = null; 111 private Color backgroundColor, foregroundColor, gridColor; 112 private String memoryUnit; 113 private double timeWindow; 114 115 /** 116 * Constructor for a set of Memory Charts (ie a set of memory series). 117 * @param title Title of the Memory Charts set. 118 * @param memoryUnit Memory Unit. 119 * @param timeAxisLabel Time Axis Label (X axis). 120 * @param memoryValueAxisLabel Memory Value Axis Label (Y Axis). 121 * @param delayInSeconds Delay between the date printing above the charts set. 122 * @param timeWindow Time Windows for the charts. 123 * @param backgroundColor BackgroundColor. 124 * @param foregroundColor ForegroundColor. 125 * @param gridColor GridColor. 126 * 127 **/ 128 public MemoryChartPanel(String title, String memoryUnit, String timeAxisLabel, 129 String memoryValueAxisLabel, double delayInSeconds, double timeWindow, 130 Color backgroundColor, Color foregroundColor, Color gridColor) 131 { 132 this.delayInSeconds = delayInSeconds; 133 this.proportion = 1; 134 this.backgroundColor = backgroundColor; 135 this.foregroundColor = foregroundColor; 136 this.gridColor = gridColor; 137 138 reconfigure(title, memoryUnit, timeAxisLabel, memoryValueAxisLabel, timeWindow); 139 } 140 141 /** 142 * 143 * Start a Time Thread. 144 * 145 */ 146 public void start() 147 { 148 if (timeThread == null) 149 { 150 this.timeThread = new Thread(this); 151 timeThread.start(); 152 } 153 } 154 155 /** 156 * 157 * Check if a Memory Data Series Exists. 158 * @param seriesId A serie ID. 159 * @return true if the serie exists, false otherwise. 160 * 161 */ 162 private boolean seriesExists(String seriesId) 163 { 164 if (seriesData.keySet().contains(seriesId)) 165 { 166 return true; 167 } 168 else 169 { 170 return false; 171 } 172 } 173 174 /** 175 * 176 * Add a Memory Data Series. 177 * @param seriesId A serie ID. 178 * @param seriesLegend the Serie Legend 179 * @param seriesColor a color for the associated chart. 180 * 181 */ 182 public void maybeAddNewSeries(String seriesId, String seriesLegend, Color seriesColor) 183 { 184 maybeAddNewSeries(seriesId, seriesLegend, seriesColor, "%4.2f"); 185 } 186 187 /** 188 * 189 * Add a Memory Data Series. 190 * @param seriesId A serie ID. 191 * @param seriesLegend the Serie Legend 192 * @param seriesColor a color for the associated chart. 193 * @param printfMemoryValueExpression Content to print under the Charts. 194 * 195 */ 196 public synchronized void maybeAddNewSeries(String seriesId, String seriesLegend, 197 Color seriesColor, String printfMemoryValueExpression) 198 { 199 if (!seriesExists(seriesId)) 200 { 201 SeriesData data = new SeriesData(seriesId, seriesLegend, seriesColor, printfMemoryValueExpression); 202 seriesData.put(seriesId, data); 203 204 memoryCollection.addSeries(data.memorySeries); 205 memoryRenderer.setSeriesPaint(memoryCollection.getSeriesCount()-1, data.seriesColor); 206 207 panelTextStats.add(data.seriesLabel); 208 } 209 } 210 211 /** 212 * 213 * Reconfigure a Memory Data Charts set. 214 * @param title Title of the Memory Charts set. 215 * @param memoryUnit Memory Unit. 216 * @param timeAxisLabel Time Axis Label. 217 * @param memoryValueAxisLabel Memory Value Axis Label. 218 * @param timeWindow Time windows for the charts. 219 * 220 */ 221 public void reconfigure(String title, String memoryUnit, String timeAxisLabel, String memoryValueAxisLabel, 222 double timeWindow) 223 { 224 this.memoryUnit = memoryUnit; 225 this.timeWindow = timeWindow; 226 227 // reset the content pane 228 this.removeAll(); 229 panelTextStats.removeAll(); 230 SeriesColorGenerator.reset(); 231 232 seriesData.clear(); 233 234 // creation of the chart group 235 graphSet = new CombinedDomainXYPlot(new NumberAxis(timeAxisLabel)); 236 // space between charts 237 graphSet.setGap(10.0); 238 // creation of the jFreeChart 239 jFreeChart = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, graphSet, false); 240 jFreeChart.setBackgroundPaint(backgroundColor); 241 if (title != null) 242 { 243 jFreeChart.setTitle(title); 244 jFreeChart.getTitle().setPaint(foregroundColor); 245 } 246 // creation of the chart panel 247 chartPanel = new ChartPanel(jFreeChart); 248 chartPanel.setBackground(backgroundColor); 249 // creation of the series set 250 memoryCollection = new XYSeriesCollection(); 251 // creation of the renderer 252 memoryRenderer = new XYLineAndShapeRenderer(); 253 // set the UI presentation 254 NumberAxis rangeAxis = new NumberAxis(memoryValueAxisLabel); 255 rangeAxis.setLabelPaint(foregroundColor); 256 257 // creation of the memory plot 258 XYPlot memoryPlot = new XYPlot(memoryCollection, null, rangeAxis, memoryRenderer); 259 memoryPlot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT); 260 memoryPlot.setDomainCrosshairVisible(false); 261 memoryPlot.setRangeCrosshairVisible(false); 262 memoryPlot.setBackgroundPaint(backgroundColor); 263 memoryPlot.setDomainGridlinePaint(gridColor); 264 memoryPlot.setRangeGridlinePaint(gridColor); 265 266 // add the plot 267 graphSet.add(memoryPlot, proportion); 268 269 // set up the domain axis 270 ValueAxis axis = memoryPlot.getDomainAxis(); 271 if (timeAxisLabel != null) 272 { 273 axis.setTickLabelPaint(foregroundColor); 274 axis.setLabel(timeAxisLabel); 275 axis.setLabelPaint(foregroundColor); 276 } 277 else 278 { 279 axis.setVisible(false); 280 } 281 axis.setAutoRange(true); 282 axis.setFixedAutoRange((int)Math.min(timeWindow, 60)); 283 284 // set up the range axis 285 axis = memoryPlot.getRangeAxis(); 286 axis.setTickLabelPaint(foregroundColor); 287 288 // set up the hour&date label presentation 289 labelDate.setHorizontalAlignment(JLabel.RIGHT); 290 labelDate.setForeground(foregroundColor); 291 292 panelTextStats.setBackground(backgroundColor); 293 294 this.add(labelDate, BorderLayout.NORTH); 295 this.add(chartPanel, BorderLayout.CENTER); 296 this.add(panelTextStats, BorderLayout.SOUTH); 297 298 this.setBackground(backgroundColor); 299 } 300 301 /** 302 * 303 * Add a new measurement to an existing memory data serie. 304 * @param seriesId the sery ID. 305 * @param measurement the measurement to add. 306 * 307 */ 308 public void addSeriesMemoryMeasurement(String seriesId, MemoryMeasurement measurement) 309 { 310 SeriesData data = seriesData.get(seriesId); 311 data.memorySeries.add(measurement.getEndTime(), measurement.getValue()); 312 data.seriesLabel.setText(String.format("<html><b>%s</b> " + data.printfMemoryValueExpression + "%s </html>", 313 data.memoryLegend, measurement.getValue(), 314 " " + measurement.getUnits() +" ")); 315 } 316 317 /** 318 * 319 * Start a Thread to update the date. 320 * 321 */ 322 public void run() 323 { 324 while (true) 325 { 326 try 327 { 328 Date d = new Date(); 329 labelDate.setText(sdf.format(d)); 330 Thread.sleep((int) (delayInSeconds * 1000)); 331 } 332 catch (Exception ex) 333 { 334 } 335 } 336 } 337 }