The Application Kit: BInvoker

The Application Kit Table of Contents | The Application Kit Index

# BInvoker

Derived from: none

Declared in: be/app/Invoker.h

Library: libbe.so

###### Summary

BInvoker is a convenience class that bundles up everything you need to create a handy message-sending package. The BInvoker contains: (a) a BMessage, (b) a BMessenger (that identifies a target handler), and (c) an optional BHandler that handles replies. You set these ingredients, invoke `Invoke()`, and off goes the message to the target. Replies are sent to the reply handler (`be_app` by default).

BInvoker uses `BMessenger::SendMessage()` to send its messages. The invocation is asynchronous, and there's no time limit on the reply.

BInvoker is mostly used as a mix-in class. A number of classes in the Interface Kit—notably BControl—derive from BInvoker.

## Constructor and Destructor

### BInvoker()

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

Initializes the BInvoker by setting its message and its messenger.

- The object's BMessage is taken directly as message—the object is not copied. The BInvoker takes over ownership of the BMessage that you pass in.

- The object's BMessenger is copied from messenger, or initialized with looper and handler. See the BMessenger class for details on how a BMessenger identifies a target.

If you want a reply handler, you have to call `SetHandlerForReply()` after the constructor returns. You can reset the message and messenger through `SetMessage()` and `SetTarget()`.

### ~BInvoker()

virtual `~BInvoker()`

Deletes the object's BMessage.

## Member Functions

### BeginInvokeNotify() , EndInvokeNotify()

void `BeginInvokeNotify(`uint32 kind = B_CONTROL_INVOKED`) `
void `EndInvokeNotify() `

If for some reason you need to implement a method that emulates an `InvokeNotify()` call inside an `Invoke()` implementation, you should wrap the invocation code in these functions. They set up and tear down an `InvokeNotify()` context.

### Command() see SetMessage()

### HandlerForReply() see SetHandlerForReply()

### Invoke() , InvokeNotify()

virtual status_t `Invoke(` BMessage *message = NULL`) `
status_t `InvokeNotify(` BMessage *message, uint32 kind = B_CONTROL_INVOKED`) `

`Invoke()` tells the BInvoker's messenger to send a message. If message is non-`NULL`, that message is sent, otherwise the object sends its default message (i.e. the BMessage that was passed in the constructor or in `SetMessage()`). The message is sent asynchronously with no time limit on the reply.

| Regarding the use of the default message vs the argument, a common practice is to reserve the default message as a template, and pass a fine-tuned copy to `Invoke()`:

       /* Add the current system time to a copy of the default message. */
       BMessage copy(invoker.Message());
       copy.AddInt64("when", system_time());
       invoker.Invoke(&copy);

The `InvokeNotify()` function sends the message to the target, using the notification change code specified by kind. If message is `NULL`, nothing gets sent to the target, but any watchers of the invoker's handler will receive their expected notifications. By default, the kind is `B_CONTROL_INVOKED`—the same kind sent by a straight `Invoke()`.

| In general, you should call `InvokeNotify()` instead of `Invoke()` in new BeOS applications that run under BeOS 5 and later. You can map old code to new like this:

BeOS 4.5.x | BeOS 5
--- | ---
Invoke() | InvokeNotify(Message())
Invoke(Message()) | InvokeNotify(Message())
Invoke(ModificationMessage()) | InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED)

`Invoke()` doesn't call `SendNotices()` by default; you'll have to implement code to do it yourself. Here's how:

       status_t BControl::Invoke(BMessage *msg) {
          bool notify = false;
          uint32 kind = InvokeKind(&notify);

          BMessage clone(kind);
          status_t err = B_BAD_VALUE;

          if (!msg && !notify) {
             // If no message is supplied, pull it from the BInvoker.
             // However, ONLY do so if this is not an InvokeNotify()
             // context -- otherwise, this is not the default invocation
             // message, so we don>t want it to get in the way here.
             // For example, a control may call InvokeNotify() with their
             // "modification" message...  if that message isn>t set,
             // we still want to send notification to any watchers, but
             // -don>t- want to send a message through the invoker.
             msg = Message();
          }
          if (!msg) {
             // If not being watched, there is nothing to do.
             if( !IsWatched() ) return err;
          } else {
             clone = *msg;
          }

          clone.AddInt64("when", system_time());
          clone.AddPointer("source", this);
          clone.AddInt32("be:value",fValue);
          clone.AddMessenger(B_NOTIFICATION_SENDER, BMessenger(this));
          if( msg ) err = BInvoker::Invoke(&clone);

          // Also send invocation to any observers of this handler.
          SendNotices(kind, &clone);

          return err;
       }

