| 1 7 8 package javax.swing; 9 10 import java.awt.*; 11 import java.awt.event.*; 12 import java.awt.image.VolatileImage ; 13 import java.awt.peer.ComponentPeer; 14 import java.applet.Applet ; 15 import javax.swing.plaf.ViewportUI ; 16 17 import javax.swing.event.*; 18 import javax.swing.border.*; 19 import javax.accessibility.*; 20 21 22 import java.io.Serializable ; 23 24 25 82 public class JViewport extends JComponent implements Accessible 83 { 84 88 private static final String uiClassID = "ViewportUI"; 89 90 92 static final Object EnableWindowBlit = "EnableWindowBlit"; 93 94 98 protected boolean isViewSizeSet = false; 99 100 104 protected Point lastPaintPosition = null; 105 106 115 @Deprecated  116 protected boolean backingStore = false; 117 118 119 transient protected Image backingStoreImage = null; 120 121 137 protected boolean scrollUnderway = false; 138 139 142 private ComponentListener viewListener = null; 143 144 149 private transient ChangeEvent changeEvent = null; 150 151 158 public static final int BLIT_SCROLL_MODE = 1; 159 160 169 public static final int BACKINGSTORE_SCROLL_MODE = 2; 170 171 181 public static final int SIMPLE_SCROLL_MODE = 0; 182 183 187 private int scrollMode = BLIT_SCROLL_MODE; 188 189 213 214 218 private transient boolean repaintAll; 219 220 227 private transient boolean waitingForRepaint; 228 229 233 private transient Timer repaintTimer; 234 235 238 private boolean hasHadValidView; 239 240 241 public JViewport() { 242 super(); 243 setLayout(createLayoutManager()); 244 setOpaque(true); 245 updateUI(); 246 } 247 248 249 250 255 public ViewportUI getUI() { 256 return (ViewportUI )ui; 257 } 258 259 260 271 public void setUI(ViewportUI ui) { 272 super.setUI(ui); 273 } 274 275 276 281 public void updateUI() { 282 setUI((ViewportUI )UIManager.getUI(this)); 283 } 284 285 286 295 public String getUIClassID() { 296 return uiClassID; 297 } 298 299 300 312 protected void addImpl(Component child, Object constraints, int index) { 313 setView(child); 314 } 315 316 317 322 public void remove(Component child) { 323 child.removeComponentListener(viewListener); 324 super.remove(child); 325 } 326 327 328 349 public void scrollRectToVisible(Rectangle contentRect) { 350 Component view = getView(); 351 352 if (view == null) { 353 return; 354 } else { 355 if (!view.isValid()) { 356 validateView(); 360 } 361 int dx = 0, dy = 0; 362 363 dx = positionAdjustment(getWidth(), contentRect.width, contentRect.x); 364 dy = positionAdjustment(getHeight(), contentRect.height, contentRect.y); 365 366 if (dx != 0 || dy != 0) { 367 Point viewPosition = getViewPosition(); 368 Dimension viewSize = view.getSize(); 369 int startX = viewPosition.x; 370 int startY = viewPosition.y; 371 Dimension extent = getExtentSize(); 372 373 viewPosition.x -= dx; 374 viewPosition.y -= dy; 375 if (view.isValid()) { 380 if (getParent().getComponentOrientation().isLeftToRight()) { 381 if (viewPosition.x + extent.width > viewSize.width) { 382 viewPosition.x = Math.max(0, viewSize.width - extent.width); 383 } else if (viewPosition.x < 0) { 384 viewPosition.x = 0; 385 } 386 } else { 387 if (extent.width > viewSize.width) { 388 viewPosition.x = viewSize.width - extent.width; 389 } else { 390 viewPosition.x = Math.max(0, Math.min(viewSize.width - extent.width, viewPosition.x)); 391 } 392 } 393 if (viewPosition.y + extent.height > viewSize.height) { 394 viewPosition.y = Math.max(0, viewSize.height - 395 extent.height); 396 } 397 else if (viewPosition.y < 0) { 398 viewPosition.y = 0; 399 } 400 } 401 if (viewPosition.x != startX || viewPosition.y != startY) { 402 setViewPosition(viewPosition); 403 scrollUnderway = false; 425 } 426 } 427 } 428 } 429 430 440 private void validateView() { 441 Component validateRoot = null; 442 443 446 for(Component c = this; c != null; c = c.getParent()) { 447 if ((c instanceof CellRendererPane ) || (c.getPeer() == null)) { 448 return; 449 } 450 if ((c instanceof JComponent ) && 451 (((JComponent )c).isValidateRoot())) { 452 validateRoot = c; 453 break; 454 } 455 } 456 457 if (validateRoot == null) { 459 return; 460 } 461 462 Component root = null; 464 465 for(Component c = validateRoot; c != null; c = c.getParent()) { 466 if (c.getPeer() == null) { 471 return; 472 } 473 if ((c instanceof Window) || (c instanceof Applet )) { 474 root = c; 475 break; 476 } 477 } 478 479 if (root == null) { 481 return; 482 } 483 484 validateRoot.validate(); 486 487 RepaintManager rm = RepaintManager.currentManager(this); 490 491 if (rm != null) { 492 rm.removeInvalidComponent((JComponent )validateRoot); 493 } 494 } 495 496 501 private int positionAdjustment(int parentWidth, int childWidth, int childAt) { 502 503 if (childAt >= 0 && childWidth + childAt <= parentWidth) { 507 return 0; 508 } 509 510 if (childAt <= 0 && childWidth + childAt >= parentWidth) { 514 return 0; 515 } 516 517 if (childAt > 0 && childWidth <= parentWidth) { 521 return -childAt + parentWidth - childWidth; 522 } 523 524 if (childAt >= 0 && childWidth >= parentWidth) { 528 return -childAt; 529 } 530 531 if (childAt <= 0 && childWidth <= parentWidth) { 535 return -childAt; 536 } 537 538 if (childAt < 0 && childWidth >= parentWidth) { 542 return -childAt + parentWidth - childWidth; 543 } 544 545 return 0; 546 } 547 548 549 564 public final void setBorder(Border border) { 565 if (border != null) { 566 throw new IllegalArgumentException ("JViewport.setBorder() not supported"); 567 } 568 } 569 570 571 578 public final Insets getInsets() { 579 return new Insets(0, 0, 0, 0); 580 } 581 582 594 public final Insets getInsets(Insets insets) { 595 insets.left = insets.top = insets.right = insets.bottom = 0; 596 return insets; 597 } 598 599 600 private Graphics getBackingStoreGraphics(Graphics g) { 601 Graphics bsg = backingStoreImage.getGraphics(); 602 bsg.setColor(g.getColor()); 603 bsg.setFont(g.getFont()); 604 bsg.setClip(g.getClipBounds()); 605 return bsg; 606 } 607 608 609 private void paintViaBackingStore(Graphics g) { 610 Graphics bsg = getBackingStoreGraphics(g); 611 try { 612 super.paint(bsg); 613 g.drawImage(backingStoreImage, 0, 0, this); 614 } finally { 615 bsg.dispose(); 616 } 617 } 618 619 private void paintViaBackingStore(Graphics g, Rectangle oClip) { 620 Graphics bsg = getBackingStoreGraphics(g); 621 try { 622 super.paint(bsg); 623 g.setClip(oClip); 624 g.drawImage(backingStoreImage, 0, 0, this); 625 } finally { 626 bsg.dispose(); 627 } 628 } 629 630 641 public boolean isOptimizedDrawingEnabled() { 642 return false; 643 } 644 645 653 boolean isPaintingOrigin() { 654 if (scrollMode == BACKINGSTORE_SCROLL_MODE) { 655 return true; 656 } 657 return false; 658 } 659 660 661 664 private Point getViewLocation() { 665 Component view = getView(); 666 if (view != null) { 667 return view.getLocation(); 668 } 669 else { 670 return new Point(0,0); 671 } 672 } 673 674 687 public void paint(Graphics g) 688 { 689 int width = getWidth(); 690 int height = getHeight(); 691 692 if ((width <= 0) || (height <= 0)) { 693 return; 694 } 695 696 if (repaintAll) { 697 repaintAll = false; 698 Rectangle clipB = g.getClipBounds(); 699 if (clipB.width < getWidth() || 700 clipB.height < getHeight()) { 701 waitingForRepaint = true; 702 if (repaintTimer == null) { 703 repaintTimer = createRepaintTimer(); 704 } 705 repaintTimer.stop(); 706 repaintTimer.start(); 707 } 710 else { 711 if (repaintTimer != null) { 712 repaintTimer.stop(); 713 } 714 waitingForRepaint = false; 715 } 716 } 717 else if (waitingForRepaint) { 718 Rectangle clipB = g.getClipBounds(); 720 if (clipB.width >= getWidth() && 721 clipB.height >= getHeight()) { 722 waitingForRepaint = false; 723 repaintTimer.stop(); 724 } 725 } 726 727 if (!backingStore || isBlitting() || getView() == null) { 728 super.paint(g); 729 lastPaintPosition = getViewLocation(); 730 return; 731 } 732 733 Rectangle viewBounds = getView().getBounds(); 738 if (!isOpaque()) { 739 g.clipRect(0, 0, viewBounds.width, viewBounds.height); 740 } 741 742 if (backingStoreImage == null) { 743 backingStoreImage = createImage(width, height); 751 Rectangle clip = g.getClipBounds(); 752 if (clip.width != width || clip.height != height) { 753 if (!isOpaque()) { 754 g.setClip(0, 0, Math.min(viewBounds.width, width), 755 Math.min(viewBounds.height, height)); 756 } 757 else { 758 g.setClip(0, 0, width, height); 759 } 760 paintViaBackingStore(g, clip); 761 } 762 else { 763 paintViaBackingStore(g); 764 } 765 } 766 else { 767 if (!scrollUnderway || lastPaintPosition.equals(getViewLocation())) { 768 paintViaBackingStore(g); 770 } else { 771 Point blitFrom = new Point(); 773 Point blitTo = new Point(); 774 Dimension blitSize = new Dimension(); 775 Rectangle blitPaint = new Rectangle(); 776 777 Point newLocation = getViewLocation(); 778 int dx = newLocation.x - lastPaintPosition.x; 779 int dy = newLocation.y - lastPaintPosition.y; 780 boolean canBlit = computeBlit(dx, dy, blitFrom, blitTo, blitSize, blitPaint); 781 if (!canBlit) { 782 paintViaBackingStore(g); 785 } else { 786 int bdx = blitTo.x - blitFrom.x; 787 int bdy = blitTo.y - blitFrom.y; 788 789 Rectangle clip = g.getClipBounds(); 791 g.setClip(0, 0, width, height); 796 Graphics bsg = getBackingStoreGraphics(g); 797 try { 798 bsg.copyArea(blitFrom.x, blitFrom.y, blitSize.width, blitSize.height, bdx, bdy); 799 800 g.setClip(clip.x, clip.y, clip.width, clip.height); 801 Rectangle r = viewBounds.intersection(blitPaint); 803 bsg.setClip(r); 804 super.paint(bsg); 805 806 g.drawImage(backingStoreImage, 0, 0, this); 808 } finally { 809 bsg.dispose(); 810 } 811 } 812 } 813 } 814 lastPaintPosition = getViewLocation(); 815 scrollUnderway = false; 816 } 817 818 819 830 public void reshape(int x, int y, int w, int h) { 831 boolean sizeChanged = (getWidth() != w) || (getHeight() != h); 832 if (sizeChanged) { 833 backingStoreImage = null; 834 } 835 super.reshape(x, y, w, h); 836 if (sizeChanged) { 837 fireStateChanged(); 838 } 839 } 840 841 842 867 public void setScrollMode(int mode) { 868 scrollMode = mode; 869 if (mode == BACKINGSTORE_SCROLL_MODE) { 870 backingStore = true; 871 } else { 872 backingStore = false; 873 } 874 } 875 876 883 public int getScrollMode() { 884 return scrollMode; 885 } 886 887 897 @Deprecated  898 public boolean isBackingStoreEnabled() { 899 return scrollMode == BACKINGSTORE_SCROLL_MODE; 900 } 901 902 903 915 @Deprecated  916 public void setBackingStoreEnabled(boolean enabled) { 917 if (enabled) { 918 setScrollMode(BACKINGSTORE_SCROLL_MODE); 919 } else { 920 setScrollMode(BLIT_SCROLL_MODE); 921 } 922 } 923 924 private final boolean isBlitting() { 925 Component view = getView(); 926 return (scrollMode == BLIT_SCROLL_MODE) && 927 (view instanceof JComponent ) && ((JComponent )view).isOpaque(); 928 } 929 930 931 938 public Component getView() { 939 try { 940 return getComponent(0); 941 } catch (ArrayIndexOutOfBoundsException e) { 942 return null; 943 } 944 } 945 946 954 public void setView(Component view) { 955 956 960 int n = getComponentCount(); 961 for(int i = n - 1; i >= 0; i--) { 962 remove(getComponent(i)); 963 } 964 965 isViewSizeSet = false; 966 967 if (view != null) { 968 super.addImpl(view, null, -1); 969 viewListener = createViewListener(); 970 view.addComponentListener(viewListener); 971 } 972 973 if (hasHadValidView) { 974 fireStateChanged(); 976 } 977 else if (view != null) { 978 hasHadValidView = true; 979 } 980 981 revalidate(); 982 repaint(); 983 } 984 985 986 993 public Dimension getViewSize() { 994 Component view = getView(); 995 996 if (view == null) { 997 return new Dimension(0,0); 998 } 999 else if (isViewSizeSet) { 1000 return view.getSize(); 1001 } 1002 else { 1003 return view.getPreferredSize(); 1004 } 1005 } 1006 1007 1008 |