1 2 23 24 package net.fenyo.gnetwatch.GUI; 25 26 import java.awt.Color ; 27 import java.awt.Component ; 28 import java.awt.Dimension ; 29 import java.awt.Graphics ; 30 import java.awt.Graphics2D ; 31 import java.awt.Image ; 32 import java.awt.RenderingHints ; 33 import java.awt.event.ComponentEvent ; 34 import java.awt.event.ComponentListener ; 35 import java.awt.event.WindowEvent ; 36 import java.awt.event.WindowListener ; 37 import java.awt.font.TextLayout ; 38 import java.awt.geom.Rectangle2D ; 39 import java.text.DateFormat ; 40 import java.util.Date ; 41 42 import net.fenyo.gnetwatch.data.EventGeneric; 43 import net.fenyo.gnetwatch.targets.Target; 44 45 import org.apache.commons.logging.Log; 46 import org.apache.commons.logging.LogFactory; 47 48 53 54 58 public abstract class BasicComponent extends Component implements ComponentListener , WindowListener { 59 private static Log log = LogFactory.getLog(BasicComponent.class); 60 61 final private Target target; 62 63 private static Object sync_update = new Object (); 64 65 private java.util.List <EventGeneric> events = null; 66 67 private Image backing_store = null; 68 private Graphics2D backing_g = null; 69 private Dimension dimension = null; 70 71 private final DateFormat date_format = DateFormat.getDateTimeInstance(); 72 73 private int fps = 0; 74 private long last_paint = System.currentTimeMillis(); 75 private long last_paint_100ms = System.currentTimeMillis(); 76 private int last_fps_100ms = 0; 77 78 protected final int pixels_per_interval = 80; 81 private int value_per_vinterval = 200; 83 private final Object sync_value_per_vinterval = new Object (); 84 private final int pixels_per_vinterval = 80; 86 private final static int std_margin = 30; 87 private final static int std_separator = 3; 88 89 private final static int axis_margin_bottom = std_margin; 90 private final static int axis_margin_top = std_margin; 91 protected int axis_margin_left = std_margin; 92 protected final static int axis_margin_right = std_margin; 93 94 98 public BasicComponent(final Target target) { 100 this.target = target; 101 } 102 103 108 public long getDelayPerInterval() { 109 return 5000; } 111 112 117 protected void setEvents(final java.util.List <EventGeneric> events) { 118 this.events = events; 119 } 120 121 126 protected Dimension getDimension() { 127 return dimension; 128 } 129 130 135 protected Object getSyncUpdate() { 136 return sync_update; 137 } 138 139 144 protected Target getTarget() { 145 return target; 146 } 147 148 152 public void init() { 154 setPreferredSize(new Dimension (700, 400)); 155 addComponentListener(this); 156 } 157 158 163 public void componentHidden(final ComponentEvent e) { 164 } 165 166 171 public void componentMoved(final ComponentEvent e) { 172 } 173 174 180 public void componentResized(final ComponentEvent e) { 183 synchronized (sync_value_per_vinterval) { 184 newBackingElts(); 185 setMargin(); 186 updateValues(); 187 } 188 } 189 190 195 public void componentShown(final ComponentEvent e) { 197 componentResized(e); 198 } 199 200 205 public void windowActivated(final WindowEvent e) { 206 } 207 208 213 public void windowClosed(final WindowEvent e) { 214 } 215 216 221 public abstract void windowClosing(final WindowEvent e); 223 224 229 public void windowDeactivated(final WindowEvent e) { 230 } 231 232 237 public void windowDeiconified(final WindowEvent e) { 238 } 239 240 245 public void windowIconified(final WindowEvent e) { 246 } 247 248 253 public void windowOpened(final WindowEvent e) { 254 } 255 256 261 private void setMargin() { 264 final String left_values_str = "" + (int) (value_per_vinterval * 265 (1 + (dimension.height - axis_margin_top - axis_margin_bottom) / pixels_per_vinterval)); 266 final TextLayout layout = new TextLayout (left_values_str, backing_g.getFont(), backing_g.getFontRenderContext()); 267 final Rectangle2D bounds = layout.getBounds(); 268 axis_margin_left = (int) bounds.getWidth() + 5 + 10; 269 } 270 271 276 private void newBackingElts() { 279 dimension = getSize(); 280 backing_store = createImage(dimension.width, dimension.height); 281 backing_g = (Graphics2D ) backing_store.getGraphics(); 282 backing_g.setBackground(Color.BLACK); 283 backing_g.setColor(Color.WHITE); 284 backing_g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 285 RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 286 backing_g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 287 RenderingHints.VALUE_ANTIALIAS_ON); 288 } 289 290 296 private void removeOldEvents() { 298 final Date begin = new Date (System.currentTimeMillis() - getDelayPerInterval() * 299 (dimension.width - axis_margin_left - axis_margin_right) / pixels_per_interval); 300 while (events.size() >= 2 && (events.get(1).getDate().before(begin) || events.get(1).getDate().equals(begin))) 301 events.remove(0); 302 } 303 304 309 protected void updateVerticalScale() { 311 final int previous_value_per_vinterval = value_per_vinterval; 312 313 int max_value = 0; 314 int i = 0; 315 for (final EventGeneric event : events) { 316 final int value = event.getIntValue(events, i++); 317 if (value > max_value) max_value = value; 318 } 319 320 int nintervals = (dimension.height - axis_margin_top - axis_margin_bottom) / pixels_per_vinterval - 1; 321 if (nintervals < 1) nintervals = 1; 322 value_per_vinterval = max_value / nintervals; 323 324 final int base = (int) Math.pow(10, new Integer (value_per_vinterval).toString().length() - 1); 326 if (value_per_vinterval != base) 327 if (value_per_vinterval <= 2 * base) value_per_vinterval = 2 * base; 328 else if (base >= 10 && value_per_vinterval <= 25 * base / 10) value_per_vinterval = 25 * base / 10; 329 else if (value_per_vinterval <= 5 * base) value_per_vinterval = 5 * base; 330 else value_per_vinterval = 10 * base; 331 332 if (value_per_vinterval == 0) value_per_vinterval = 1; 333 334 if (previous_value_per_vinterval != value_per_vinterval) setMargin(); 335 } 336 337 342 public void updateValues(final EventGeneric event) { 345 synchronized (sync_value_per_vinterval) { 346 synchronized (sync_update) { 347 synchronized (events) { 348 for (int i = events.size() - 1; i >= 0; i--) 349 if (events.get(i).getDate().before(event.getDate())) { 350 if (i + 1 < events.size()) events.add(i + 1, event); 351 else events.add(event); 352 removeOldEvents(); 353 updateVerticalScale(); 354 return; 355 } 356 events.add(0, event); 357 removeOldEvents(); 358 updateVerticalScale(); 359 } 360 } 361 } 362 } 363 364 369 protected abstract void updateValues(); 372 373 378 private void updateFPS() { 380 final long current_time = System.currentTimeMillis(); 381 fps = 100 / (int) (current_time - last_paint + 1) + (9 * fps) / 10; 382 last_paint = current_time; 383 } 384 385 390 private void paintFPS(final int fps) { 392 backing_g.setColor(Color.GRAY); 393 backing_g.drawString(fps + " frames/s", 1, 10); 394 } 395 396 401 private String formatTime(final long time) { 403 String str = date_format.format(new Date (time)); 404 return str.substring(str.lastIndexOf(' ') + 1); 405 } 406 407 412 private long paintAxis() { 414 backing_g.setColor(new Color (50, 50, 50)); 415 backing_g.fillRect(axis_margin_left, axis_margin_top, 416 dimension.width - axis_margin_left - axis_margin_right + 1, 417 dimension.height - axis_margin_top - axis_margin_bottom + 1); 418 419 backing_g.setColor(Color.YELLOW); 420 backing_g.drawLine(axis_margin_left, dimension.height - axis_margin_bottom, 421 dimension.width - axis_margin_right, dimension.height - axis_margin_bottom); 422 backing_g.drawLine(axis_margin_left, axis_margin_top, 423 axis_margin_left, dimension.height - axis_margin_bottom); 424 425 backing_g.setColor(Color.YELLOW.darker()); 426 backing_g.drawLine(axis_margin_left + 1, axis_margin_top, 427 dimension.width - axis_margin_right, 428 axis_margin_top); 429 backing_g.drawLine(dimension.width - axis_margin_right, 430 axis_margin_top, 431 dimension.width - axis_margin_right, 432 dimension.height - axis_margin_bottom - 1); 433 434 int vinterval_pos = dimension.height - axis_margin_bottom - pixels_per_vinterval; 435 backing_g.setColor(Color.YELLOW.darker().darker().darker()); 436 while (vinterval_pos + 9 * (pixels_per_vinterval / 10) > axis_margin_top) { 437 int cpt = 10; 438 while (--cpt > 0) 439 if (vinterval_pos + cpt * (pixels_per_vinterval / 10) > axis_margin_top) 440 backing_g.drawLine(axis_margin_left + 1, vinterval_pos + cpt * (pixels_per_vinterval / 10), 441 dimension.width - axis_margin_right - 1, vinterval_pos + cpt * (pixels_per_vinterval / 10)); 442 vinterval_pos -= pixels_per_vinterval; 443 } 444 445 final long now = System.currentTimeMillis(); 446 447 final long time_to_display = now - now % getDelayPerInterval(); 448 final int pixels_offset = (pixels_per_interval * (int) (now % getDelayPerInterval())) / (int) getDelayPerInterval(); 449 final int last_interval_pos = dimension.width - axis_margin_right - pixels_offset; 450 451 backing_g.setClip(axis_margin_left, 0, 452 dimension.width - axis_margin_left - axis_margin_right, 453 dimension.height); 454 int current_interval_pos = last_interval_pos + pixels_per_interval; 455 long current_time_to_display = time_to_display + getDelayPerInterval(); 456 boolean stop = false; 457 while (stop == false) { 458 backing_g.setColor(Color.YELLOW.darker()); 459 backing_g.drawLine(current_interval_pos, axis_margin_top, 460 current_interval_pos, dimension.height - axis_margin_bottom + std_separator); 461 462 int cpt = 10; 463 backing_g.setColor(Color.YELLOW.darker().darker().darker()); 464 while (--cpt > 0) 465 if (current_interval_pos - cpt * (pixels_per_interval / 10) > axis_margin_left) 466 backing_g.drawLine(current_interval_pos - cpt * (pixels_per_interval / 10), 467 axis_margin_top + 1, 468 current_interval_pos - cpt * (pixels_per_interval / 10), 469 dimension.height - axis_margin_bottom - 1); 470 471 final String current_time_str = formatTime(current_time_to_display); 472 final TextLayout current_layout = new TextLayout (current_time_str, backing_g.getFont(), backing_g.getFontRenderContext()); 473 final Rectangle2D current_bounds = current_layout.getBounds(); 474 backing_g.setColor(Color.YELLOW.darker()); 475 backing_g.drawString(current_time_str, 476 current_interval_pos - (int) (current_bounds.getWidth() / 2), 477 dimension.height - axis_margin_bottom + (int) current_bounds.getHeight() + 2 * std_separator); 478 if (current_interval_pos - current_bounds.getWidth() / 2 < axis_margin_left) 479 stop = true; 480 current_interval_pos -= pixels_per_interval; 481 current_time_to_display -= getDelayPerInterval(); 482 } 483 backing_g.setClip(null); 484 485 vinterval_pos = dimension.height - axis_margin_bottom - pixels_per_vinterval; 486 int value = value_per_vinterval; 487 while (vinterval_pos > axis_margin_top) { 488 backing_g.setColor(Color.YELLOW.darker()); 489 backing_g.drawLine(axis_margin_left - std_separator, vinterval_pos, 490 dimension.width - axis_margin_right, vinterval_pos); 491 final String value_str = "" + value; 492 final TextLayout current_layout = new TextLayout (value_str, backing_g.getFont(), backing_g.getFontRenderContext()); 493 final Rectangle2D current_bounds = current_layout.getBounds(); 494 backing_g.setColor(Color.YELLOW.darker()); 495 backing_g.drawString(value_str, 496 axis_margin_left - (int) current_bounds.getWidth() - 2 * std_separator, 497 vinterval_pos + (int) (current_bounds.getHeight() / 2)); 498 vinterval_pos -= pixels_per_vinterval; 499 value += value_per_vinterval; 500 } 501 502 return now; 503 } 504 505 510 public void paintChart(final long now) { 513 backing_g.setClip(axis_margin_left + 1, axis_margin_top, 514 dimension.width - axis_margin_left - axis_margin_right - 1, 515 dimension.height - axis_margin_top - axis_margin_bottom); 516 517 synchronized (events) { 518 final int npoints = events.size(); 519 final int point_x[] = new int [npoints]; 520 final int point_y[] = new int [npoints]; 521 522 final long time_to_display = now - now % getDelayPerInterval(); 523 final int pixels_offset = (pixels_per_interval * (int) (now % getDelayPerInterval())) / (int) getDelayPerInterval(); 524 final int last_interval_pos = dimension.width - axis_margin_right - pixels_offset; 525 526 for (int i = 0; i < events.size(); i++) { 527 final EventGeneric event = events.get(i); 528 point_x[i] = last_interval_pos + (int) ((pixels_per_interval * 529 (int) (event.getDate().getTime() - time_to_display)) / getDelayPerInterval()); 530 531 point_y[i] = (int) (dimension.height - axis_margin_bottom - 533 pixels_per_vinterval * (double) event.getIntValue(events, i) / value_per_vinterval); 534 if (point_y[i] < 0) log.warn("y < 0: y=" + point_y[i]); 535 } 536 537 backing_g.setColor(Color.GREEN); 538 backing_g.drawPolyline(point_x, point_y, events.size()); 539 540 backing_g.setColor(Color.RED); 541 for (int i = 0; i < events.size(); i++) 542 backing_g.drawRect(point_x[i] - 2, point_y[i] - 2, 4, 4); 543 544 backing_g.setClip(null); 545 } 546 } 547 548 553 public void paint(final Graphics g) { 555 if (backing_store == null) return; 556 backing_g.clearRect(0, 0, dimension.width, dimension.height); 557 558 updateFPS(); 559 560 final long current_time = System.currentTimeMillis(); 561 if (current_time - last_paint_100ms >= 100) { 562 last_paint_100ms = current_time; 563 last_fps_100ms = fps; 564 } 565 paintFPS(last_fps_100ms); 566 567 synchronized (sync_value_per_vinterval) { 568 final long now = paintAxis(); 569 paintChart(now); 570 } 571 572 g.drawImage(backing_store, 0, 0, this); 573 } 574 } 575 | Popular Tags |