root/haiku/trunk/docs/user/app/Handler.dox

Revision 24304, 17.6 kB (checked in by nielx, 2 months ago)
Handler.dox:
- Small link fix
- Clean up the titles of the subsections a bit: these are reused in the looper documentation and they sort of clashed before.

Also, new documentation for Looper.dox!
Line 
1 /*
2  * Copyright 2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *              Niels Sascha Reedijk, niels.reedijk@gmail.com
7  *
8  * Corresponds to:
9  *              /trunk/headers/os/app/Handler.h  rev 22577
10  *              /trunk/src/kits/app/Handler.cpp  rev 21332
11  */
12
13 /*!
14         \file Handler.h
15         \brief Provides the BHandler class.
16 */
17
18 ///// Globals /////
19
20 /*!
21         \def B_OBSERVE_WHAT_CHANGE
22         \brief Internal.
23 */
24
25
26 /*!
27         \def B_OBSERVE_ORIGINAL_WHAT
28         \brief Constant for a message data field in observer messages.
29        
30         If you have called one of the flavors of BHandler::StartWachting(), and
31         you receive a notification, sometimes there can be send a BMessage to go
32         with that notification. The message you receive is a copy of that message,
33         but with the what constant set to \c B_OBSERVER_NOTICE_CHANGE. The original
34         \c what constant of the transmitted data message is stored behind the
35         label defined by this constant.
36 */
37
38
39 /*!
40         \var B_OBSERVER_OBSERVE_ALL
41         \brief Parameter to BHandler::StartWatching().
42        
43         \note Specifying this parameter as the \a what value, leads to the same
44                 results as calling BHandler::StartWatchingAll().
45 */
46
47
48 ///// BHandler /////
49
50
51 /*!
52         \class BHandler
53         \ingroup app
54         \brief Handles messages that are passed on by a BLooper.
55        
56         The BHandler class implements two important pieces of functionality. It
57         provides the foundations for <b>handling messages</b>, and it serves as a
58         <b>state machine</b> that sends out notifications of the state changes.
59        
60         The most common use of this class is to <b>handle messages</b>. Handlers
61         can be tied to loopers, which are the objects that send and receive
62         messages. As soon as a message is received, the looper passes through its
63         list of associated handlers and tries them in a certain order until the
64         message is handled, or the options are exhausted.
65        
66         You should know that a looper is a subclass of a handler, and as such,
67         loopers can be self-contained and do not need additional handlers. In many
68         cases, this construction will suffice. You will simply subclass the looper,
69         override its MessageReceived() hook and handle the messages you receive. In
70         some cases, you might opt in for a more ingenious construction. A
71         real-world example is the interface kit. Within that kit, the windows are
72         represented by a BLooper, and all the views and controls in that kit are
73         derived from BHandler. If you put a control in a window, then whenever
74         messages such as clicks are received, the window loops the handlers until
75         there is a handler that is at the screen position the click was in. It is
76         not unlikely that you will some day want to use this functionality of the
77         API.
78        
79         If your handler is limited to a certain type of messages, you can set a
80         filter that the looper will apply to your message before passing it on to
81         your overridden MessageReceived() method. The BMessageFilter class provides
82         the framework for the flexible filtering options, and using AddFilter() you
83         can apply filters to this handler. Note that a filter object should only be
84         applied to one handler. They cannot be shared.
85        
86         For more information on the handling chain, have a look at the
87         documentation of the BLooper class.
88        
89         Using BHandler as a <b>state machine</b> is a second area of functionality.
90         Since handlers process messages, and perform actions associated with those,
91         they are the center of keeping track on the current state of things within
92         an application. If you want to synchronize these states between different
93         parts of your application, you could perform this manually by sending
94         messages to the interested components, or you can use the more flexible
95         approach with observers.
96        
97         Observers watch a certain state. A handler can track one or more different
98         states. Each state is represented by a four byte constant - just like the
99         \c what property of a message. Using the StartWatching() methods, you can
100         register observers both within your team, and in other applications. As an
101         argument of that method, you can supply the state you want to watch, or you
102         can register an observer using StartWatchingAll() to watch all the states
103         the handler tracks. When the handler needs to emit a state change, you can
104         use SendNotices(). You can specify the exact state change, and some data
105         that you want to be send to the observers. This data is in the form of the
106         very flexible BMessage, as such you are almost free to pass anything you
107         want.
108        
109         Whenever SendNotices() is called, all interested observers will receive a
110         message of the \a B_OBSERVER_NOTICE_CHANGE type. Please note that the
111         constant that is associated with the state itself is not transmitted. If
112         you require this information, consider using the message that is passed
113         on to describe the state change.
114
115         BHandler is a part of the chain in the eloquent messaging structure. For a
116         proper understanding of all its facets, have a look at the \ref app_messaging
117         "messaging overview".
118 */
119
120
121 /*!
122         \fn BHandler::BHandler(const char* name = NULL)
123         \brief Construct a new handler with a \a name.
124        
125         The newly constructed handler is not associated with a looper until you
126         explicitly request this to happen. To associate this handler with a looper,
127         use BLooper::AddHandler().
128 */
129
130
131 /*!
132         \fn BHandler::~BHandler()
133         \brief Free the filters of this handler, as well as the list of observers.
134        
135         This method does not remove the handler from the looper to which this
136         handler is associated. You should do this yourself, using
137         BLooper::RemoveHandler().
138        
139         \warning This constructor does no type check whatsoever. Since you can pass
140                 any BMessage, you should - if you are not sure about the exact type -
141                 use the Instantiate() method, which does check the type.
142 */
143
144
145 /*!
146         \fn BArchivable *BHandler::Instantiate(BMessage *data)
147         \brief Static method to instantiate a handler from an archived message.
148        
149         \return A pointer to the instantiated handler, or \c NULL if the \a data
150                 is not a valid archived BHandler object.
151         \see BHandler(BMessage* data)
152 */
153
154
155 ///// Archiving /////
156
157 /*!
158         \name Archiving
159         BHandler inherits the BArchivable class, and as such implements support for
160         archiving and unarchiving handlers.
161 */
162
163
164 //! @{
165        
166        
167 /*!
168         \fn BHandler::BHandler(BMessage* data)
169         \brief Construct a handler from an archived message.
170        
171         This \a data has to be created using the BHandler::Archive() method.
172         Note that only the name is stored. The filters, the associated looper and
173         the observers are not stored, and should be manually added when you are
174         using this object.
175 */
176
177
178 /*!
179         \fn status_t BHandler::Archive(BMessage *data, bool deep) const
180         \brief Archive a handler to a message
181        
182         Currently, only the name is archived. The filters, the associated looper
183         and the observers are not stored.
184        
185         \param data The message to archive the object in.
186         \param deep This parameter is ignored, as BHandler does not have children.
187         \retval B_OK Archiving succeeded.
188         \retval B_BAD_VALUE The \a data parameter is not a valid message.
189         \see BHandler::Instantiate(BMessage *data)
190 */
191
192
193 //! @}
194
195
196 ///// The guts of BHandler /////
197
198
199 /*!
200         \name Core Handler Functionality
201 */
202
203
204 //! @{
205
206
207 /*!
208         \fn void BHandler::MessageReceived(BMessage *message)
209         \brief Handle a message that has been received by the associated looper.
210        
211         This method is reimplemented in your subclasses. If the messages that have
212         been received by a looper pass through the filters, then they end up in
213         the MessageReceived() methods.
214        
215         The example shows a very common way to handle message. Usually, this
216         involves parsing the BMessage::what constant and then perform an action
217         based on that.
218        
219 \code
220 void
221 ShowImageApp::MessageReceived(BMessage *message)
222 {
223         switch (message->what) {
224                 case MSG_FILE_OPEN:
225                         fOpenPanel->Show();
226                         break;
227
228                 case B_CANCEL:
229                         // File open panel was closed,
230                         // start checking count of open windows.
231                         StartPulse();
232                         break;
233                
234                 default:
235                         // We do not handle this message, pass it on to the base class.
236                         BApplication::MessageReceived(message);
237                         break;
238         }
239 }
240 \endcode
241
242         If your handler cannot process this message, you should pass it on to the
243         base class. Eventually, it will reach the default implementation, which
244         will reply with a \c B_MESSAGE_NOT_UNDERSTOOD constant.
245        
246         \attention If you want to keep or manipulate the \a message, have a look
247                 at the \link BLooper::DetachCurrentMessage() DetachCurrentMessage() \endlink
248                 method to get ownership of the message.
249        
250         \param message The message that needs to be handled.
251 */
252
253
254 /*!
255         \fn BLooper *BHandler::Looper() const
256         \brief Return a pointer to the looper that this handler is associated with.
257        
258         \return If the handler is not yet associated with a looper, it will return
259                 \c NULL.
260         \see BLooper::AddHandler()
261         \see LockLooper()
262 */
263
264
265 /*!
266         \fn void BHandler::SetName(const char *name)
267         \brief Set or change the name of this handler.
268         \see Name()
269 */
270
271
272 /*!
273         \fn const char *BHandler::Name() const
274         \brief Return the name of this handler.
275         \see SetName()
276 */
277
278
279 /*!
280         \fn void BHandler::SetNextHandler(BHandler *handler)
281         \brief Set the next handler in the chain that the message is passed on to
282                 if this handler cannot process it.
283        
284         This method has three requirements:
285         -# This handler should belong to a looper.
286         -# The looper needs to be locked. See LockLooper().
287         -# The \a handler that you pass must be associated with the same looper.
288        
289         Failure to meet any of these requirements will result in your application
290         crashing.
291        
292         By default, the handlers are chained in order that they were associated to
293         a looper with BLooper::AddHander().
294        
295         \see NextHandler()
296 */
297
298
299 /*!
300         \fn BHandler *BHandler::NextHandler() const
301         \brief Return the next hander in the chain to which the message is passed
302                 on.
303         \see SetNextHandler()
304 */
305
306
307 //! @}
308
309
310 ///// Message Filtering /////
311
312
313 /*!
314         \name Message Filtering
315 */
316
317
318 //! @{
319        
320        
321 /*!
322         \fn void BHandler::AddFilter(BMessageFilter *filter)
323         \brief Add a filter as a prerequisite to this handler.
324        
325         If the handler is associated with a looper, this looper needs to be locked
326         in order for this operation to succeed.
327        
328         Note that the filter is not copied, rather a pointer to the filter is
329         stored. As such, you need to make sure that the filter object exists as
330         long as it is added to this handler.
331        
332         \see RemoveFilter(), SetFilterList()
333 */
334
335
336 /*!
337         \fn bool BHandler::RemoveFilter(BMessageFilter *filter)
338         \brief Remove a filter from the filter list.
339        
340         If the handler is associated with a looper, this looper needs to be locked
341         in order for this operation to succeed.
342        
343         Note that the filter is not deleted, merely removed from the list. You need
344         to take care of the memory yourself.
345        
346         \retval true The filter was in the filter list and is removed.
347         \retval false The filter was not found in the filter list.
348        
349         \see AddFilter(), FilterList()
350 */
351
352
353 /*!
354         \fn void BHandler::SetFilterList(BList* filters)
355         \brief Set the internal list of filters to \a filters.
356
357         If the handler is associated with a looper, this looper needs to be locked
358         in order for this operation to succeed.
359        
360         The internal list will be replaced with the new list of \a filters. All the
361         existing filters will be \b deleted.
362
363         \see AddFilter(), FilterList()
364 */
365
366
367 /*!
368         \fn BList *BHandler::FilterList()
369         \brief Return a pointer to the list of filters.
370        
371         \return A pointer to the list of filters. Do not manipulate the list of
372                 filters directly, but use the methods provided by this class, in order
373                 to maintain internal consistency.
374                
375         \see AddFilter(), RemoveFilter(), SetFilterList().
376 */
377
378
379 //! @}
380
381
382 ///// Locking /////
383
384
385 /*!
386         \name Locking
387        
388         This class provides some utility functions to look the looper associated
389         with this handler.
390 */
391
392
393 //! @{
394        
395        
396 /*!
397         \fn bool BHandler::LockLooper()
398         \brief Lock the looper associated with this handler.
399        
400         \retval true The looper is locked.
401         \retval false There was an error acquiring the lock.
402        
403         \see LockLooperWithTimeout(), UnlockLooper()
404 */
405
406
407 /*!
408         \fn status_t BHandler::LockLooperWithTimeout(bigtime_t timeout)
409         \brief Lock the looper associated with this handler, with a time out value.
410        
411         \param timeout The time to wait for acquiring the lock in microseconds. You
412                 may also use B_INFINITE_TIMEOUT, in which this method will wait as long
413                 as it takes to acquire the lock.
414        
415         \retval B_OK Locking succeeded.
416         \retval B_BAD_VALUE This handler is not associated with a looper (anymore).
417         \retval B_TIMED_OUT The time specified in \a timeout has passed without
418                 locking the looper.
419        
420         \see LockLooper(), UnlockLooper()
421 */
422
423
424 /*!
425         \fn void BHandler::UnlockLooper()
426         \brief Unlock the looper.
427 */
428
429
430 //! @}
431
432
433 ///// Scripting //////
434
435
436 /*!
437         \name Scripting
438 */
439
440
441 //! @{
442
443
444 /*!
445         \fn BHandler * BHandler::ResolveSpecifier(BMessage *msg, int32 index,
446                 BMessage *specifier, int32 form, const char *property)
447         \brief Undocumented.
448 */
449
450
451 /*!
452         \fn status_t BHandler::GetSupportedSuites(BMessage *data)
453         \brief Undocumented.
454 */
455
456
457 //! @}
458
459
460 ///// Observing /////
461
462
463 /*!
464         \name Observing
465        
466         Handlers can function as state machines, which emit messages to observers
467         when the state changes. Use the following methods to subscribe to these
468         notifications.
469        
470         Note that there is a semantic difference between the two StartWatching()
471         methods. The overloaded method that accepts a BHandler, expects as
472         argument an \a observer that watches <em>this handler</em>. The method that
473         accepts a BMessenger, expects a \a target that emits the state changes
474         <em>to this handler</em>.
475 */
476
477
478 //! @{
479
480
481 /*!
482         \fn status_t BHandler::StartWatching(BMessenger target, uint32 what)
483         \brief Subscribe this handler to watch a specific state change of a
484                 \a target.
485        
486         Use this method to subscribe messengers to watch state changes in <em>this
487         handler</em>. This means that also observers  from other teams can be
488         subscribed.
489        
490 \code
491         // Handler B watches Handler A
492         BHandler A, B;
493         BMessenger messengerA(&A)
494        
495         B.StartWatching(messengerA, kNetworkConnection);
496 \endcode
497        
498         \param target The messenger from which the notifications would be
499                 received.
500         \param what The state that needs to be watched.
501         \return During the call of this method, a notification will be transmitted
502                 using the \a target. If this works, then this method will return
503                 \c B_OK.
504         \see StartWatchingAll(BMessenger), StopWatching(BMessenger, uint32)
505 */
506
507
508 /*!
509         \fn status_t BHandler::StartWatchingAll(BMessenger target)
510         \brief Subscribe this handler to watch a \a target for all events.
511        
512         This method performs the same task as StartWatching(BMessenger, uint32),
513         but it will subscribe to all the state changes the \a target knows.
514        
515         \see StartWatching(BMessenger, uint32), StopWatchingAll(BMessenger)
516 */
517
518
519 /*!
520         \fn status_t BHandler::StopWatching(BMessenger target, uint32 what)
521         \brief Unsubscribe this handler from watching a specific state.
522        
523         This method will unsubscribe this handler from watching a specific event
524         in a \a target.
525        
526         \see StartWatching(BMessenger, uint32)
527 */
528
529
530 /*!
531         \fn status_t BHandler::StopWatchingAll(BMessenger target)
532         \brief Unsubscribe this handler from watching all states.
533        
534         This method will unsubscribe the \a target from watching all state changes.
535        
536         \see StartWatchingAll(BMessenger)
537 */
538
539
540 /*!
541         \fn status_t BHandler::StartWatching(BHandler* observer, uint32 what)
542         \brief Subscribe an \a observer for a specific state change of this handler.
543        
544         Use this method to subscribe observers to watch this handler. State changes
545         of this handler that match the \a what argment, will be sent.
546
547 \code
548         // Handler B wants to observe Handler A
549         BHandler A, B;
550        
551         A.StartWatching(&B, kNetworkConnection);
552 \endcode
553
554         Since pointers to handlers can only
555         exist in the local namespace, have a look at
556         StartWatching(BMessenger, uint32) for inter-team watching.
557        
558         \param observer The observer for this handler.
559         \param what The state that needs to be watched.
560         \return During the call of this method, a notification will be transmitted
561                 using the \a observer. If this works, then this method will return
562                 \c B_OK.
563        
564         \see StartWatchingAll(BHandler*), StopWatching(BHandler*, uint32)       
565 */
566
567
568 /*!
569         \fn status_t BHandler::StartWatchingAll(BHandler* observer)
570         \brief  Subscribe an \a observer for a all state changes.
571        
572         This method performs the same task as StartWatching(BHandler, uint32),
573         but it will subscribe the \a observer to all the state changes this handler
574         tracks.
575        
576         \see StartWatching(BHandler*, uint32), StopWatchingAll(BHandler*)       
577 */
578
579
580 /*!
581         \fn status_t BHandler::StopWatching(BHandler* handler, uint32 what)
582         \brief Unsubscribe an observer from watching a specific state.
583
584         This method will unsubscribe the \a handler from watching a specific event.
585
586         \see StartWatching(BHandler*, uint32)
587 */
588
589
590 /*!
591         \fn status_t BHandler::StopWatchingAll(BHandler* handler)
592         \brief Unsubscribe an observer from watching all states.
593        
594         This method will unsubscribe the \a handler from watching all state changes.
595        
596         \see StartWatchingAll(BHandler*)
597 */
598
599
600 //! @}
601
602
603 ///// State changes /////
604
605
606 /*!
607         \name Emitting State Changes
608         If your handler functions as a state machine, and it has observers (which
609         subscribed using the StartWatching() method), you can emit these state
610         changes.
611 */
612
613
614 //! @{
615        
616        
617 /*!
618         \fn void BHandler::SendNotices(uint32 what, const BMessage *msg)
619         \brief Emit a state change to the observers.
620        
621         The actual state (specified by \a what) will not be transmitted. This is
622         merely for internal bookkeeping. It is not entirely unimaginable that you
623         still want to inform the observers of what actually took place. You can
624         use the \a msg to transmit this, and any other data you want. Note that the
625         message will be copied and slightly altered: the \c what member of the
626         message will be \c B_OBSERVER_NOTICE_CHANGE, and the \c what constant you
627         specified will be stored in the #B_OBSERVE_ORIGINAL_WHAT label.
628        
629         \param what The identifier of the state.
630         \param msg Any data associated with the state change. You retain ownership
631                 of this data, so make sure you dispose it when you are done.
632 */
633        
634        
635 /*!
636         \fn bool BHandler::IsWatched() const
637         \brief Check if there are any observers watching this handler.
638 */
639
640
641 //! @}
642
Note: See TracBrowser for help on using the browser.