| Using Components, the GUI Building Blocks

## How to Use Scrollbars

> Scrollbars have two uses:
> - A scrollbar can act as a slider that the user manipulates to set a value. An example of this is in the Converter program in The Anatomy of a a GUI-Based Program.
> - Scrollbars can help you display part of a region that's too large for the available display area. Scrollbars let the user choose exactly which part of the region is visible. Here's an example (it might take a minute for the image to load):

> To create a scrollbar, you need to create an instance of the Scrollbar class. You must also initialize the following values, either by specifying them to a Scrollbar constructor or by calling the `setValues()` method before the scrollbar is visible.
> `int orientation`
>   Indicates whether the scrollbar should be horizontal or vertical. Specified with either `Scrollbar.HORIZONTAL` or `Scrollbar.VERTICAL`.
> `int value`
>   The initial value of the scrollbar. For scrollbars that control a scrollable area, this usually means the x value (for horizontal scrollbars) or y value (for vertical scrollbars) of the part of the area that's visible when the user first sees the scrollable area. For example, when the applet above starts up, both the horizontal and vertical scrollbars' values are 0, and the image portion that's displayed starts at (0,0).
> `int visible`
>   The size in pixels of the visible portion of the scrollable area. This value, if set before the scrollbar is visible, determines how many pixels a click in the scrollbar (but not on the knob) causes the display area to shift. Setting this value after the scrollbar is visible has no effect. After the scrollbar is visible, you should use the `setPageIncrement()` method to get the same effect.
> `int minimum`
>   The minimum value the scrollbar can have. For scrollbars controlling scrollable areas, this value is usually 0 (the left/upper part of the area).
> `int maximum`
>   The maximum value the scrollbar can have. For scrollbars controlling scrollable areas, this value is usually: (total width/height, in pixels, of the component that's being partially displayed) - (currently visible width/height of the scrollable area).
> Here's a figure that illustrates the meaning of the above values:

> Here's the code for the above applet. The code defines two classes. The first is a simple Canvas subclass (ScrollableCanvas) that draws an image. The second is a Panel subclass (ImageScroller, which actually extends Applet) that creates and contains a ScrollableCanvas and two Scrollbars. This program illustrates a few important details of managing a scrollable area:

> - Event handling for a scrollbar is pretty straightforward. The program must merely respond to scrolling events by saving the scrollbar's new value in a place accessible to the Component that displays itself within the scrollable area, and then invoke `repaint()` on the Component.

>   >     public boolean handleEvent(Event evt) {
>   >         switch (evt.id) {
>   >           case Event.SCROLL_LINE_UP:
>   >           case Event.SCROLL_LINE_DOWN:
>   >           case Event.SCROLL_PAGE_UP:
>   >           case Event.SCROLL_PAGE_DOWN:
>   >           case Event.SCROLL_ABSOLUTE:
>   >             if (evt.target == vert) {
>   >                 canvas.ty = ((Integer)evt.arg).intValue();
>   >                 canvas.repaint();
>   >             }
>   >             if (evt.target == horz) {
>   >                 canvas.tx = ((Integer)evt.arg).intValue();
>   >                 canvas.repaint();
>   >             }
>   >         }
>   >         return super.handleEvent(evt);
>   >     }

> - The Component that displays itself within the scrollable area can be very simple. All it needs to do is draw itself at the origin specified by the values from its controlling scrollbars. A Component can change its origin (and thus not have to change its normal drawing code) by putting code such as the following at the beginning of its `paint()` or `update()` method:

>   >     g.translate(-tx, -ty);

> - While scrolling occurs, you'll probably notice flashing, or flickering, in the display area. If you don't want this to occur, you'll need to implement the `update()` method in the displayed Component, and possibly double buffering as well. How to do this is discussed in Eliminating Flashing.

> - If your scrolling area is resizable, beware of a common scrolling problem. It occurs when the user scrolls to the right/bottom of the area and then enlarges the area. If you aren't careful, the scrolling area will display a blank space at its right/bottom. After the user scrolls and then returns to the right/bottom, the blank space will no longer be there. To avoid displaying a blank space unnecessarily, when the scrollable area's size becomes larger you should shift the Component's origin so that it takes advantage of the available new space. Here's an example:

>   >     int canvasWidth = canvas.size().width;

>   >     //Shift everything to the right if we're displaying empty space
>   >     //on the right side.
>   >     if ((canvas.tx + canvasWidth) > imageSize.width) {
>   >         int newtx = imageSize.width - canvasWidth;
>   >         if (newtx < 0) {
>   >                     newtx = 0;
>   >         }
>   >         canvas.tx = newtx;
>   >     }

>   Here's a figure that illustrates the scrolling problem and its fix:

| Using Components, the GUI Building Blocks