1 16 17 package org.mc4j.console.swing.graph; 18 19 import org.jfree.chart.ChartPanel; 20 import org.jfree.chart.JFreeChart; 21 import org.jfree.chart.axis.DateAxis; 22 import org.jfree.chart.axis.LogarithmicAxis; 23 import org.jfree.chart.axis.NumberAxis; 24 import org.jfree.chart.plot.XYPlot; 25 import org.jfree.chart.renderer.xy.DefaultXYItemRenderer; 26 import org.jfree.chart.title.TextTitle; 27 import org.jfree.data.time.Millisecond; 28 import org.jfree.data.time.TimeSeries; 29 import org.jfree.data.time.TimeSeriesCollection; 30 import org.mc4j.console.dashboard.components.RefreshControlComponent; 31 import org.mc4j.console.swing.LogarithmicTimeJSlider; 32 import org.openide.windows.TopComponent; 33 34 import javax.swing.*; 35 import javax.swing.border.LineBorder ; 36 import java.awt.BorderLayout ; 37 import java.awt.Color ; 38 import java.awt.Dimension ; 39 import java.awt.FlowLayout ; 40 import java.awt.Font ; 41 import java.awt.event.ActionEvent ; 42 import java.awt.event.ActionListener ; 43 import java.awt.event.WindowAdapter ; 44 import java.awt.event.WindowEvent ; 45 import java.util.Calendar ; 46 import java.util.Date ; 47 import java.util.GregorianCalendar ; 48 import java.util.HashMap ; 49 import java.util.Map ; 50 import java.util.Timer ; 51 import java.util.TimerTask ; 52 import java.util.Set ; 53 54 63 public abstract class AbstractGraphPanel<T> extends TopComponent { 64 65 66 protected TimeSeriesCollection dataset = new TimeSeriesCollection(); 67 68 protected JFreeChart chart; 69 protected Timer dataGeneratorTimer; 70 protected TimerTask dataGeneratorTimerTask; 71 72 protected Map <T,TimeSeries> timeSeriesMap = new HashMap <T, TimeSeries>(); 73 protected XYPlot xyplot; 74 75 76 private JCheckBox controlsButton; 78 private JPanel controlsPanel; 79 80 private ButtonGroup buttonGroupScale; 81 private ButtonGroup buttonGroupTimeRange; 82 private JRadioButton jRadioButtonScaleLinear; 83 private JRadioButton jRadioButtonScaleLogarithmic; 84 private JRadioButton jRadioTimeHours; 85 private JRadioButton jRadioTimeMinutes; 86 private JRadioButton jRadioTimeSeconds; 87 protected LogarithmicTimeJSlider sleepSlider; 88 protected JLabel sleepDelay; 89 90 91 92 private boolean removed = false; 93 94 protected int failures = 0; 95 protected static final int MAX_FAILURES = 10; 96 protected ChartPanel chartPanel; 97 98 99 public AbstractGraphPanel() { 100 setDoubleBuffered(false); 101 initGraphPanel(); 102 } 103 104 public int getPersistenceType() { 105 return TopComponent.PERSISTENCE_NEVER; 106 } 107 108 public String getChartTitle() { 109 return chart.getTitle().getText(); 110 } 111 public void setChartTitle(final String name) { 112 SwingUtilities.invokeLater(new Runnable () { 113 public void run() { 114 setName(name); 115 } 116 }); 117 118 chart.setTitle( 119 new TextTitle(name, 120 new Font ("SansSerif",Font.BOLD, 12))); 121 122 } 123 124 protected void initGraphPanel() { 125 126 setPreferredSize(new Dimension (500,450)); 127 128 DateAxis domain = new DateAxis("Time"); 129 NumberAxis range = new NumberAxis(""); 130 131 this.xyplot = new XYPlot(); 132 this.xyplot.setDataset(dataset); 133 this.xyplot.setDomainAxis(domain); 134 this.xyplot.setRangeAxis(range); 135 DefaultXYItemRenderer renderer = new DefaultXYItemRenderer(); 136 renderer.setShapesVisible(false); 137 this.xyplot.setRenderer(renderer); 138 139 domain.setAutoRange(true); 140 domain.setLowerMargin(0.0); 141 domain.setUpperMargin(0.0); 142 domain.setTickLabelsVisible(true); 143 144 range.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); 145 146 this.chart = 147 new JFreeChart( 148 "", 149 JFreeChart.DEFAULT_TITLE_FONT, 150 xyplot, 151 true); 152 153 157 chartPanel = new ChartPanel(chart,false,true,true,false,false); 158 chartPanel.setOpaque(true); 160 chartPanel.setDoubleBuffered(false); 161 chart.setBackgroundPaint(this.getBackground()); 162 chartPanel.setBackground(this.getBackground()); 163 chartPanel.setBorder(new LineBorder (Color.BLACK,1)); 164 165 setLayout(new BorderLayout ()); 166 setOpaque(false); 167 add(chartPanel,BorderLayout.CENTER); 168 169 buildGraphControls(); 170 171 ControlsPopupButton dataButton = new ControlsPopupButton(new GraphSeriesPanel(dataset),"images/GraphElements.gif"); 172 this.controlsButton = new ControlsPopupButton(this.controlsPanel,"images/GraphSettings2.gif"); 173 174 JPanel northPanel = new JPanel(new FlowLayout (FlowLayout.RIGHT)); 175 northPanel.add(dataButton); 176 northPanel.add(this.controlsButton); 177 northPanel.setOpaque(false); 178 add(northPanel,BorderLayout.NORTH); 179 this.controlsPanel.setLocation(5,5); 180 181 doLayout(); 182 repaint(); 183 } 184 185 186 189 public static class ControlsPopupButton extends JCheckBox { 190 191 private JPopupMenu popup; 192 private Icon icon; 194 private JComponent payload; 195 196 public ControlsPopupButton(JComponent payload, String img) { 197 this.payload = payload; 198 this.icon = createImageIcon(img); 199 200 setIcon(icon); 201 setOpaque(false); 202 init(); 203 } 204 205 206 protected ImageIcon createImageIcon(String path) { 207 java.net.URL imgURL = RefreshControlComponent.class.getClassLoader().getResource(path); 208 if (imgURL != null) { 209 return new ImageIcon(imgURL); 210 } else { 211 System.err.println("Couldn't find file: " + path); 212 return null; 213 } 214 } 215 216 public void showPopup() { 217 GlassWindow.show(this.payload, this); 218 } 229 230 private void init() { 231 addActionListener(new ActionListener () { 232 public void actionPerformed(ActionEvent e) { 233 showPopup(); 234 } 235 }); 236 } 237 } 238 239 240 241 public long getUpdateDelay() { 242 if (sleepSlider != null) 243 return sleepSlider.getValue(); 244 else 245 return 1000L; 246 } 247 248 252 public void reschedule() { 253 if (this.dataGeneratorTimer == null) { 254 this.dataGeneratorTimer = new Timer (); 255 } 256 257 if (this.dataGeneratorTimerTask != null) { 258 try { 259 this.dataGeneratorTimerTask.cancel(); 260 } catch(Exception e) { e.printStackTrace();} 261 } 262 263 this.dataGeneratorTimer.schedule( 264 this.dataGeneratorTimerTask = getDataGeneratorTask(), 265 getUpdateDelay(), 266 getUpdateDelay()); 267 268 } 269 270 273 public void pauseSchedule() { 274 this.dataGeneratorTimerTask.cancel(); 275 this.dataGeneratorTimerTask = null; 276 } 277 278 279 protected TimerTask getDataGeneratorTask() { 280 return new DataGenerator(); 281 } 282 283 284 public void addNotify() { 285 super.addNotify(); 286 if (removed) { 287 reschedule(); 288 this.removed = false; 289 } 290 } 291 292 293 public void removeNotify() { 294 super.removeNotify(); 295 if (this.dataGeneratorTimer != null) 296 this.dataGeneratorTimer.cancel(); 297 this.dataGeneratorTimer = null; 298 this.removed = true; 299 } 300 301 302 303 308 public void setLogarithmic(boolean logarithmic) { 309 if (logarithmic) { 310 try { 311 this.xyplot.setRangeAxis(new LogarithmicAxis("")); 312 } catch(Exception e) { 313 this.xyplot.setRangeAxis(new NumberAxis("")); 315 } 316 } else { 317 this.xyplot.setRangeAxis(new NumberAxis("")); 318 } 319 } 320 321 public void setBackground(Color bg) { 322 super.setBackground(bg); 323 } 325 326 public void updateRange() { 327 DateAxis dateAxis = (DateAxis) this.xyplot.getDomainAxis(); 328 329 Calendar start = new GregorianCalendar (); 330 331 start.setTime(new Date ()); 332 333 if (this.jRadioTimeSeconds.isSelected()) { 334 start.add(Calendar.SECOND, -60); 335 } else if (this.jRadioTimeMinutes.isSelected()) { 336 start.add(Calendar.MINUTE, -60); 338 } else if (this.jRadioTimeHours.isSelected()) { 339 start.add(Calendar.HOUR, -48); 340 } 341 342 if (this.jRadioTimeMinutes.isSelected()) { 348 sleepSlider.setValue(10000); 349 } else if (this.jRadioTimeHours.isSelected()) { 350 sleepSlider.setValue(100000); 351 } 352 353 354 dateAxis.setRange(start.getTime(),new Date ()); 355 } 356 357 358 protected JPanel buildGraphControls() { 359 360 this.controlsPanel = new JPanel(); 361 this.controlsPanel.setLayout(new BoxLayout(this.controlsPanel,BoxLayout.X_AXIS)); 363 364 JPanel timeDurationPanel = new JPanel(); 366 timeDurationPanel.setLayout(new BoxLayout(timeDurationPanel, BoxLayout.Y_AXIS)); 367 timeDurationPanel.setBorder(BorderFactory.createTitledBorder("Time Range")); 368 369 buttonGroupTimeRange = new javax.swing.ButtonGroup (); 370 371 jRadioTimeSeconds = new javax.swing.JRadioButton ("seconds", true); 372 jRadioTimeSeconds.setToolTipText("Track the graph for 60 seconds"); 373 jRadioTimeSeconds.setOpaque(false); 374 375 jRadioTimeMinutes = new javax.swing.JRadioButton ("minutes", false); 376 jRadioTimeMinutes.setToolTipText("Track this graph for 60 minutes."); 377 jRadioTimeMinutes.setOpaque(false); 378 379 jRadioTimeHours = new javax.swing.JRadioButton ("hours", false); 380 jRadioTimeHours.setToolTipText("Track this graph for 48 hours."); 381 jRadioTimeHours.setOpaque(false); 382 383 buttonGroupTimeRange.add(jRadioTimeSeconds); 384 buttonGroupTimeRange.add(jRadioTimeMinutes); 385 buttonGroupTimeRange.add(jRadioTimeHours); 386 387 timeDurationPanel.add(jRadioTimeSeconds); 388 timeDurationPanel.add(jRadioTimeMinutes); 389 timeDurationPanel.add(jRadioTimeHours); 390 391 JPanel timeScalePanel = new JPanel(); 393 timeScalePanel.setLayout(new BoxLayout(timeScalePanel, BoxLayout.Y_AXIS)); 394 timeScalePanel.setBorder(BorderFactory.createTitledBorder("Time Scale")); 395 396 buttonGroupScale = new javax.swing.ButtonGroup (); 397 398 jRadioButtonScaleLinear = new javax.swing.JRadioButton ("Linear", true); 399 jRadioButtonScaleLinear.setOpaque(false); 400 401 jRadioButtonScaleLogarithmic = new javax.swing.JRadioButton ("Logarithmic", false); 402 jRadioButtonScaleLogarithmic.setOpaque(false); 403 404 buttonGroupScale.add(jRadioButtonScaleLinear); 405 buttonGroupScale.add(jRadioButtonScaleLogarithmic); 406 407 timeScalePanel.add(jRadioButtonScaleLinear); 408 timeScalePanel.add(jRadioButtonScaleLogarithmic); 409 410 JPanel updateSpeedPanel = new JPanel(); 412 updateSpeedPanel.setLayout(new BoxLayout(updateSpeedPanel, BoxLayout.Y_AXIS)); 413 updateSpeedPanel.setBorder(BorderFactory.createTitledBorder("Update Speed")); 414 415 421 sleepSlider = new LogarithmicTimeJSlider(100, 100000, 1000); 422 423 sleepSlider.setPaintTicks(true); 424 sleepSlider.setPaintLabels(true); 425 sleepSlider.setMajorTickSpacing(10); 426 sleepSlider.setMinorTickSpacing(10); 427 428 sleepSlider.setToolTipText("Time between updates"); 429 sleepSlider.setOpaque(false); 430 431 sleepDelay = new JLabel("Delay: " + sleepSlider.getTime()); 432 433 sleepSlider.addChangeListener(new javax.swing.event.ChangeListener () { 434 public void stateChanged(javax.swing.event.ChangeEvent evt) { 435 sleepSliderPropertyChange(null); 436 sleepDelay.setText("Delay: " + sleepSlider.getTime()); 437 } 438 }); 439 440 441 updateSpeedPanel.add(sleepSlider); 442 updateSpeedPanel.add(sleepDelay); 443 444 jRadioButtonScaleLinear.addChangeListener(new javax.swing.event.ChangeListener () { 445 public void stateChanged(javax.swing.event.ChangeEvent evt) { 446 scaleChanged(evt); 447 } 448 }); 449 450 jRadioButtonScaleLogarithmic.addChangeListener(new javax.swing.event.ChangeListener () { 451 public void stateChanged(javax.swing.event.ChangeEvent evt) { 452 scaleChanged(evt); 453 } 454 }); 455 456 457 this.controlsPanel.add(timeDurationPanel); 458 this.controlsPanel.add(updateSpeedPanel); 459 this.controlsPanel.add(timeScalePanel); 460 461 return this.controlsPanel; 462 } 463 464 465 private void scaleChanged(javax.swing.event.ChangeEvent evt) { 466 setLogarithmic(jRadioButtonScaleLogarithmic.isSelected()); 467 } 468 469 470 private void sleepSliderPropertyChange(java.beans.PropertyChangeEvent evt) { 471 if (!sleepSlider.getValueIsAdjusting()) { 472 reschedule(); 473 } 474 } 475 476 477 481 public abstract void addObservation() throws Exception ; 482 483 private void addObservationHandler() { 484 try { 485 addObservation(); 486 if (failures > 0) 487 failures--; 488 } catch (Exception e) { 489 failures++; 490 org.openide.windows.IOProvider.getDefault().getStdOut().println(e); 491 } 492 if (failures > MAX_FAILURES) { 493 pauseSchedule(); 494 } 495 496 updateRange(); 497 498 } 499 500 505 protected void createTimeSeries(String name, T key) { 506 TimeSeries ts = new TimeSeries(name, Millisecond.class); 507 ts.setMaximumItemAge(1000 * 60 * 60 * 48); this.timeSeriesMap.put(key, ts); 509 dataset.addSeries(ts); 511 } 512 513 protected TimeSeries getTimeSeries(T key) { 514 return this.timeSeriesMap.get(key); 515 } 516 517 public Set <T> getTimeSeriesKeys() { 518 return this.timeSeriesMap.keySet(); 519 } 520 521 524 protected class DataGenerator extends TimerTask { 525 526 public void run() { 527 addObservationHandler(); 528 } 529 } 530 531 532 533 private static class TestGraph extends AbstractGraphPanel { 534 public static final String TEST = "test"; 535 private int x = 1; 536 public TestGraph() { 537 createTimeSeries(TEST, TEST); 538 reschedule(); 539 } 540 public void addObservation() throws Exception { 541 getTimeSeries(TEST). 542 add(new Millisecond(), new Integer (x++)); 543 } 544 } 545 546 public static void main(String [] args) { 547 TestGraph graph = new TestGraph(); 548 549 JFrame frame = new JFrame(); 550 JPanel panel = new JPanel(); 551 panel.setLayout(new BorderLayout ()); 552 frame.getContentPane().add(panel); 553 panel.add(graph, BorderLayout.CENTER); 554 555 frame.pack(); 556 frame.addWindowListener(new WindowAdapter () { 557 public void windowClosing(WindowEvent e) { 558 System.exit(0); 559 } 560 }); 561 frame.setVisible(true); 562 } 563 564 } 565 | Popular Tags |