# The Interface Kit: BControl

Derived from: public BView, public BInvoker

Declared in: be/interface/Control.h

Library: libbe.so

## Overview

BControl is an abstract class for views that draw control devices on the screen. Objects that inherit from BControl emulate, in software, real-world control devices--like the switches and levers on a machine, the check lists and blank lines on a form to fill out, or the dials and knobs on a home appliance.

Controls translate the messages that report generic mouse and keyboard events into other messages with more specific instructions for the application. A BControl object can be customized by setting the message it posts when invoked and the target object that should handle the message.

Controls also register a current value, stored as an `int32` integer that's typically set to `B_CONTROL_ON` or `B_CONTROL_OFF`. The value is changed only by calling `SetValue()`, a virtual function that derived classes can implement to be notified of the change.

### Derived Classes

The Interface Kit currently includes six classes derived from BControl--BButton, BPictureButton, BRadioButton, BCheckBox, BColorControl, and BTextControl. In addition, it has two classes--BListView and BMenuItem--that implement control devices but are not derived from this class. BListView and its subclass, BOutlineListView, share an interface with the BList class (of the Support Kit) and BMenuItem is designed to work with the other classes in the menu system. Like BControl, BListView and BMenuItem inherit from the Application Kit's BInvoker class.

As BListView and BMenuItem demonstrate, it's possible to implement a control device that's not a BControl. However, it's simpler to take advantage of the code that's already provided by the BControl class. That way you can keep a simple programming interface and avoid reimplementing functions that BControl has defined for you. If your application defines its own control devices--dials, sliders, selection lists, and the like--they should be derived from BControl.

## Hook Functions

`SetEnabled()`
Enables and disables the control device; can be augmented by derived classes to note when the state of the object has changed.

`SetValue()`
Changes the value of the control device; can be augmented to take collateral action when the change is made.

## Constructor and Destructor

### BControl()

          BControl(BRect frame, const char *name,
             const char *label, BMessage *message,
             uint32 resizingMode, uint32 flags)
          BControl(BMessage *archive)

Initializes the BControl by setting its initial value to 0 (`B_CONTROL_OFF`), assigning it a label, and registering a model message that captures what the control does--the command it gives when it's invoked and the information that accompanies the command. The label and the message can each be `NULL`.

The label is copied, but the message is not. The BMessage object becomes the property of the BControl; it should not be deleted, posted, assigned to another object, or otherwise used in application code. The label and message can be altered after construction with the `SetLabel()` and `SetMessage()` functions.

The BControl class doesn't define a `Draw()` function to draw the label or a `MouseDown()` function to post the message. (It does define `KeyDown()`, but only to enable keyboard navigation between controls.) It's up to derived classes to determine how the label is drawn and how the message is to be used. Typically, when a BControl object needs to take action (in response to a click, for example), it calls the `Invoke()` function, which copies the model message and delivers the copy to the designated target. By default, the target is the window where the control is located, but `SetTarget()` can designate another handler.

Before delivering the message, `Invoke()` adds two data field to it, under the names "when" and "source". These names should not be used for data items in the model.

The frame, name, resizingMode, and flags arguments are identical to those declared for the BView class and are passed unchanged to the BView constructor.

The BControl begins life enabled, and the system plain font is made the default font for all control devices.

See also: the BView constructor, `BLooper::PostMessage()` in the Application Kit, `SetLabel()`, `SetMessage()`, `SetTarget()`, `Invoke()`

### ~BControl()

          virtual ~BControl()

Frees the model message and all memory allocated by the BControl.

## Static Functions

### Instantiate()

          static BControl *Instantiate(BMessage *archive)

Returns a new BControl object, allocated by `new` and created with the version of the constructor that takes a BMessage archive. However, if the archive doesn't contain data for a BControl object, `Instantiate()` returns `NULL`.

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

## Member Functions

### Archive()

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

Archives the BControl by recording its label, current value, model message, and whether or not it's disabled in the BMessage archive.

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

### AttachedToWindow()

          virtual void AttachedToWindow(void)

Overrides BView's version of this function to set the BControl's low color and view color so that it matches the view color of its new parent. It also makes the BWindow to which the BControl has become attached the default target for the `Invoke()` function, provided that another target hasn't already been set.

`AttachedToWindow()` is called for you when the BControl becomes a child of a view already associated with the window.

See also: `BView::AttachedToWindow()`, `BView::SetFontName()`, `Invoke()`, `SetTarget()`

### GetSupportedSuites()

          virtual status_t GetSupportedSuites(BMessage *message)