RETURN CODES

- `B_OK`. The message was sent.

- `B_BAD_VALUE`. No default message, and no message argument.

- Other errors forwarded from `BMessenger::SendMessage()`.

### InvokeKind()

uint32 `InvokeKind(`bool *notify = NULL`)`

Returns the kind passed to `InvokeNotify()`. This should be called from within your implementation of `Invoke()` if you need to determine what kind was specified when `InvokeNotify()` was called. If you care whether `Invoke()` or `InvokeNotify()` was originally called, you can specify a pointer to a bool, notify, which is set to `true` if `InvokeNotify()` was called, or `false` if `Invoke()` was called.

This lets you fetch the `InvokeNotify()` arguments from your `Invoke()` code without breaking compatibility with older applications by adding arguments to `Invoke()`.

### InvokeNotify() see Invoke()

### IsTargetLocal() see SetTarget()

### Message() see SetMessage()

### Messenger() see SetTarget()

### SetHandlerForReply() , HandlerForReply()

virtual status_t `SetHandlerForReply(` BHandler *replyHandler`) `
BHandler *`HandlerForReply(`void`)` const

`SetHandlerForReply()` sets the BHandler object that handles replies that are sent back by the target. By default (or if replyHandler is `NULL`), replies are sent to the BApplication object.

`HandlerForReply()` returns the object set through `SetHandlerForReply()`. If the reply handler isn't set, this function returns `NULL`, it doesn't return `be_app` (even though `be_app` will be handling the reply).

RETURN CODES

- `SetHandlerForReply()` always returns `B_OK`—it doesn't check for validity.

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

virtual status_t `SetMessage(` BMessage *message`) `
BMessage *`Message(`void`)` const
uint32 `Command(`void`)` const

`SetMessage()` sets the BInvoker's default message to point to message (the message is not copied). The previous default message (if any) is deleted; a `NULL` message deletes the previous message without setting a new one. The BInvoker owns the BMessage that you pass in; you mustn't `delete` it yourself.

`Message()` returns a pointer to the default message, and `Command()` returns its `what` data member. Lacking a default message, the functions return `NULL`.

RETURN CODES

- `SetMessage()` always returns `B_OK`.

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

virtual status_t `SetTarget(` BMessenger messenger`) `
virtual status_t `SetTarget(`const BHandler *handler, const BLooper *looper = NULL`)`
BHandler *`Target(` BLooper **looper = NULL`)` const
bool `IsTargetLocal(`void`)` const
BMessenger `Messenger(`void`)` const

These functions set and query the BInvoker's target. This is the BHandler to which the object sends a message when `Invoke()` is called. The target is represented by a BMessenger object; you can set the BMessenger as a copy of messenger, or initialize it with looper and handler. See the BMessenger class for details on how a BMessenger identifies a target.

`Target()` returns the BHandler that's targeted by the object's messenger. If looper is non-`NULL`, the BLooper that owns the BHandler is returned by reference. If the target was set as a looper's preferred handler (i.e. `SetTarget(NULL, looper)`), or if the target hasn't been set yet, `Target()` returns `NULL`. The function returns `NULL` for both objects if the target is remote.

`IsTargetLocal()` returns `true` if the target lives within the BInvoker's application, and `false` if it belongs to some other app.

`Messenger()` returns a copy of the BMessenger object the BInvoker uses to send messages. If a target hasn't been set yet, the return will be invalid.

RETURN CODES

- `B_OK`. The target was successfully set.

- `B_BAD_VALUE`. The proposed handler doesn't belong to a BLooper.

- `B_MISMATCHED_VALUES`. handler doesn't belong to looper.

| `SetTarget()` doesn't detect invalid BLoopers and BMessengers.

### SetTimeout() , Timeout()

status_t `SetTimeout(`bigtime_t timeout`) `
bigtime_t `Timeout(`void`)` const

`SetTimeout()` sets the timeout that will be used when sending the invocation message to the invoker's target. By default this is `B_INFINITE_TIMEOUT`.

`Timeout()` returns the current setting for this value.

RETURN CODES

``

- B_OK. No error.

### Target() see SetTarget()

### Timeout() see SetTimeout()

The Application Kit Table of Contents | The Application Kit Index

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

Copyright © 2000 Be, Inc. All rights reserved..