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