Adds the name "suite/vnd.Be-control" to the message. See Scripting Support in the class overview and the "Scripting" section in The Application Kit chapter for more information.

See also: `BHandler::GetSupportedSuites()`

### Invoke()

          virtual status_t Invoke(BMessage *message = NULL)

Copies the BControl's model BMessage and sends the copy so that it will be dispatched to the designated target (which may be a BLooper's preferred handler). The following two pieces of information are added to the copy before it's delivered:

Data name | Type code | Description
"when" | `B_INT64_TYPE` | When the control was invoked, as measured in the number of milliseconds since 12:00:00 AM January 1, 1970.
"source" | `B_OBJECT_TYPE` | A pointer to the BControl object. This permits the message handler to request more information from the source of the message.

These two names shouldn't be used for data fields in the model.

BControl's version of `Invoke()` overrides the version that the BInvoker class defines. It's designed to be called by derived classes in their `MouseDown()` and `KeyDown()` functions; it's not called for you in BControl code. It's up to each derived class to define what user actions trigger the call to `Invoke()`--what activity constitutes "invoking" the control.

This function doesn't check to make sure the BControl is currently enabled. Derived classes should make that determination before calling `Invoke()`.

See also: `BInvoker::Invoke()`, `SetEnabled()`

### IsEnabled() see SetEnabled()

### IsFocusChanging()

          bool IsFocusChanging(void) const

Returns `true` if the BControl is being asked to draw because the focus changed, and `false` if not. If the return value is `true`, either the BControl has just become the focus view or it has just lost that status and the `Draw()` function has been called to update the on-screen display.

This function can be called from inside `Draw()` to learn whether it's necessary to draw or erase the visible indication that the BControl is the focus view. `IsFocus()` will return the new status of the view.

See also: `MakeFocus()`

### KeyDown()

          virtual void KeyDown(const char *bytes, int32 numBytes)

Augments the BView version of `KeyDown()` to toggle the BControl's value and call `Invoke()` when the character encoded in bytes is either `B_SPACE` or `B_ENTER`. This is done to facilitate keyboard navigation and make all derived control devices operable from the keyboard. Some derived classes--BCheckBox in particular--find this version of the function to be adequate. Others, like BRadioButton, reimplement it.

`KeyDown()` is called only when the BControl is the focus view in the active window. (However, if the window has a default button, `B_ENTER` events will be passed to that object and won't be dispatched to the focus view.)

See also: `BView::KeyDown()`, `MakeFocus()`

### Label() see SetLabel()

### MakeFocus()

          virtual void MakeFocus(bool focused = true)

Augments the BView version of this function to call the BControl's `Draw()` function when the focus changes. This is done to aid keyboard navigation among control devices. If the `Draw()` function of a derived class has a section of code that checks whether the object is in focus and marks the on-screen display to show that it is (and removes any such marking when it isn't), the visual part of keyboard navigation will be taken care of. The derived class doesn't have to reimplement `MakeFocus()`. Most of the derived classes implemented in the Interface Kit depend on this version of the function.

When `Draw()` is called from this function, `IsFocusChanging()` returns `true`.

See also: `BView::MakeFocus()`, `KeyDown()`, `IsFocusChanging()`

### MessageReceived()

          virtual void MessageReceived(BMessage *message)

Handles scripting messages for the BControl. See Scripting Support for a description of the messages.

See also: `BHandler::MessageReceived()`

### ResolveSpecifier()

          virtual BHandler *ResolveSpecifier(BMessage *message, int32 index, BMessage *specifier, int32 command, const char *property)

Resolves specifiers for the "Label" and "Value" properties. See Scripting Support in the class overview and the "Scripting" section of The Application Kit chapter for more information.

See also: `BHandler::ResolveSpecifier()`

### SetEnabled(), IsEnabled()

          virtual void SetEnabled(bool enabled)

          bool IsEnabled(void) const

`SetEnabled()` enables the BControl if the enabled flag is `true`, and disables it if enabled is `false`. `IsEnabled()` returns whether or not the object is currently enabled. BControls are enabled by default.

While disabled, a BControl won't let the user navigate to it; the `B_NAVIGABLE` flag is turned off if enabled is `false` and turned on again if enabled is `true`.

Typically, a disabled BControl also won't post messages or respond visually to mouse and keyboard manipulation. To indicate this nonfunctional state, the control device is displayed on-screen in subdued colors. However, it's left to each derived class to carry out this strategy in a way that's appropriate for the kind of control it implements. The BControl class merely marks an object as being enabled or disabled; none of its functions take the enabled state of the device into account.

