# The Interface Kit: BScrollBar

Derived from: public BView

Declared in: be/interface/ScrollBar.h

Library: libbe.so

## Overview

A BScrollBar object displays a vertical or horizontal scroll bar that users can operate to scroll the contents of another view, a target view. Scroll bars usually are grouped as siblings of the target view under a common parent. That way, when the parent is resized, the target and scroll bars can be automatically resized to match. (A companion class, BScrollView, defines just such a container view; a BScrollView object sets up the scroll bars for a target view and makes itself the parent of the target and the scroll bars.)

### The Update Mechanism

BScrollBars are different from other views in one important respect: All their drawing and event handling is carried out within the Application Server, not in the application. A BScrollBar object doesn't receive `Draw()` or `MouseDown()` notifications; the server intercepts updates and interface messages that would otherwise be reported to the BScrollBar and handles them itself. As the user moves the knob on a scroll bar or presses a scroll arrow, the Application Server continuously refreshes the scroll bar's image on-screen and informs the application with a steady stream of `B_VALUE_CHANGED` messages.

The window dispatches these messages by calling the BScrollBar's `ValueChanged()` function. Each function call notifies the BScrollBar of a change in its value and, consequently, of a need to scroll the target view.

Confining the update mechanism for scroll bars to the Application Server limits the volume of communication between the application and server and enhances the efficiency of scrolling. The application's messages to the server can concentrate on updating the target view as its contents are being scrolled, rather than on updating the scroll bars themselves.

### Value and Range

A scroll bar's value determines what the target view displays. The assumption is that the left coordinate value of the target view's bounds rectangle should match the value of the horizontal scroll bar, and the top of the target view's bounds rectangle should match the value of the vertical scroll bar. When a BScrollBar is notified of a change of value (through `ValueChanged()`), it calls the target view's `ScrollTo()` function to put the new value at the left or top of the bounds rectangle.

The value reported in a `ValueChanged()` notification and passed to `ScrollTo()` depends on where the user moves the scroll bar's knob and on the range of values the scroll bar represents. The range is first set in the BScrollBar constructor and can be modified by the `SetRange()` function.

The range must be large enough to bring all the coordinate values where the target view can draw into its bounds rectangle. If everything the target view can draw is conceived as being enclosed in a "data rectangle," the range of a horizontal scroll bar must extend from a minimum that makes the left side of the target's bounds rectangle coincide with the left side of its data rectangle, to a maximum that puts the right side of the bounds rectangle at the right side of the data rectangle. This is illustrated in part below:

As this illustration helps demonstrate, the maximum value of a horizontal scroll bar can be no less than the right coordinate value of the data rectangle minus the width of the bounds rectangle. Similarly, for a vertical scroll bar, the maximum value can be no less than the bottom coordinate of the data rectangle minus the height of the bounds rectangle. The range of a scroll bar subtracts the dimensions of the target's bounds rectangle from its data rectangle. (The minimum values of horizontal and vertical scroll bars can be no greater than the left and top sides of the data rectangle.)

What the target view can draw may change from time to time as the user adds or deletes data. As this happens, the range of the scroll bar should be updated with the `SetRange()` function. The range may also need to be recalculated when the target view is resized.

### Coordination

Scroll bars control the target view, but a target can also be scrolled without the intervention of its scroll bars (by calling `ScrollTo()` or `ScrollBy()` directly). Therefore, not only must a scroll bar know about its target, but a target view must know about its scroll bars. When a BScrollBar sets its target, the target BView is notified and records the identity of the BScrollBar.

The two objects communicate whenever the display changes: When the scroll bar is the instrument that initiates scrolling, `ValueChanged()` calls the target view's `ScrollTo()` function. To cover cases of target-initiated scrolling, `ScrollTo()` calls the BScrollBar's `SetValue()` function so that the scroll bars can be updated on-screen. `SetValue()` in turn calls `ValueChanged()`, which makes sure the exchange of function calls doesn't get too circular.

### Scroll Bar Options

Users have control over some aspects of how scroll bars look and behave. With the ScrollBar preferences application, they can choose:

- Whether the knob should be a fixed size, or whether it should grow and shrink to proportionally represent how much of a document (how much of the data rectangle) is visible within the target view. A proportional knob is the default.

- Whether double, bidirectional scroll arrows should appear on each end of the scroll bar, or whether each end should have only a single, unidirectional arrow. Double arrows are the default.

- Which of three patterns should appear on the knob.

