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 220void 221ShowImageApp::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 643