1 7 package com.sun.java.swing.plaf.nimbus; 8 9 import java.awt.*; 10 import java.awt.image.*; 11 import java.lang.reflect.Method ; 12 import java.lang.reflect.InvocationTargetException ; 13 import javax.swing.*; 14 import javax.swing.plaf.UIResource ; 15 import com.sun.java.swing.Painter; 16 import java.awt.print.PrinterGraphics ; 17 import java.beans.PropertyDescriptor ; 18 19 26 public abstract class AbstractRegionPainter implements Painter<JComponent> { 27 36 private PaintContext ctx; 37 40 private float f; 41 67 70 private float leftWidth; 71 74 private float topHeight; 75 78 private float centerWidth; 79 82 private float centerHeight; 83 86 private float rightWidth; 87 90 private float bottomHeight; 91 94 private float leftScale; 95 98 private float topScale; 99 103 private float centerHScale; 104 108 private float centerVScale; 109 112 private float rightScale; 113 116 private float bottomScale; 117 118 121 protected AbstractRegionPainter() { } 122 123 126 @Override  127 public final void paint(Graphics2D g, JComponent c, int w, int h) { 128 if (w <= 0 || h <=0) return; 130 131 Object [] extendedCacheKeys = getExtendedCacheKeys(c); 132 ctx = getPaintContext(); 133 PaintContext.CacheMode cacheMode = ctx == null ? PaintContext.CacheMode.NO_CACHING : ctx.cacheMode; 134 if (cacheMode == PaintContext.CacheMode.NO_CACHING || 135 !ImageCache.getInstance().isImageCachable(w, h) || 136 g instanceof PrinterGraphics ) { 137 paint0(g, c, w, h, extendedCacheKeys); 139 } else if (cacheMode == PaintContext.CacheMode.FIXED_SIZES) { 140 paintWithFixedSizeCaching(g, c, w, h, extendedCacheKeys); 141 } else { 142 paintWith9SquareCaching(g, ctx, c, w, h, extendedCacheKeys); 144 } 145 } 146 147 155 protected Object [] getExtendedCacheKeys(JComponent c) { 156 return null; 157 } 158 159 171 protected abstract PaintContext getPaintContext(); 172 173 182 protected void configureGraphics(Graphics2D g) { 183 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 184 } 185 186 205 protected abstract void doPaint(Graphics2D g, JComponent c, int width, 206 int height, Object [] extendedCacheKeys); 207 208 215 protected final float decodeX(float x) { 216 if (ctx.canvasSize == null) return x; 217 218 if (x >= 0 && x <= 1) { 219 return x * leftWidth; 220 } else if (x > 1 && x < 2) { 221 return ((x-1) * centerWidth) + leftWidth; 222 } else if (x >= 2 && x <= 3) { 223 return ((x-2) * rightWidth) + leftWidth + centerWidth; 224 } else { 225 throw new AssertionError ("Invalid x"); 226 } 227 } 228 229 236 protected final float decodeY(float y) { 237 if (ctx.canvasSize == null) return y; 238 239 if (y >= 0 && y <= 1) { 240 return y * topHeight; 241 } else if (y > 1 && y < 2) { 242 return ((y-1) * centerHeight) + topHeight; 243 } else if (y >= 2 && y <= 3) { 244 return ((y-2) * bottomHeight) + topHeight + centerHeight; 245 } else { 246 throw new AssertionError ("Invalid y"); 247 } 248 } 249 250 259 protected final float decodeAnchorX(float x, float dx) { 260 if (ctx.canvasSize == null) return x + dx; 261 262 if (x >= 0 && x <= 1) { 263 return decodeX(x) + (dx * leftScale); 264 } else if (x > 1 && x < 2) { 265 return decodeX(x) + (dx * centerHScale); 266 } else if (x >= 2 && x <= 3) { 267 return decodeX(x) + (dx * rightScale); 268 } else { 269 throw new AssertionError ("Invalid x"); 270 } 271 } 272 273 282 protected final float decodeAnchorY(float y, float dy) { 283 if (ctx.canvasSize == null) return y + dy; 284 285 if (y >= 0 && y <= 1) { 286 return decodeY(y) + (dy * topScale); 287 } else if (y > 1 && y < 2) { 288 return decodeY(y) + (dy * centerVScale); 289 } else if (y >= 2 && y <= 3) { 290 return decodeY(y) + (dy * bottomScale); 291 } else { 292 throw new AssertionError ("Invalid y"); 293 } 294 } 295 296 309 protected final Color decodeColor(String key, float hOffset, float sOffset, 310 float bOffset, int aOffset) { 311 if (UIManager.getLookAndFeel() instanceof NimbusLookAndFeel){ 312 NimbusLookAndFeel laf = (NimbusLookAndFeel) UIManager.getLookAndFeel(); 313 return laf.getDerivedColor(key, hOffset, sOffset, bOffset, aOffset, true); 314 } else { 315 return Color.getHSBColor(hOffset,sOffset,bOffset); 318 } 319 } 320 321 334 protected final Color decodeColor(Color color1, Color color2, 335 float midPoint) { 336 if (UIManager.getLookAndFeel() instanceof NimbusLookAndFeel){ 337 NimbusLookAndFeel laf = (NimbusLookAndFeel) UIManager.getLookAndFeel(); 338 return laf.getDerivedColor(color1, color2, midPoint); 339 } else { 340 return new Color( 343 (color1.getRed() + color2.getRed())/2, 344 (color1.getGreen() + color2.getGreen())/2, 345 (color1.getBlue() + color2.getBlue())/2 346 ); 347 } 348 } 349 350 365 protected final LinearGradientPaint decodeGradient(float x1, float y1, float x2, float y2, float[] midpoints, Color[] colors) { 366 if (x1 == x2 && y1 == y2) { 367 y2 += .00001f; 368 } 369 return new LinearGradientPaint(x1, y1, x2, y2, midpoints, colors); 370 } 371 372 386 protected final RadialGradientPaint decodeRadialGradient(float x, float y, float r, float[] midpoints, Color[] colors) { 387 if (r == 0f) { 388 r = .00001f; 389 } 390 return new RadialGradientPaint(x, y, r, midpoints, colors); 391 } 392 393 405 protected final Color getComponentColor(JComponent c, String property, 406 Color defaultColor, 407 float saturationOffset, 408 float brightnessOffset, 409 int alphaOffset) { 410 Color color = null; 411 if (c != null) { 412 if ("background".equals(property)) { 414 color = c.getBackground(); 415 } else if ("foreground".equals(property)) { 416 color = c.getForeground(); 417 } else if (c instanceof JList && "selectionForeground".equals(property)) { 418 color = ((JList) c).getSelectionForeground(); 419 } else if (c instanceof JList && "selectionBackground".equals(property)) { 420 color = ((JList) c).getSelectionBackground(); 421 } else if (c instanceof JTable && "selectionForeground".equals(property)) { 422 color = ((JTable) c).getSelectionForeground(); 423 } else if (c instanceof JTable && "selectionBackground".equals(property)) { 424 color = ((JTable) c).getSelectionBackground(); 425 } else { 426 String s = "get" + Character.toUpperCase(property.charAt(0)) + property.substring(1); 427 try { 428 Method method = c.getClass().getMethod(s); 429 color = (Color) method.invoke(c); 430 } catch (Exception e) { 431 } 436 if (color == null) { 437 Object value = c.getClientProperty(property); 438 if (value instanceof Color) { 439 color = (Color) value; 440 } 441 } 442 } 443 } 444 if (color == null || color instanceof UIResource ) { 451 return defaultColor; 452 } else if (saturationOffset != 0 || brightnessOffset != 0 || alphaOffset != 0) { 453 float[] tmp = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); 454 tmp[1] = clamp(tmp[1] + saturationOffset); 455 tmp[2] = clamp(tmp[2] + brightnessOffset); 456 int alpha = clamp(color.getAlpha() + alphaOffset); 457 return new Color((Color.HSBtoRGB(tmp[0], tmp[1], tmp[2]) & 0xFFFFFF) | (alpha <<24)); 458 } else { 459 return color; 460 } 461 } 462 463 469 protected static class PaintContext { 470 protected static enum CacheMode { 471 NO_CACHING, FIXED_SIZES, NINE_SQUARE_SCALE 472 } 473 474 private static Insets EMPTY_INSETS = new Insets(0, 0, 0, 0); 475 476 private Insets stretchingInsets; 477 private Dimension canvasSize; 478 private boolean inverted; 479 private CacheMode cacheMode; 480 private double maxHorizontalScaleFactor; 481 private double maxVerticalScaleFactor; 482 483 private float a; private float b; private float c; private float d; private float aPercent; private float bPercent; private float cPercent; private float dPercent; 492 502 public PaintContext(Insets insets, Dimension canvasSize, boolean inverted) { 503 this(insets, canvasSize, inverted, null, 1, 1); 504 } 505 506 524 public PaintContext(Insets insets, Dimension canvasSize, boolean inverted, 525 CacheMode cacheMode, double maxH, double maxV) { 526 if (maxH < 1 || maxH < 1) { 527 throw new IllegalArgumentException ("Both maxH and maxV must be >= 1"); 528 } 529 530 this.stretchingInsets = insets == null ? EMPTY_INSETS : insets; 531 this.canvasSize = canvasSize; 532 this.inverted = inverted; 533 this.cacheMode = cacheMode == null ? CacheMode.NO_CACHING : cacheMode; 534 this.maxHorizontalScaleFactor = maxH; 535 this.maxVerticalScaleFactor = maxV; 536 537 if (canvasSize != null) { 538 a = insets.left; 539 b = canvasSize.width - insets.right; 540 c = insets.top; 541 d = canvasSize.height - insets.bottom; 542 this.canvasSize = canvasSize; 543 this.inverted = inverted; 544 if (inverted) { 545 float available = canvasSize.width - (b - a); 546 aPercent = available > 0f ? a / available : 0f; 547 bPercent = available > 0f ? b / available : 0f; 548 available = canvasSize.height - (d - c); 549 cPercent = available > 0f ? c / available : 0f; 550 dPercent = available > 0f ? d / available : 0f; 551 } 552 } 553 } 554 } 555 556 558 private void prepare(float w, float h) { 560 if (ctx == null || ctx.canvasSize == null) { 563 f = 1f; 564 leftWidth = centerWidth = rightWidth = 0f; 565 topHeight = centerHeight = bottomHeight = 0f; 566 leftScale = centerHScale = rightScale = 0f; 567 topScale = centerVScale = bottomScale = 0f; 568 return; 569 } 570 571 Number scale = (Number )UIManager.get("scale"); 573 f = scale == null ? 1f : scale.floatValue(); 574 575 if (ctx.inverted) { 576 centerWidth = (ctx.b - ctx.a) * f; 577 float availableSpace = w - centerWidth; 578 leftWidth = availableSpace * ctx.aPercent; 579 rightWidth = availableSpace * ctx.bPercent; 580 centerHeight = (ctx.d - ctx.c) * f; 581 availableSpace = h - centerHeight; 582 topHeight = availableSpace * ctx.cPercent; 583 bottomHeight = availableSpace * ctx.dPercent; 584 } else { 585 leftWidth = ctx.a * f; 586 rightWidth = (float)(ctx.canvasSize.getWidth() - ctx.b) * f; 587 centerWidth = w - leftWidth - rightWidth; 588 topHeight = ctx.c * f; 589 bottomHeight = (float)(ctx.canvasSize.getHeight() - ctx.d) * f; 590 centerHeight = h - topHeight - bottomHeight; 591 } 592 593 leftScale = ctx.a == 0f ? 0f : leftWidth / ctx.a; 594 centerHScale = (ctx.b - ctx.a) == 0f ? 0f : centerWidth / (ctx.b - ctx.a); 595 rightScale = (ctx.canvasSize.width - ctx.b) == 0f ? 0f : rightWidth / (ctx.canvasSize.width - ctx.b); 596 topScale = ctx.c == 0f ? 0f : topHeight / ctx.c; 597 centerVScale = (ctx.d - ctx.c) == 0f ? 0f : centerHeight / (ctx.d - ctx.c); 598 bottomScale = (ctx.canvasSize.height - ctx.d) == 0f ? 0f : bottomHeight / (ctx.canvasSize.height - ctx.d); 599 } 600 601 private void paintWith9SquareCaching(Graphics2D g, PaintContext ctx, 602 JComponent c, int w, int h, 603 Object [] extendedCacheKeys) { 604 Dimension canvas = ctx.canvasSize; 606 Insets insets = ctx.stretchingInsets; 607 608 if (w <= (canvas.width * ctx.maxHorizontalScaleFactor) && h <= (canvas.height * ctx.maxVerticalScaleFactor)) { 609 VolatileImage img = getImage(g.getDeviceConfiguration(), c, canvas.width, canvas.height, extendedCacheKeys); 611 if (img != null) { 612 Insets dstInsets; 615 if (ctx.inverted){ 616 int leftRight = (w-(canvas.width-(insets.left+insets.right)))/2; 617 int topBottom = (h-(canvas.height-(insets.top+insets.bottom)))/2; 618 dstInsets = new Insets(topBottom,leftRight,topBottom,leftRight); 619 } else { 620 dstInsets = insets; 621 } 622 Object oldScaleingHints = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION); 624 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR); 625 ImageScalingHelper.paint(g, 0, 0, w, h, img, insets, dstInsets, 626 ImageScalingHelper.PaintType.PAINT9_STRETCH, ImageScalingHelper.PAINT_ALL); 627 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 628 oldScaleingHints!=null?oldScaleingHints:RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); 629 } else { 630 paint0(g, c, w, h, extendedCacheKeys); 632 } 633 } else { 634 paint0(g, c, w, h, extendedCacheKeys); 636 } 637 } 638 639 private void paintWithFixedSizeCaching(Graphics2D g, JComponent c, int w, 640 int h, Object [] extendedCacheKeys) { 641 VolatileImage img = getImage(g.getDeviceConfiguration(), c, w, h, extendedCacheKeys); 642 if (img != null) { 643 g.drawImage(img, 0, 0, null); 645 } else { 646 paint0(g, c, w, h, extendedCacheKeys); 648 } 649 } 650 651 652 private VolatileImage getImage(GraphicsConfiguration config, JComponent c, 653 int w, int h, Object [] extendedCacheKeys) { 654 ImageCache imageCache = ImageCache.getInstance(); 655 VolatileImage buffer = (VolatileImage) imageCache.getImage(config, w, h, this, extendedCacheKeys); 657 658 int renderCounter = 0; do { 660 int bufferStatus = VolatileImage.IMAGE_INCOMPATIBLE; 662 if (buffer != null) { 663 bufferStatus = buffer.validate(config); 664 } 665 666 if (bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE || bufferStatus == VolatileImage.IMAGE_RESTORED) { 668 if (buffer == null || buffer.getWidth() != w || buffer.getHeight() != h || 671 bufferStatus == VolatileImage.IMAGE_INCOMPATIBLE) { 672 if (buffer != null) { 674 buffer.flush(); 675 buffer = null; 676 } 677 buffer = config.createCompatibleVolatileImage(w, h, 679 Transparency.TRANSLUCENT); 680 imageCache.setImage(buffer, config, w, h, this, extendedCacheKeys); 682 } 683 Graphics2D bg = buffer.createGraphics(); 685 bg.setComposite(AlphaComposite.Clear); 687 bg.fillRect(0, 0, w, h); 688 bg.setComposite(AlphaComposite.SrcOver); 689 configureGraphics(bg); 690 paint0(bg, c, w, h, extendedCacheKeys); 692 bg.dispose(); 694 } 695 } while (buffer.contentsLost() && renderCounter++ < 3); 696 if (renderCounter == 3) return null; 698 return buffer; 700 } 701 702 private void paint0(Graphics2D g, JComponent c, int width, int height, 707 Object [] extendedCacheKeys) { 708 prepare(width, height); 709 g = (Graphics2D)g.create(); 710 configureGraphics(g); 711 doPaint(g, c, width, height, extendedCacheKeys); 712 g.dispose(); 713 } 714 715 private float clamp(float value) { 716 if (value < 0) { 717 value = 0; 718 } else if (value > 1) { 719 value = 1; 720 } 721 return value; 722 } 723 724 private int clamp(int value) { 725 if (value < 0) { 726 value = 0; 727 } else if (value > 255) { 728 value = 255; 729 } 730 return value; 731 } 732 } 733 | Popular Tags |