Derived classes can augment `SetEnabled()` (override it) to take action when the control device becomes enabled or disabled. To be sure that `SetEnabled()` has been called to actually make a change, its current state should be checked before calling the inherited version of the function. For example:

       void MyControl::SetEnabled(bool enabled)
       {
           if ( enabled == IsEnabled() )
               return;
           BControl::SetEnabled(enabled);
           /* Code that responds to the change in state goes here. */
       }

Note, however, that you don't have to override `SetEnabled()` just to update the on-screen display when the control becomes enabled or disabled. If the BControl is attached to a window, the kit's version of `SetEnabled()` always calls the `Draw()` function. Therefore, the device on-screen will be updated automatically--as long as `Draw()` has been implemented to take the enabled state into account.

See also: the BControl constructor

### SetLabel(), Label()

          virtual void SetLabel(const char *string)

          const char *Label(void) const

These functions set and return the label on a control device--the text that's displayed, for example, on top of a button or alongside a check box or radio button. The label is a null-terminated string.

`SetLabel()` frees the old label, replaces it with a copy of string, and updates the control on-screen so the new label will be displayed to the user--but only if the string that's passed differs from the current label. The label is first set by the constructor and can be modified thereafter by this function.

`Label()` returns the current label. The string it returns belongs to the BControl and may be altered or freed in due course.

See also: the BControl constructor, `BView::AttachedToWindow()`, `BView::SetFontName()`

### SetValue(), Value()

          virtual void SetValue(int32 value)

          int32 Value(void) const

These functions set and return the value of the BControl object.

`SetValue()` assigns the object a new value. If the value passed is in fact different from the BControl's current value, this function calls the object's `Draw()` function so that the new value will be reflected in what the user sees on-screen; otherwise it does nothing.

`Value()` returns the current value.

Classes derived from BControl should call `SetValue()` to change the value of the control device in response to user actions. The derived classes defined in the Be software kits change values only by calling this function.

Since `SetValue()` is a virtual function, you can override it to take note whenever a control's value changes. However, if you want your code to act only when the value actually changes, you must check to be sure the new value doesn't match the old before calling the inherited version of the function. For example:

       void MyControl::SetValue(int32 value)
       {
           if ( value != Value() ) {
               BControl::SetValue(value);
               /* MyControl's additions to SetValue() go here */
           }
       }

Remember that the BControl version of `SetValue()` does nothing unless the new value differs from the old.

### Value() see SetValue()

### WindowActivated()

          virtual void WindowActivated(bool active)

Makes sure that the BControl, if it's the focus view, is redrawn when the window is activated or deactivated.

See also: `BView::WindowActivated()`

## Scripting Support

The BControl class implements the suite called "suite/vnd.Be-control" consisting of the following messages:

### The Enabled Property

Message | Specifiers | Meaning
`B_GET_PROPERTY` | `B_DIRECT_SPECIFIER` | Returns whether or not the BControl is currently enabled.
`B_SET_PROPERTY` | `B_DIRECT_SPECIFIER` | Enables or disables the BControl.

The "Enabled" property corresponds to the methods `IsEnabled()` and `SetEnabled()`, using a boolean to store the data.

### The Label Property

Message | Specifiers | Meaning
`B_GET_PROPERTY` | `B_DIRECT_SPECIFIER` | Returns the BControl's label.
`B_SET_PROPERTY` | `B_DIRECT_SPECIFIER` | Sets the label of the BControl.

The "Label" property corresponds to the methods `Label()` and `SetLabel()`, using a string to store the data.

### The Value Property

Message | Specifiers | Meaning
`B_GET_PROPERTY` | `B_DIRECT_SPECIFIER` | Returns the BControl's value.
`B_SET_PROPERTY` | `B_DIRECT_SPECIFIER` | Sets the value of the BControl.

The "Value" property corresponds to the methods `Value()` and `SetValue()`, using an int32 to store the data.

## Archived Fields

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

Field | Type code | Meaning
"_msg" | `B_MESSAGE_TYPE` | The BControl's modal invocation message.
"_label" | `B_STRING_TYPE` | The BControl's label.
"_val" | `B_INT32_TYPE` | The BControl's value.
"_disable" | `B_BOOL_TYPE` | `true` if the control is disabled.

Some of these fields may not be present if the setting they represent isn't used, or is the default value. For example, if the value is 0, the "_val" field won't be found in the archive.

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

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.