# The Application Kit: BInvoker

Derived from: none

Declared in: be/app/Invoker.h

Library: libbe.so

## Overview

A BInvoker is a simple object that can be "invoked" to send a message to a BHandler (the "target"). The message is set as a BMessage object (which is not copied by the BInvoker). The target is designated as...

- a handler/looper pair, or...
- a BMessenger that's been initialized to designate a handler/looper.

The muscle of a BInvoker object is its `Invoke()` function: When `Invoke()` is called, the object's message is sent to its target

BInvoker is most often used as a mix-in class. For example, BControl in the Interface Kit derives from BInvoker as well as, principally, from BView.

## Constructor and Destructor

### BInvoker()

          BInvoker(BMessage *message,
             const BHandler *handler, const BLooper *looper = NULL)
          BInvoker(BMessage *message, Messenger messenger)
          BInvoker(void)

Initializes the BInvoker with a message and sets the target where the message is to be sent when `Invoke()` is called. The target can be set as a local BHandler object, as the preferred handler of a local BLooper, or with a BMessenger object. A BMessenger can target either local or remote objects. The handler, looper, and messenger arguments passed to the constructor work precisely like identical arguments passed to `SetTarget()`. See that function for a full description of how to set the BInvoker's target.

A BInvoker doesn't have a default message or target. If a target isn't specified when constructing the object, `SetTarget()` must be called to set it. If a message isn't set, `SetMessage()` can be called to set it. However, you can also pass the BMessage to `Invoke()` each time you call it.

See also: `SetTarget()`, `SetMessage()`, `Invoke()`

### ~BInvoker()

          virtual ~BInvoker()

Frees the BMessage object.

## Member Functions

### Command() see SetMessage()

### HandlerForReply() see SetHandlerForReply()

### Invoke()

          virtual status_t Invoke(BMessage *message = NULL)

Sends the message passed as an argument--or, if the message argument is `NULL`, the message last assigned by `SetMessage()`--to the designated target. The message is sent asynchronously with no time limit (an infinite timeout).

`Invoke()` is not called for you in BInvoker code; it's designed to be called in derived or client classes when the conditions are met for taking the action encapsulated in the message. For example, a BButton object (defined in the Interface Kit) calls `Invoke()` from its `MouseDown()` and `KeyDown()` functions when the button is clicked or operated from the keyboard. It's up to each derived class to define what events trigger the call to `Invoke()`--what activity constitutes "invoking" the object.

If variable information needs to be added to the message each time it's sent--for example, the current time--it's possible to treat the message assigned to the BInvoker as a model or template for the message that actually gets sent. In this case, you need to get the message from the BInvoker, copy it, add the necessary data to the copy, and pass the copy to `Invoke()`. For example, this code adds the current time:

       BMessage copy(theInvoker->Message());
       copy.AddInt64("when", system_time());
       theInvoker->Invoke(&copy);

`Invoke()` fails and returns `B_BAD_VALUE` if a BMessage hasn't been assigned to the object and the message argument is `NULL`. Otherwise, it returns any errors encountered when sending the message. These are the same errors returned by BMessenger's `SendMessage()` function; they include `B_BAD_PORT_ID` if a target destination hasn't yet been set for the BInvoker or the one that was set has become invalid. If successful in sending the message, `Invoke()` returns `B_OK`.

See also: `SetTarget()`, `SetMessage()`

### IsTargetLocal() see SetTarget()

### Message() see SetMessage()

### Messenger() see SetTarget()

### SetHandlerForReply(), HandlerForReply()

          virtual status_t SetHandlerForReply(BHandler *replyHandler)

          BHandler *HandlerForReply(void) const

These functions set and return the BHandler object that will be responsible for handling replies to all messages the BInvoker sends. When `Invoke()` is called, the replyHandler is passed to the BMessenger's `SendMessage()` function, as follows:

       theMessenger->SendMessage(message, replyHandler);

By default, the handler for replies is `NULL`, which means that all replies will be directed to the BApplication object.

`SetHandlerForReply()` always returns `B_OK`.

See also: `BMessenger::SendMessage()`

### SetMessage(), Message(), Command()

          virtual status_t SetMessage(BMessage *message)

          BMessage *Message(void) const

          uint32 Command(void) const