- What the size of the knob should be--the minimum length of a proportional knob or the fixed length of a knob that's not proportional. The default length is 15 pixels.

  When this class constructs a new BScrollBar, it conforms the object to the choices the user has made.

  See also: `set_scroll_bar_info()`, `BView::ScrollBar()`, the BScrollView class

  ## Hook Functions

  `ValueChanged()`
  Scrolls the target view when the BScrollBar is informed that its value has changed; can be augmented to coordinate other activities with the change in value..

  ## Constructor and Destructor

  ### BScrollBar()

            BScrollBar(BRect frame, const char *name, BView *target,
               float min, float max, orientation posture)
            BScrollBar(BMessage *archive)

  Initializes the BScrollBar and connects it to the target view that it will scroll. It will be a horizontal scroll bar if posture is `B_HORIZONTAL` and a vertical scroll bar if posture is `B_VERTICAL`.

  The range of values that the scroll bar can represent at the outset is set by min and max. These values should be calculated from the boundaries of a rectangle that encloses the entire contents of the target view--everything that it can draw. If min and max are both 0, the scroll bar is disabled and the knob is not drawn.

  The object's initial value is 0 even if that falls outside the range set for the scroll bar.

  The other arguments, frame and name, are the same as for other BViews:

  - The frame rectangle locates the scroll bar within its parent view. For consistency in the user interface, a horizontal scroll bar should be `B_H_SCROLL_BAR_HEIGHT` coordinate units high, and a vertical scroll bar should be `B_V_SCROLL_BAR_WIDTH` units wide.

  - The BScrollBar's name identifies it and permits it to be located by the `FindView()` function. It can be `NULL`.

  Unlike other BViews, the BScrollBar constructor doesn't set an automatic resizing mode. By default, scroll bars have the resizing behavior that befits their posture--horizontal scroll bars resize themselves horizontally (as if they had a resizing mode that combined `B_FOLLOW_LEFT_RIGHT` with `B_FOLLOW_BOTTOM`) and vertical scroll bars resize themselves vertically (as if their resizing mode combined `B_FOLLOW_TOP_BOTTOM` with `B_FOLLOW_RIGHT`).

  ### ~BScrollBar()

            virtual ~BScrollBar()

  Disconnects the scroll bar from its target.

  ## Static Functions

  ### Instantiate()

            static BScrollBar *Instantiate(BMessage *archive)

  Returns a new BScrollBar object, allocated by `new` and created with the version of the constructor that takes a BMessage archive. However, if the archive message doesn't contain data for a BScrollBar object, the return value will be `NULL`.

  See also: `BArchivable::Instantiate()`, `instantiate_object()`, `Archive()`

  ## Member Functions

  ### Archive()

            virtual status_t Archive(BMessage *archive, bool deep = true) const

  Calls the inherited version of `Archive()`, then adds the BScrollBar's range, orientation, current value and proportion, and the size of its big and little steps to the BMessage archive.

  See also: `BArchivable::Archive()`, `Instantiate()` static function

  ### AttachedToWindow()

            virtual void AttachedToWindow(void)

  Makes sure that the Application Server is cognizant of the BScrollBar's value, if a value was set before the object was attached to a window.

  See also: `BHandler::AttachedToWindow()`

  ### GetRange() see SetRange()

  ### GetSteps() see SetSteps()

  ### Orientation()

            orientation Orientation(void) const

  Returns `B_HORIZONTAL` if the object represents a horizontal scroll bar and `B_VERTICAL` if it represents a vertical scroll bar.

  See also: the BScrollBar constructor

  ### SetProportion(), Proportion()

            void SetProportion(float ratio)

            float Proportion(void) const

  These functions set and return a value between 0.0 and 1.0 that represents the proportion of the entire document that can be displayed within the target view--the ratio of the width (or height) of the target's bounds rectangle to the width (or height) of its data rectangle. This ratio determines the size of a proportional scroll knob relative to the whole scroll bar. It's not adjusted to take into account the minimum size of the knob.

  The proportion should be reset as the size of the data rectangle changes (as data is entered and removed from the document) and when the target view is resized.

  ### SetRange(), GetRange()

            void SetRange(float min, float max)

            void GetRange(float *min, float *max) const

  These functions modify and return the range of the scroll bar. `SetRange()` sets the minimum and maximum values of the scroll bar to min and max. `GetRange()` places the current minimum and maximum in the variables that min and max refer to.

  If the scroll bar's current value falls outside the new range, it will be reset to the closest value--either min or max--within range. `ValueChanged()` is called to inform the BScrollBar of the change whether or not it's attached to a window.

  If the BScrollBar is attached to a window, any change in its range will be immediately reflected on-screen. The knob will move to the appropriate position to reflect the current value.

  Setting both the minimum and maximum to 0 disables the scroll bar. It will be drawn without a knob.

  See also: the BScrollBar constructor

  ### SetSteps(), GetSteps()

            void SetSteps(float smallStep, float bigStep)

            void GetSteps(float *smallStep, float *bigStep) const

  `SetSteps()` sets how much a single user action should change the value of the scroll bar--and therefore how far the target view should scroll. `GetSteps()` provides the current settings.

  When the user presses one of the scroll arrows at either end of the scroll bar, its value changes by a smallStep coordinate units. When the user clicks in the bar itself (other than on the knob), it changes by a bigStep units. For an application that displays text, the small step of a vertical scroll bar should be large enough to bring another line of text into view.

  The default small step is 1.0, which should be too small for most purposes; the default large step is 10.0, which is also probably too small.

  Currently, a BScrollBar's steps can be successfully set only after it's attached to a window.

  See also: `ValueChanged()`

  ### SetTarget(), Target()

            void SetTarget(BView *view)
            void SetTarget(const char *name)

            BView *Target(void) const

  These functions set and return the target of the BScrollBar, the view that the scroll bar scrolls. `SetTarget()` sets the target to view, or to the BView identified by name. `Target()` returns the current target view. The target can also be set when the BScrollBar is constructed.

  `SetTarget()` can be called either before or after the BScrollBar is attached to a window. If the target is set by name, the named view must eventually be found within the same window as the scroll bar. Typically, the target and its scroll bars are children of a container view that serves to bind them together as a unit.

  When the target is successfully set, a pointer to the BScrollBar object is passed to the target view. This lets the target update its scroll bars when its contents are scrolled.

  See also: the BScrollBar constructor, `ValueChanged()`, `BView::ScrollBar()`

  ### SetValue(), Value()

            void SetValue(float value)

            float Value(void) const

  These functions modify and return the value of the scroll bar. The value is usually set as the result of user actions; `SetValue()` provides a way to do it programmatically. `Value()` returns the current value, whether set by `SetValue()` or by the user.

  `SetValue()` assigns a new value to the scroll bar and calls the `ValueChanged()` hook function, whether or not the new value is really a change from the old. If the value passed lies outside the range of the scroll bar, the BScrollBar is reset to the closest value within range--that is, to either the minimum or the maximum value previously specified.

  If the scroll bar is attached to a window, changing its value updates its on-screen display. The call to `ValueChanged()` enables the object to scroll the target view so that it too is updated to conform to the new value.

  The initial value of a scroll bar is 0.

  See also: `ValueChanged()`, `SetRange()`

  ### Target() see SetTarget()

  ### Value() see SetValue()

  ### ValueChanged()

            virtual void ValueChanged(float newValue)

  Responds to a notification that the value of the scroll bar has changed to newValue. For a horizontal scroll bar, this function interprets newValue as the coordinate value that should be at the left side of the target view's bounds rectangle. For a vertical scroll bar, it interprets newValue as the coordinate value that should be at the top of the rectangle. It calls `ScrollTo()` to scroll the target's contents into position, unless they have already been scrolled.

  `ValueChanged()` is called as the result both of user actions (`B_VALUE_CHANGED` messages received from the Application Server) and of programmatic ones. Programmatically, scrolling can be initiated by the target view (calling `ScrollTo()`) or by the BScrollBar (calling `SetValue()` or `SetRange()`).

  In all these cases, the target view and the scroll bars need to be kept in synch. This is done by a chain of function calls: `ValueChanged()` calls `ScrollTo()`, which in turn calls `SetValue()`, which then calls `ValueChanged()` again. It's up to `ValueChanged()` to get off this merry-go-round, which it does by checking the target view's bounds rectangle. If newValue already matches the left or top side of the bounds rectangle, if forgoes calling `ScrollTo()`.

  `ValueChanged()` does nothing if a target BView hasn't been set--or if the target has been set by name, but the name doesn't correspond to an actual BView within the scroll bar's window.

  Derived classes can override this function to interpret newValue differently, or to do something in addition to scrolling the target view.

  See also: `SetTarget()`, `SetValue()`, `BView::ScrollTo()`

  ## Archived Fields

  The `Archive()` function adds the following fields to its BMessage argument:

  Field | Type code | Meaning
  "_range" (array) | `B_FLOAT_TYPE` | Minimum and maximum values of the scroll bar.
  "_steps" (array) | `B_FLOAT_TYPE` | Small and large steps of the scroll bar.
  "_val" | `B_FLOAT_TYPE` | Current value of the scroll bar.
  "_orient" | `B_INT32_TYPE` | Orientation of the scroll bar.
  "_prop" | `B_FLOAT_TYPE` | Proportion of the document visible in the target view.

  The Be Book, in lovely HTML, for BeOS Release 3.

  Copyright © 1998 Be, Inc. All rights reserved.

  Last modified March 26, 1998.