/***************************************************************************** gui.Scroller *****************************************************************************/ package gui; import java.awt.*; /** ************************************************************************** A `wrapper' panel for containing an awt.Component (of whatever design) which can be scrolled. The Scroller provides a viewport onto the `scrolled' panel and maintains optional scrollbars.

Note that due to limitations in the awt design (and limitations in time to find workarounds) there are two notable problems with this Containter:

@author Bruce R. Miller (bruce.miller@nist.gov) @author Contribution of the National Institute of Standards and Technology, @author not subject to copyright. */ public class Scroller extends Panel implements LayoutManager { /** Indicator to show scrollbars only when the scrolled component is * too large.*/ public static final int IFNEEDED = 0; /** Indicator to always show scrollbars. */ public static final int ALWAYS = 1; /** Indicator to never show scrollbars. */ public static final int NEVER = 2; int xscrolling = IFNEEDED, yscrolling = IFNEEDED; int margin = 2; Scrollbar xscroll,yscroll; Panel clipper; Component scrolled; /** Create a Scroller panel using scrolled as the inner component to be * scrolled, and placing scrollbars only if needed. */ public Scroller(Component scrolled) { this(scrolled, IFNEEDED,IFNEEDED); } /** Create a Scroller panel using scrolled as the inner component to be * scrolled, and placing according to the given flags. */ public Scroller(Component scrolled, int xscrolling, int yscrolling) { this.scrolled = scrolled; setXScrolling(xscrolling); setYScrolling(yscrolling); GridBagLayout layout = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(layout); c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.weightx = c.weighty = 1.0; c.gridwidth = c.gridheight = GridBagConstraints.RELATIVE; layout.setConstraints(add(clipper = new Panel()),c); clipper.setLayout(this); clipper.add(scrolled); c.fill = GridBagConstraints.VERTICAL; c.weightx = c.weighty = 0.0; c.gridwidth = GridBagConstraints.REMAINDER; add(yscroll = new Scrollbar(Scrollbar.VERTICAL, 0,1,0,1)); yscroll.setLineIncrement(1); layout.setConstraints(yscroll,c); c.fill = GridBagConstraints.HORIZONTAL; c.gridwidth = GridBagConstraints.RELATIVE; c.gridheight = GridBagConstraints.REMAINDER; add(xscroll = new Scrollbar(Scrollbar.HORIZONTAL, 0,1,0,1)); xscroll.setLineIncrement(1); layout.setConstraints(xscroll,c); } /** Set the parameter for when the X (horizontal) scrollbar should be * shown.*/ public void setXScrolling(int xscrolling) { if (this.xscrolling != xscrolling) { this.xscrolling = xscrolling; //invalidate(); }} /** Set the parameter for when the Y (vertical) scrollbar should be shown.*/ public void setYScrolling(int yscrolling) { if (this.yscrolling != yscrolling) { this.yscrolling = yscrolling; // invalidate(); }} public boolean handleEvent(Event e) { if ((e.target == xscroll) || (e.target == yscroll)) { scrolled.move(-xscroll.getValue(),-yscroll.getValue()); return true; } return super.handleEvent(e); } public Insets insets() { return new Insets(margin,margin,0,0); } public void paint(Graphics g) { Dimension S = size(); g.setColor(getBackground().darker()); g.fillRect(0,0,margin,S.height); g.fillRect(0,0,S.width,margin); } /********************************************************************** Implementing Layout manager for use by clipping panel ONLY! */ public void addLayoutComponent(String name, Component comp) {} public void layoutContainer(Container parent) { if (parent != clipper) throw new IllegalArgumentException("Using Scroller as layout manager"); Dimension s = clipper.size(), S = scrolled.preferredSize(); int w = s.width, h = s.height, W = S.width, H = S.height; //int maxX = Math.max(0,W-w), maxY = Math.max(0,H-h); int maxX = W, maxY = H; int x = (xscrolling == NEVER ? 0 : Math.max(-xscroll.getValue(),-maxX)), y = (yscrolling == NEVER ? 0 : Math.max(-yscroll.getValue(),-maxY)); if ((w==0) || (h==0)) // Why this happens, no clue. (but it does!) return; scrolled.reshape(x,y, (xscrolling == NEVER ? w : W), (yscrolling == NEVER ? h : H)); if ((xscrolling == NEVER) || ((xscrolling == IFNEEDED) && (w >= W))) xscroll.hide(); else { xscroll.show(); xscroll.setValues(-x,w,0,maxX); } if ((yscrolling == NEVER) || ((yscrolling == IFNEEDED) && (h >= H))) yscroll.hide(); else { yscroll.show(); yscroll.setValues(-y,h,0,maxY); } if (isVisible()) repaint(); } public Dimension minimumLayoutSize(Container parent) { return scrolled.minimumSize(); } public Dimension preferredLayoutSize(Container parent) { return scrolled.preferredSize(); } public void removeLayoutComponent(Component comp) {} }