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