`SetMessage()` assigns a message to the BInvoker, deleting any message previously assigned. The message is not copied; this function transfers ownership of the BMessage object to the BInvoker. The BInvoker will free the object when it's replaced by another message or when the BInvoker is itself freed. Passing a `NULL` message frees the current BMessage object without replacing it.

`Message()` returns a pointer to the BInvoker's message, and `Command()` returns its `what` data member. If a message has not been assigned to the BInvoker, both functions return `NULL`. (Note that `Command()` will also return 0 if that happens to be the command constant of the message.)

The message passed to `SetMessage()` and returned by `Message()` belongs to the BInvoker object; you can modify it, but you shouldn't assign it to another object or delete it (except by passing `NULL` to `SetMessage()`).

`SetMessage()` always returns `B_OK`.

See also: `Invoke()`

### SetTarget(), Target(), IsTargetLocal(), Messenger()

          virtual status_t SetTarget(const BHandler *handler, const BLooper *looper = NULL)
          virtual status_t SetTarget(BMessenger messenger)

          BHandler *Target(BLooper **looper = NULL) const

          BMessenger Messenger(void) const

          bool IsTargetLocal(void) const

These functions set the BInvoker's target--the destination of the messages it sends--and return information about the current target.

`SetTarget()` sets the target to a particular BHandler object, or to the preferred handler of a particular BLooper. It can be passed either a pointer to a BHandler handler or a `NULL` handler and a pointer to a BLooper looper; it's never necessary to specify both the handler and the looper:

- If you pass `SetTarget()` a valid target handler, the BInvoker will send messages to the BLooper associated with the handler so that the BLooper will dispatch them to that BHandler object. The target handler must be a BHandler that's known to a BLooper--that is, it must either be a BLooper itself or have been explicitly added to a BLooper's list of eligible handlers.

  To identify the BLooper where messages should be delivered, `SetTarget()` calls the handler's `Looper()` function. Therefore, it's not necessary to also pass `SetTarget()` a looper argument (other than the default `NULL`). If a BLooper is specified, it must match the object that `Looper()` returns for the handler.

- If you pass `SetTarget()` a `NULL` handler but a valid looper, the target will be the BLooper's preferred handler. This permits the targeting decision to be made dynamically. When the BInvoker sends a message to the BLooper, the BLooper will dispatch it to whatever object happens to be its preferred handler at the time.

  For example, the preferred handler of a BWindow object (in the Interface Kit) is the current focus view. Therefore, by passing a `NULL` handler and a BWindow looper to `SetTarget()`,

          theInvoker->SetTarget(NULL, someWindow);

       the BInvoker can be targeted to whatever BView happens to be in focus when the BWindow receives the message.  This is useful for actions that affect the current selection.

- For obvious reasons, the handler and looper can't both be `NULL`.

Instead of a BHandler or BLooper, you can set the target as a BMessenger object. The messenger will send messages to the BHandler and BLooper specified when it was constructed. The arguments passed to the BMessenger constructor parallel the handler and looper arguments passed to `SetTarget()`. See the BMessenger class for details.

`Target()` returns the current target BHandler and, if a looper argument is provided, fills in a pointer to the target BLooper that will receive the messages `Invoke()` sends. If the target BHandler is the preferred handler of the BLooper, `Target()` returns `NULL`. It also returns `NULL` if a target hasn't been set yet.

`Target()` provides the target BHandler and BLooper whether they were set directly, indirectly (where one of the objects is inferred from the other), or through a BMessenger object. However, it can only identify objects that are local to the application. If the BMessenger has a remote target, `Target()` returns `NULL` and sets the pointer referred to by looper to `NULL`, as it would if a target wasn't set. `IsTargetLocal()` can distinguish these cases; it returns `true` if the BInvoker and its target are in the same team, and `false` if they're in different address spaces.

`Messenger()` returns the BMessenger object the BInvoker uses to send its messages. This may be the messenger passed to `SetTarget()` or an object the BInvoker constructs for itself. If a target hasn't been set yet, the returned BMessenger will be invalid.

When successful, `SetTarget()` returns `B_OK`. It fails and returns `B_BAD_VALUE` if the proposed target handler isn't associated with a BLooper. It also fails if a handler and a specific looper are both named but the handler is associated with some other BLooper object. In this case, it returns `B_MISMATCHED_VALUES` to indicate that there's a conflict between the two arguments. `SetTarget()` doesn't detect invalid BLoopers and BMessengers.

### Target() see SetTarget()

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

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.