1 26 27 package org.nightlabs.editor2d.viewer.awt; 28 29 import java.awt.BasicStroke ; 30 import java.awt.Color ; 31 import java.awt.Component ; 32 import java.awt.Graphics ; 33 import java.awt.Graphics2D ; 34 import java.awt.Rectangle ; 35 import java.awt.event.ComponentAdapter ; 36 import java.awt.event.ComponentEvent ; 37 import java.awt.event.ComponentListener ; 38 import java.awt.geom.Point2D ; 39 import java.awt.image.BufferedImage ; 40 import java.util.Iterator ; 41 42 import javax.swing.JPanel ; 43 import javax.swing.JToolTip ; 44 45 import org.apache.log4j.Logger; 46 47 import org.nightlabs.base.util.GeomUtil; 48 import org.nightlabs.editor2d.DrawComponent; 49 import org.nightlabs.editor2d.render.Renderer; 50 import org.nightlabs.editor2d.viewer.BufferManager; 51 import org.nightlabs.editor2d.viewer.DrawComponentPaintable; 52 import org.nightlabs.editor2d.viewer.IBufferedCanvas; 53 import org.nightlabs.editor2d.viewer.IBufferedViewport; 54 import org.nightlabs.editor2d.viewer.ICanvas; 55 import org.nightlabs.editor2d.viewer.ITempContentManager; 56 import org.nightlabs.editor2d.viewer.IViewport; 57 import org.nightlabs.editor2d.viewer.RenderingHintsManager; 58 import org.nightlabs.editor2d.viewer.TempContentManager; 59 60 public class DisplayPanel 61 extends JPanel 62 implements IBufferedViewport 64 { 65 public static final Logger LOGGER = Logger.getLogger(DisplayPanel.class); 66 67 public DisplayPanel(DrawComponent dc) 68 { 69 super(); 70 this.dc = dc; 71 Rectangle dcBounds = GeomUtil.translateRectToOrigin(dc.getBounds()); 72 setBackground(bgColor); 73 renderingHintsManager.setRenderMode(RenderingHintsManager.RENDER_MODE_QUALITY); 74 init(dcBounds); 75 } 77 78 public DrawComponent getDrawComponent() { 79 return dc; 80 } 81 82 private boolean debugBounds = false; 83 private boolean debugPaint = false; 84 85 private void setDebug(boolean paint, boolean bounds) 86 { 87 debugPaint = paint; 88 debugBounds = bounds; 89 } 90 91 protected int imageType = BufferedImage.TYPE_INT_RGB; 92 protected Rectangle bufferBounds; 93 protected DrawComponent dc; 94 protected BufferedImage bufferedImage; 95 protected BufferedImage viewImage; 96 protected int initSize = 100; 98 protected RenderingHintsManager renderingHintsManager = RenderingHintsManager.sharedInstance(); 100 101 105 public void paint(Graphics g) 106 { 107 Graphics2D g2d = (Graphics2D ) g; 108 109 long startPaintTime = 0; 110 if (debugPaint) { 111 startPaintTime = System.currentTimeMillis(); 112 } 113 114 if (isChanged) 115 { 116 if (debugPaint) 117 LOGGER.debug("buffer cleared!"); 118 119 paintDrawComponent(); 120 isChanged = false; 121 } 122 123 g2d.setPaint(bgColor); 125 Rectangle bgRect = initRealBounds; 126 g2d.setClip(0, 0, bgRect.width, bgRect.height); 127 g2d.fillRect(0, 0, bgRect.width, bgRect.height); 128 129 if (debugBounds) 130 LOGGER.debug("bgRect = "+bgRect); 131 132 if (bufferedImage != null) 133 { 134 long startTime = 0; 135 if (debugPaint) 136 startTime = System.currentTimeMillis(); 137 138 calcBufferedViewImage(); 140 g2d.drawImage(viewImage,0,0,this); 141 142 if (debugPaint) 143 LOGGER.debug("BitBlockTransfer took "+(System.currentTimeMillis()-startTime)+" ms!"); 144 145 if (debugBounds) { 146 LOGGER.debug("viewImage width = "+viewImage.getWidth()); 147 LOGGER.debug("viewImage height = "+viewImage.getHeight()); 148 } 149 } 150 151 if (drawTempContent == true) { 153 g2d.translate(-getOffsetX(), -getOffsetY()); 154 g2d.scale(getScale(), getScale()); 155 drawTempContent(g2d); 156 } 157 158 if (debugPaint) { 159 LOGGER.debug("Total Paint took "+(System.currentTimeMillis()-startPaintTime)+" ms"); 160 LOGGER.debug(""); 161 } 162 } 163 164 169 protected void calcBufferedViewImage() 170 { 171 int offsetX = getBufferOffsetX(); 172 int offsetY = getBufferOffsetY(); 173 174 if (viewImage != null) 175 viewImage.flush(); 176 177 long startTime = 0; 178 if (debugPaint) { 179 startTime = System.currentTimeMillis(); 180 } 181 182 185 if ((bufferedImage.getWidth() >= viewBounds.width + offsetX) && 186 (bufferedImage.getHeight() >= viewBounds.height + offsetY)) 187 { 188 viewImage = 189 bufferedImage.getSubimage(offsetX, offsetY, 190 viewBounds.width, 191 viewBounds.height); 192 } 193 194 if (debugPaint) { 195 long endTime = System.currentTimeMillis() - startTime; 196 LOGGER.debug("create viewImage took "+endTime+" ms!"); 197 } 198 } 199 200 206 protected void setZoomedRealBounds(double scale) 207 { 208 int newWidth = (int) Math.floor(initRealBounds.width * scale); 209 int newHeight = (int) Math.floor(initRealBounds.height * scale); 210 Rectangle newRealBounds = new Rectangle (0, 0, newWidth, newHeight); 211 setRealBounds(newRealBounds); 212 } 213 214 protected double scale = 1.0d; 215 protected double oldScale = scale; 216 217 221 public void setScale(double scale) { 222 oldScale = this.scale; 223 this.scale = scale; 224 setZoomedRealBounds(scale); 225 } 226 227 230 public double getScale() { 231 return scale; 232 } 233 234 237 public void translateX(float translateX) { 238 setViewLocation((int)(viewBounds.x + translateX), viewBounds.y); 239 } 240 241 244 public void translateY(float translateY) { 245 setViewLocation(viewBounds.x, (int)(viewBounds.y + translateY)); 246 } 247 248 protected Color bgColor = Color.WHITE; 249 public void setBackground(int red, int green, int blue) { 250 bgColor = new Color (red, green, blue); 251 } 252 253 protected Rectangle realBounds; 254 255 260 public Rectangle getRealBounds() { 261 return realBounds; 262 } 263 public void setRealBounds(Rectangle realBounds) 264 { 265 Rectangle oldReal = this.realBounds; 266 checkScale(realBounds); 267 scaleToCenter(); 268 firePropertyChange(REAL_CHANGE, oldReal, this.realBounds); 269 setViewBounds(getViewBounds()); 270 notifyChange(); 271 } 272 273 278 protected void scaleToCenter() 279 { 280 int newViewX = (int) ((((double)viewBounds.x) / oldScale) * scale); 281 int newViewY = (int) ((((double)viewBounds.y) / oldScale) * scale); 282 285 if (debugBounds) { 286 LOGGER.debug("newViewX = "+newViewX); 287 LOGGER.debug("newViewY = "+newViewY); 288 } 289 290 setViewLocation(newViewX, newViewY); 291 } 292 293 protected Rectangle viewBounds; 294 295 299 public Rectangle getViewBounds() { 300 return viewBounds; 301 } 302 303 306 public Point2D getViewLocation() 307 { 308 return getViewBounds().getLocation(); 309 } 310 311 315 public void setViewBounds(Rectangle viewBounds) 316 { 317 Rectangle oldView = this.viewBounds; 318 319 if (isRectangleInReal(viewBounds)) 320 this.viewBounds = viewBounds; 321 else 322 this.viewBounds = GeomUtil.checkBounds(viewBounds, realBounds); 323 324 firePropertyChange(VIEW_CHANGE, oldView, this.viewBounds); 325 checkBuffer(); 326 repaint(); 327 328 if (debugBounds) { 329 LOGGER.debug("realBounds = " + realBounds); 330 LOGGER.debug("bufferBounds = " + bufferBounds); 331 LOGGER.debug("viewBounds = "+viewBounds); 332 LOGGER.debug(""); 333 } 334 } 335 336 protected Rectangle initRealBounds; 337 protected Rectangle initViewBounds; 338 339 protected void init(Rectangle realBounds) 340 { 341 initRealBounds = new Rectangle (realBounds); 342 initViewBounds = getVisibleRect(); 343 344 this.realBounds = realBounds; 345 viewBounds = getVisibleRect(); 346 initBuffer(); 347 paintDrawComponent(); 348 addComponentListener(resizeListener); 349 350 if (debugBounds) { 351 LOGGER.debug("realBounds = "+realBounds); 352 LOGGER.debug("viewBounds = "+viewBounds); 353 } 354 } 355 356 protected void initBuffer() 357 { 358 bufferBounds = new Rectangle (0, 0, initSize, initSize); 359 bufferedImage = new BufferedImage (bufferBounds.width, bufferBounds.height, imageType); 360 } 361 362 protected ComponentListener resizeListener = new ComponentAdapter () 363 { 364 public void componentResized(ComponentEvent e) 365 { 366 Rectangle visibleRect = getVisibleRect(); 367 initViewBounds = getVisibleRect(); 368 Rectangle newView = new Rectangle (viewBounds.x, viewBounds.y, 369 visibleRect.width, visibleRect.height); 370 371 if (!newView.equals(viewBounds)) 372 { 373 setViewBounds(newView); 374 if (debugBounds) { 375 LOGGER.debug("Viewport resized!"); 376 LOGGER.debug("viewBounds = "+viewBounds); 377 } 378 } 379 } 380 }; 381 382 protected boolean isChanged = false; 383 384 388 public void notifyChange() 389 { 390 isChanged = true; 391 repaint(); 392 393 LOGGER.debug("notifyChange!"); 394 } 395 396 399 protected void paintDrawComponent() 400 { 401 long startTime = 0; 402 if (debugPaint) 403 startTime = System.currentTimeMillis(); 404 405 if (bufferedImage != null) 406 { 407 Graphics2D g2d = (Graphics2D ) bufferedImage.getGraphics(); 408 g2d.setRenderingHints(renderingHintsManager.getRenderingHints()); 409 g2d.setBackground(bgColor); 410 g2d.translate(-bufferBounds.x, -bufferBounds.y); 411 412 g2d.setClip(bufferBounds); 413 g2d.fillRect(bufferBounds.x, bufferBounds.y, bufferBounds.width, bufferBounds.height); 414 415 if (debugPaint) 416 { 417 drawRealRectangle(g2d); 418 drawBufferRectangle(g2d); 419 drawViewRectangle(g2d); 420 } 421 422 g2d.scale(scale, scale); 423 DrawComponentPaintable.paintDrawComponent(dc, g2d); 424 } 425 426 if (debugPaint) 427 { 428 long endTime = System.currentTimeMillis() - startTime; 429 LOGGER.debug("paintDrawComponent took "+endTime+" ms!"); 430 } 431 } 432 433 private void drawViewRectangle(Graphics2D g2) 435 { 436 if (viewBounds != null) 437 { 438 int distance = 10; 439 g2.setPaint(java.awt.Color.YELLOW); 440 g2.setStroke(new BasicStroke (2)); 441 g2.drawRect(viewBounds.x+distance, 442 viewBounds.y+distance, 443 viewBounds.width-distance, 444 viewBounds.height-distance); 445 } 446 } 447 448 private void drawBufferRectangle(Graphics2D g2) 450 { 451 if (bufferBounds != null) 452 { 453 int distance = 10; 454 g2.setPaint(java.awt.Color.GREEN); 455 g2.setStroke(new BasicStroke (4)); 456 g2.drawRect(bufferBounds.x+distance, 457 bufferBounds.y+distance, 458 bufferBounds.width-distance, 459 bufferBounds.height-distance); 460 } 461 } 462 463 private void drawRealRectangle(Graphics2D g2) 465 { 466 if (bufferBounds != null) 467 { 468 int distance = 10; 469 g2.setPaint(java.awt.Color.BLUE); 470 g2.setStroke(new BasicStroke (6)); 471 g2.drawRect(realBounds.x+distance, 472 realBounds.y+distance, 473 realBounds.width-distance, 474 realBounds.height-distance); 475 } 476 } 477 478 483 protected Rectangle getBufferRectangle() 484 { 485 double bufferScaleFactor = BufferManager.sharedInstance().getBufferScaleFactor(); 486 int bufferWidth = (int) (viewBounds.width * bufferScaleFactor); 487 int bufferHeight = (int) (viewBounds.height * bufferScaleFactor); 488 489 Rectangle newBufferBounds = new Rectangle (viewBounds.x - ((bufferWidth - viewBounds.width)/2), 490 viewBounds.y - ((bufferHeight-viewBounds.height)/2), bufferWidth, bufferHeight); 491 492 if (isRectangleInReal(newBufferBounds)) 493 return newBufferBounds; 494 else 495 return GeomUtil.checkBounds(newBufferBounds, realBounds); 496 } 497 498 504 protected void checkBuffer() 505 { 506 if (!isViewInBuffer()) 507 { 508 if (bufferedImage != null) 509 bufferedImage.flush(); 510 bufferedImage = null; 511 createOffScreenImage(); 512 notifyChange(); 513 514 if (debugBounds) 515 LOGGER.debug("Buffer updated!"); 516 } 517 } 518 519 523 protected boolean isViewInBuffer() 524 { 525 if (bufferBounds != null && viewBounds != null) 526 return bufferBounds.contains(viewBounds); 527 else 528 return false; 529 } 530 531 536 protected boolean isRectangleInReal(Rectangle r) 537 { 538 if (realBounds != null && r != null) 539 return realBounds.contains(r); 540 else 541 return false; 542 } 543 544 549 protected void createOffScreenImage() 550 { 551 bufferBounds = getBufferRectangle(); 552 bufferedImage = new BufferedImage (bufferBounds.width, bufferBounds.height, imageType); 553 } 554 555 public int getOffsetX() { 556 return viewBounds.x - realBounds.x; 557 } 558 559 public int getOffsetY() { 560 return viewBounds.y - realBounds.y; 561 } 562 563 protected int getBufferOffsetX() { 564 return viewBounds.x - bufferBounds.x; 565 } 566 567 protected int getBufferOffsetY() { 568 return viewBounds.y - bufferBounds.y; 569 } 570 571 public void setViewLocation(int x, int y) { 572 setViewBounds(new Rectangle (x, y, viewBounds.width, viewBounds.height)); 573 } 574 575 public void setViewLocation(Point2D p) { 576 setViewLocation((int)p.getX(), (int)p.getY()); 577 } 578 579 public void setViewCenter(float x, float y) 580 { 581 Rectangle newView = new Rectangle (); 582 newView.setFrameFromCenter(x, y, 583 x + viewBounds.getWidth() / 2, 584 y + viewBounds.getHeight() / 2); 585 setViewBounds(newView); 586 } 587 588 public Point2D getViewCenter() 589 { 590 double viewCenterX = viewBounds.getCenterX(); 591 double viewCenterY = viewBounds.getCenterY(); 592 return new Point2D.Float ((float)viewCenterX, (float)viewCenterY); 593 } 594 595 protected void checkScale(Rectangle newReal) 596 { 597 int maxRealX = (int)newReal.getMaxX(); 598 int maxRealY = (int)newReal.getMaxY(); 599 int maxViewX = (int)initViewBounds.getMaxX(); 600 int maxViewY = (int)initViewBounds.getMaxY(); 601 int maxX = Math.max(maxRealX, maxViewX); 602 int maxY = Math.max(maxRealY, maxViewY); 603 realBounds = new Rectangle (0, 0, maxX, maxY); 604 605 if (debugBounds) { 606 LOGGER.debug("viewBounds = "+viewBounds); 607 LOGGER.debug("realBounds = "+realBounds); 608 LOGGER.debug("initViewBounds = "+initViewBounds); 609 } 610 } 611 612 protected boolean drawTempContent = true; 613 public void drawTempContent(Graphics2D g2d) 614 { 615 for (Iterator it = getTempContentManager().getTempContent().iterator(); it.hasNext(); ) 616 { 617 Object o = it.next(); 618 if (o instanceof DrawComponent) { 619 DrawComponent dc = (DrawComponent) o; 620 Renderer r = null; 621 if (dc.getRoot() != null) { 622 r = dc.getRenderer(); 623 } 624 if (r == null) { 625 int renderMode = dc.getRenderMode(); 626 r = getDrawComponent().getRenderModeManager().getRenderer(renderMode, dc.getClass()); 627 } 628 r.paint(dc, g2d); 629 } 630 else if (o instanceof JToolTip ) { 631 JToolTip tooltip = (JToolTip ) o; 632 JToolTip tt = createToolTip(); 633 tt.setTipText(tooltip.getTipText()); 634 tt.setLocation(tooltip.getLocation()); 635 } 636 else if (o instanceof Component ) { 637 Component c = (Component ) o; 638 c.paint(g2d); 639 } 640 } 641 } 642 643 protected ITempContentManager tempContentMan = new TempContentManager(); 644 public ITempContentManager getTempContentManager() { 645 return tempContentMan; 646 } 647 } 648 | Popular Tags |