1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55:
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63:
64:
105: public class JViewport extends JComponent implements Accessible
106: {
107:
112: protected class AccessibleJViewport extends AccessibleJComponent
113: {
114:
117: protected AccessibleJViewport()
118: {
119:
120: }
121:
122:
128: public AccessibleRole getAccessibleRole()
129: {
130: return AccessibleRole.VIEWPORT;
131: }
132: }
133:
134:
139: protected class ViewListener extends ComponentAdapter implements Serializable
140: {
141: private static final long serialVersionUID = -2812489404285958070L;
142:
143:
146: protected ViewListener()
147: {
148:
149: }
150:
151:
158: public void componentResized(ComponentEvent ev)
159: {
160: revalidate();
161: }
162: }
163:
164: public static final int SIMPLE_SCROLL_MODE = 0;
165: public static final int BLIT_SCROLL_MODE = 1;
166: public static final int BACKINGSTORE_SCROLL_MODE = 2;
167:
168: private static final long serialVersionUID = -6925142919680527970L;
169:
170:
174: private static final int defaultScrollMode;
175:
176: protected boolean scrollUnderway;
177: protected boolean isViewSizeSet;
178:
179:
184: protected boolean backingStore;
185:
186:
189: protected Image backingStoreImage;
190:
191:
195: protected Point lastPaintPosition;
196:
197: ChangeEvent changeEvent = new ChangeEvent(this);
198:
199: int scrollMode;
200:
201:
210: Dimension extentSize;
211:
212:
215: Dimension viewSize;
216:
217:
220: ViewListener viewListener;
221:
222:
226: Point cachedBlitFrom;
227:
228:
232: Point cachedBlitTo;
233:
234:
238: Dimension cachedBlitSize;
239:
240:
244: Rectangle cachedBlitPaint;
245:
246: boolean damaged = true;
247:
248:
253: boolean sizeChanged = true;
254:
255:
260: private boolean isPaintRoot = false;
261:
262:
265: static
266: {
267: String scrollModeProp =
268: SystemProperties.getProperty("gnu.javax.swing.JViewport.scrollMode",
269: "BLIT");
270: if (scrollModeProp.equalsIgnoreCase("simple"))
271: defaultScrollMode = SIMPLE_SCROLL_MODE;
272: else if (scrollModeProp.equalsIgnoreCase("backingstore"))
273: defaultScrollMode = BACKINGSTORE_SCROLL_MODE;
274: else
275: defaultScrollMode = BLIT_SCROLL_MODE;
276: }
277:
278: public JViewport()
279: {
280: setOpaque(true);
281: setScrollMode(defaultScrollMode);
282: updateUI();
283: setLayout(createLayoutManager());
284: lastPaintPosition = new Point();
285: cachedBlitFrom = new Point();
286: cachedBlitTo = new Point();
287: cachedBlitSize = new Dimension();
288: cachedBlitPaint = new Rectangle();
289: }
290:
291: public Dimension getExtentSize()
292: {
293: if (extentSize == null)
294: return toViewCoordinates(getSize());
295: else
296: return extentSize;
297: }
298:
299: public Dimension toViewCoordinates(Dimension size)
300: {
301: return size;
302: }
303:
304: public Point toViewCoordinates(Point p)
305: {
306: Point pos = getViewPosition();
307: return new Point(p.x + pos.x,
308: p.y + pos.y);
309: }
310:
311: public void setExtentSize(Dimension newSize)
312: {
313: extentSize = newSize;
314: fireStateChanged();
315: }
316:
317:
322: public Dimension getViewSize()
323: {
324: if (isViewSizeSet)
325: return viewSize;
326: else
327: {
328: Component view = getView();
329: if (view != null)
330: return view.getPreferredSize();
331: else
332: return new Dimension();
333: }
334: }
335:
336:
337: public void setViewSize(Dimension newSize)
338: {
339: viewSize = newSize;
340: Component view = getView();
341: if (view != null)
342: {
343: if (newSize != view.getSize())
344: {
345: view.setSize(viewSize);
346: fireStateChanged();
347: }
348: }
349: isViewSizeSet = true;
350: }
351:
352:
357:
358: public Point getViewPosition()
359: {
360: Component view = getView();
361: if (view == null)
362: return new Point(0,0);
363: else
364: {
365: Point p = view.getLocation();
366: p.x = -p.x;
367: p.y = -p.y;
368: return p;
369: }
370: }
371:
372: public void setViewPosition(Point p)
373: {
374: if (getViewPosition().equals(p))
375: return;
376: Component view = getView();
377: if (view != null)
378: {
379: Point q = new Point(-p.x, -p.y);
380: view.setLocation(q);
381: isViewSizeSet = false;
382: fireStateChanged();
383: }
384: repaint();
385: }
386:
387: public Rectangle getViewRect()
388: {
389: return new Rectangle(getViewPosition(),
390: getExtentSize());
391: }
392:
393:
396: public boolean isBackingStoreEnabled()
397: {
398: return scrollMode == BACKINGSTORE_SCROLL_MODE;
399: }
400:
401:
404: public void setBackingStoreEnabled(boolean b)
405: {
406: if (b && scrollMode != BACKINGSTORE_SCROLL_MODE)
407: {
408: scrollMode = BACKINGSTORE_SCROLL_MODE;
409: fireStateChanged();
410: }
411: }
412:
413: public void setScrollMode(int mode)
414: {
415: scrollMode = mode;
416: fireStateChanged();
417: }
418:
419: public int getScrollMode()
420: {
421: return scrollMode;
422: }
423:
424: public Component getView()
425: {
426: if (getComponentCount() == 0)
427: return null;
428:
429: return getComponents()[0];
430: }
431:
432: public void setView(Component v)
433: {
434: Component currView = getView();
435: if (viewListener != null && currView != null)
436: currView.removeComponentListener(viewListener);
437:
438: if (v != null)
439: {
440: if (viewListener == null)
441: viewListener = createViewListener();
442: v.addComponentListener(viewListener);
443: add(v);
444: fireStateChanged();
445: }
446: revalidate();
447: repaint();
448: }
449:
450: public void reshape(int x, int y, int w, int h)
451: {
452: if (w != getWidth() || h != getHeight())
453: sizeChanged = true;
454: super.reshape(x, y, w, h);
455: if (sizeChanged)
456: {
457: damaged = true;
458: fireStateChanged();
459: }
460: }
461:
462: public final Insets getInsets()
463: {
464: return new Insets(0, 0, 0, 0);
465: }
466:
467: public final Insets getInsets(Insets insets)
468: {
469: if (insets == null)
470: return getInsets();
471: insets.top = 0;
472: insets.bottom = 0;
473: insets.left = 0;
474: insets.right = 0;
475: return insets;
476: }
477:
478:
479:
486: public boolean isOptimizedDrawingEnabled()
487: {
488: return false;
489: }
490:
491: public void paint(Graphics g)
492: {
493: Component view = getView();
494:
495: if (view == null)
496: return;
497:
498: Point pos = getViewPosition();
499: Rectangle viewBounds = view.getBounds();
500: Rectangle portBounds = getBounds();
501:
502: if (viewBounds.width == 0
503: || viewBounds.height == 0
504: || portBounds.width == 0
505: || portBounds.height == 0)
506: return;
507:
508: switch (getScrollMode())
509: {
510:
511: case JViewport.BACKINGSTORE_SCROLL_MODE:
512: paintBackingStore(g);
513: break;
514: case JViewport.BLIT_SCROLL_MODE:
515: paintBlit(g);
516: break;
517: case JViewport.SIMPLE_SCROLL_MODE:
518: default:
519: paintSimple(g);
520: break;
521: }
522: damaged = false;
523: }
524:
525: public void addChangeListener(ChangeListener listener)
526: {
527: listenerList.add(ChangeListener.class, listener);
528: }
529:
530: public void removeChangeListener(ChangeListener listener)
531: {
532: listenerList.remove(ChangeListener.class, listener);
533: }
534:
535: public ChangeListener[] getChangeListeners()
536: {
537: return (ChangeListener[]) getListeners(ChangeListener.class);
538: }
539:
540:
545: public String getUIClassID()
546: {
547: return "ViewportUI";
548: }
549:
550:
553: public void updateUI()
554: {
555: setUI((ViewportUI) UIManager.getUI(this));
556: }
557:
558:
563: public ViewportUI getUI()
564: {
565: return (ViewportUI) ui;
566: }
567:
568:
573: public void setUI(ViewportUI ui)
574: {
575: super.setUI(ui);
576: }
577:
578: public final void setBorder(Border border)
579: {
580: if (border != null)
581: throw new IllegalArgumentException();
582: }
583:
584:
589: public void scrollRectToVisible(Rectangle contentRect)
590: {
591: Component view = getView();
592: if (view == null)
593: return;
594:
595: Point pos = getViewPosition();
596: Rectangle viewBounds = getView().getBounds();
597: Rectangle portBounds = getBounds();
598:
599: if (isShowing())
600: getView().validate();
601:
602:
603:
604: if (contentRect.y + contentRect.height + viewBounds.y > portBounds.height)
605: pos.y = contentRect.y + contentRect.height - portBounds.height;
606:
607:
608: if (contentRect.y + viewBounds.y < 0)
609: pos.y = contentRect.y;
610:
611:
612: if (contentRect.x + contentRect.width + viewBounds.x > portBounds.width)
613: pos.x = contentRect.x + contentRect.width - portBounds.width;
614:
615:
616: if (contentRect.x + viewBounds.x < 0)
617: pos.x = contentRect.x;
618: setViewPosition(pos);
619: }
620:
621:
627: public AccessibleContext getAccessibleContext()
628: {
629: if (accessibleContext == null)
630: accessibleContext = new AccessibleJViewport();
631: return accessibleContext;
632: }
633:
634:
644: public void repaint(long tm, int x, int y, int w, int h)
645: {
646:
647:
648:
649:
650:
651:
652:
653:
654:
655:
656:
657: super.repaint(tm, x, y, w, h);
658:
659: }
660:
661: protected void addImpl(Component comp, Object constraints, int index)
662: {
663: if (getComponentCount() > 0)
664: remove(getComponents()[0]);
665:
666: super.addImpl(comp, constraints, index);
667: }
668:
669: protected void fireStateChanged()
670: {
671: ChangeListener[] listeners = getChangeListeners();
672: for (int i = 0; i < listeners.length; ++i)
673: listeners[i].stateChanged(changeEvent);
674: }
675:
676:
682: protected ViewListener createViewListener()
683: {
684: return new ViewListener();
685: }
686:
687:
693: protected LayoutManager createLayoutManager()
694: {
695: return new ViewportLayout();
696: }
697:
698:
726: protected boolean computeBlit(int dx, int dy, Point blitFrom, Point blitTo,
727: Dimension blitSize, Rectangle blitPaint)
728: {
729: if ((dx != 0 && dy != 0) || (dy == 0 && dy == 0) || damaged)
730:
731:
732:
733:
734: return false;
735:
736: Rectangle portBounds = SwingUtilities.calculateInnerArea(this, getBounds());
737:
738:
739: blitFrom.x = portBounds.x;
740: blitFrom.y = portBounds.y;
741: blitTo.x = portBounds.x;
742: blitTo.y = portBounds.y;
743:
744: if (dy > 0)
745: {
746: blitFrom.y = portBounds.y + dy;
747: }
748: else if (dy < 0)
749: {
750: blitTo.y = portBounds.y - dy;
751: }
752: else if (dx > 0)
753: {
754: blitFrom.x = portBounds.x + dx;
755: }
756: else if (dx < 0)
757: {
758: blitTo.x = portBounds.x - dx;
759: }
760:
761:
762: if (dx != 0)
763: {
764: blitSize.width = portBounds.width - Math.abs(dx);
765: blitSize.height = portBounds.height;
766: }
767: else if (dy != 0)
768: {
769: blitSize.width = portBounds.width;
770: blitSize.height = portBounds.height - Math.abs(dy);
771: }
772:
773:
774: blitPaint.setBounds(portBounds);
775: if (dy > 0)
776: {
777: blitPaint.y = portBounds.y + portBounds.height - dy;
778: blitPaint.height = dy;
779: }
780: else if (dy < 0)
781: {
782: blitPaint.height = -dy;
783: }
784: if (dx > 0)
785: {
786: blitPaint.x = portBounds.x + portBounds.width - dx;
787: blitPaint.width = dx;
788: }
789: else if (dx < 0)
790: {
791: blitPaint.width = -dx;
792: }
793:
794: return true;
795: }
796:
797:
805: void paintSimple(Graphics g)
806: {
807:
808: paintComponent(g);
809:
810: Point pos = getViewPosition();
811: Component view = getView();
812: Shape oldClip = g.getClip();
813: g.clipRect(0, 0, getWidth(), getHeight());
814: boolean translated = false;
815: try
816: {
817: g.translate(-pos.x, -pos.y);
818: translated = true;
819: view.paint(g);
820: }
821: finally
822: {
823: if (translated)
824: g.translate (pos.x, pos.y);
825: g.setClip(oldClip);
826: }
827: }
828:
829:
839: void paintBackingStore(Graphics g)
840: {
841:
842:
843: if (backingStoreImage == null || sizeChanged)
844: {
845: backingStoreImage = createImage(getWidth(), getHeight());
846: sizeChanged = false;
847: Graphics g2 = backingStoreImage.getGraphics();
848: paintSimple(g2);
849: g2.dispose();
850: }
851:
852:
853:
854: else
855: {
856: Graphics g2 = backingStoreImage.getGraphics();
857: Point viewPosition = getViewPosition();
858: int dx = viewPosition.x - lastPaintPosition.x;
859: int dy = viewPosition.y - lastPaintPosition.y;
860: boolean canBlit = computeBlit(dx, dy, cachedBlitFrom, cachedBlitTo,
861: cachedBlitSize, cachedBlitPaint);
862: if (canBlit)
863: {
864:
865: g2.copyArea(cachedBlitFrom.x, cachedBlitFrom.y,
866: cachedBlitSize.width, cachedBlitSize.height,
867: cachedBlitTo.x - cachedBlitFrom.x,
868: cachedBlitTo.y - cachedBlitFrom.y);
869:
870: g2.setClip(cachedBlitPaint.x, cachedBlitPaint.y,
871: cachedBlitPaint.width, cachedBlitPaint.height);
872: paintSimple(g2);
873: }
874:
875:
876: else
877: {
878:
879:
880: if (dx == 0 && dy == 0)
881: g2.setClip(g.getClip());
882:
883: paintSimple(g2);
884: }
885: g2.dispose();
886: }
887:
888: g.drawImage(backingStoreImage, 0, 0, this);
889:
890:
891: lastPaintPosition.setLocation(getViewPosition());
892: }
893:
894:
904: void paintBlit(Graphics g)
905: {
906:
907:
908: Point viewPosition = getViewPosition();
909: int dx = viewPosition.x - lastPaintPosition.x;
910: int dy = viewPosition.y - lastPaintPosition.y;
911: boolean canBlit = computeBlit(dx, dy, cachedBlitFrom, cachedBlitTo,
912: cachedBlitSize, cachedBlitPaint);
913: if (canBlit && isPaintRoot)
914: {
915:
916: g.copyArea(cachedBlitFrom.x, cachedBlitFrom.y,
917: cachedBlitSize.width, cachedBlitSize.height,
918: cachedBlitTo.x - cachedBlitFrom.x,
919: cachedBlitTo.y - cachedBlitFrom.y);
920:
921: Shape oldClip = g.getClip();
922: g.clipRect(cachedBlitPaint.x, cachedBlitPaint.y,
923: cachedBlitPaint.width, cachedBlitPaint.height);
924: try
925: {
926: paintSimple(g);
927: }
928: finally
929: {
930: g.setClip(oldClip);
931: }
932: }
933:
934:
935: else
936: paintSimple(g);
937: lastPaintPosition.setLocation(getViewPosition());
938: }
939:
940:
945: void paintImmediately2(Rectangle r)
946: {
947: isPaintRoot = true;
948: super.paintImmediately2(r);
949: isPaintRoot = false;
950: }
951: }