xref: /haiku/docs/user/app/Handler.dox (revision 020cbad9d40235a2c50a81a42d69912a5ff8fbc4)
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
140
141/*!
142	\fn BArchivable *BHandler::Instantiate(BMessage *data)
143	\brief Static method to instantiate a handler from an archived message.
144
145	\return A pointer to the instantiated handler, or \c NULL if the \a data
146		is not a valid archived BHandler object.
147	\see BHandler(BMessage* data)
148*/
149
150
151///// Archiving /////
152
153/*!
154	\name Archiving
155	BHandler inherits the BArchivable class, and as such implements support for
156	archiving and unarchiving handlers.
157*/
158
159
160//! @{
161
162
163/*!
164	\fn BHandler::BHandler(BMessage* data)
165	\brief Construct a handler from an archived message.
166
167	This \a data has to be created using the BHandler::Archive() method.
168	Note that only the name is stored. The filters, the associated looper and
169	the observers are not stored, and should be manually added when you are
170	using this object.
171*/
172
173
174/*!
175	\fn status_t BHandler::Archive(BMessage *data, bool deep) const
176	\brief Archive a handler to a message
177
178	Currently, only the name is archived. The filters, the associated looper
179	and the observers are not stored.
180
181	\param data The message to archive the object in.
182	\param deep This parameter is ignored, as BHandler does not have children.
183	\retval B_OK Archiving succeeded.
184	\retval B_BAD_VALUE The \a data parameter is not a valid message.
185	\see BHandler::Instantiate(BMessage *data)
186*/
187
188
189//! @}
190
191
192///// The guts of BHandler /////
193
194
195/*!
196	\name Core Functionality
197*/
198
199
200//! @{
201
202
203/*!
204	\fn void BHandler::MessageReceived(BMessage *message)
205	\brief Handle a message that has been received by the associated looper.
206
207	This method is reimplemented in your subclasses. If the messages that have
208	been received by a looper pass through the filters, then they end up in
209	the MessageReceived() methods.
210
211	The example shows a very common way to handle message. Usually, this
212	involves parsing the BMessage::what constant and then perform an action
213	based on that.
214
215\code
216void
217ShowImageApp::MessageReceived(BMessage *message)
218{
219	switch (message->what) {
220		case MSG_FILE_OPEN:
221			fOpenPanel->Show();
222			break;
223
224		case B_CANCEL:
225			// File open panel was closed,
226			// start checking count of open windows.
227			StartPulse();
228			break;
229
230		default:
231			// We do not handle this message, pass it on to the base class.
232			BApplication::MessageReceived(message);
233			break;
234	}
235}
236\endcode
237
238	If your handler cannot process this message, you should pass it on to the
239	base class. Eventually, it will reach the default implementation, which
240	will reply with a \c B_MESSAGE_NOT_UNDERSTOOD constant.
241
242	\attention If you want to keep or manipulate the \a message, have a look
243		at the \link BLooper::DetachMessage() DetachMessage() \endlink method
244		to get ownership of the message.
245
246	\param message The message that needs to be handled.
247*/
248
249
250/*!
251	\fn BLooper *BHandler::Looper() const
252	\brief Return a pointer to the looper that this handler is associated with.
253
254	\return If the handler is not yet associated with a looper, it will return
255		\c NULL.
256	\see BLooper::AddHandler()
257	\see LockLooper()
258*/
259
260
261/*!
262	\fn void BHandler::SetName(const char *name)
263	\brief Set or change the name of this handler.
264	\see Name()
265*/
266
267
268/*!
269	\fn const char *BHandler::Name() const
270	\brief Return the name of this handler.
271	\see SetName()
272*/
273
274
275/*!
276	\fn void BHandler::SetNextHandler(BHandler *handler)
277	\brief Set the next handler in the chain that the message is passed on to
278		if this handler cannot process it.
279
280	This method has three requirements:
281	-# This handler should belong to a looper.
282	-# The looper needs to be locked. See LockLooper().
283	-# The \a handler that you pass must be associated with the same looper.
284
285	Failure to meet any of these requirements will result in your application
286	crashing.
287
288	By default, the handlers are chained in order that they were associated to
289	a looper with BLooper::AddHander().
290
291	\see NextHandler()
292*/
293
294
295/*!
296	\fn BHandler *BHandler::NextHandler() const
297	\brief Return the next hander in the chain to which the message is passed
298		on.
299	\see SetNextHandler()
300*/
301
302
303//! @}
304
305
306///// Message Filtering /////
307
308
309/*!
310	\name Message Filtering
311*/
312
313
314//! @{
315
316
317/*!
318	\fn void BHandler::AddFilter(BMessageFilter *filter)
319	\brief Add a filter as a prerequisite to this handler.
320
321	If the handler is associated with a looper, this looper needs to be locked
322	in order for this operation to succeed.
323
324	Note that the filter is not copied, rather a pointer to the filter is
325	stored. As such, you need to make sure that the filter object exists as
326	long as it is added to this handler.
327
328	\see RemoveFilter(), SetFilterList()
329*/
330
331
332/*!
333	\fn bool BHandler::RemoveFilter(BMessageFilter *filter)
334	\brief Remove a filter from the filter list.
335
336	If the handler is associated with a looper, this looper needs to be locked
337	in order for this operation to succeed.
338
339	Note that the filter is not deleted, merely removed from the list. You need
340	to take care of the memory yourself.
341
342	\retval true The filter was in the filter list and is removed.
343	\retval false The filter was not found in the filter list.
344
345	\see AddFilter(), FilterList()
346*/
347
348
349/*!
350	\fn void BHandler::SetFilterList(BList* filters)
351	\brief Set the internal list of filters to \a filters.
352
353	If the handler is associated with a looper, this looper needs to be locked
354	in order for this operation to succeed.
355
356	The internal list will be replaced with the new list of \a filters. All the
357	existing filters will be \b deleted.
358
359	\see AddFilter(), FilterList()
360*/
361
362
363/*!
364	\fn BList *BHandler::FilterList()
365	\brief Return a pointer to the list of filters.
366
367	\return A pointer to the list of filters. Do not manipulate the list of
368		filters directly, but use the methods provided by this class, in order
369		to maintain internal consistency.
370
371	\see AddFilter(), RemoveFilter(), SetFilterList().
372*/
373
374
375//! @}
376
377
378///// Locking /////
379
380
381/*!
382	\name Locking
383
384	This class provides some utility functions to look the looper associated
385	with this handler.
386*/
387
388
389//! @{
390
391
392/*!
393	\fn bool BHandler::LockLooper()
394	\brief Lock the looper associated with this handler.
395
396	\retval true The looper is locked.
397	\retval false There was an error acquiring the lock.
398
399	\see LockLooperWithTimeout(), UnlockLooper()
400*/
401
402
403/*!
404	\fn status_t BHandler::LockLooperWithTimeout(bigtime_t timeout)
405	\brief Lock the looper associated with this handler, with a time out value.
406
407	\param timeout The time to wait for acquiring the lock in microseconds. You
408		may also use B_INFINITE_TIMEOUT, in which this method will wait as long
409		as it takes to acquire the lock.
410
411	\retval B_OK Locking succeeded.
412	\retval B_BAD_VALUE This handler is not associated with a looper (anymore).
413	\retval B_TIMED_OUT The time specified in \a timeout has passed without
414		locking the looper.
415
416	\see LockLooper(), UnlockLooper()
417*/
418
419
420/*!
421	\fn void BHandler::UnlockLooper()
422	\brief Unlock the looper.
423*/
424
425
426//! @}
427
428
429///// Scripting //////
430
431
432/*!
433	\name Scripting
434*/
435
436
437//! @{
438
439
440/*!
441	\fn BHandler * BHandler::ResolveSpecifier(BMessage *msg, int32 index,
442		BMessage *specifier, int32 form, const char *property)
443	\brief Undocumented.
444*/
445
446
447/*!
448	\fn status_t BHandler::GetSupportedSuites(BMessage *data)
449	\brief Undocumented.
450*/
451
452
453//! @}
454
455
456///// Observing /////
457
458
459/*!
460	\name Observing
461
462	Handlers can function as state machines, which emit messages to observers
463	when the state changes. Use the following methods to subscribe to these
464	notifications.
465
466	Note that there is a semantic difference between the two StartWatching()
467	methods. The overloaded method that accepts a BHandler, expects as
468	argument an \a observer that watches <em>this handler</em>. The method that
469	accepts a BMessenger, expects a \a target that emits the state changes
470	<em>to this handler</em>.
471*/
472
473
474//! @{
475
476
477/*!
478	\fn status_t BHandler::StartWatching(BMessenger target, uint32 what)
479	\brief Subscribe this handler to watch a specific state change of a
480		\a target.
481
482	Use this method to subscribe messengers to watch state changes in <em>this
483	handler</em>. This means that also observers  from other teams can be
484	subscribed.
485
486\code
487	// Handler B watches Handler A
488	BHandler A, B;
489	BMessenger messengerA(&A)
490
491	B.StartWatching(messengerA, kNetworkConnection);
492\endcode
493
494	\param target The messenger from which the notifications would be
495		received.
496	\param what The state that needs to be watched.
497	\return During the call of this method, a notification will be transmitted
498		using the \a target. If this works, then this method will return
499		\c B_OK.
500	\see StartWatchingAll(BMessenger), StopWatching(BMessenger, uint32)
501*/
502
503
504/*!
505	\fn status_t BHandler::StartWatchingAll(BMessenger target)
506	\brief Subscribe this handler to watch a \a target for all events.
507
508	This method performs the same task as StartWatching(BMessenger, uint32),
509	but it will subscribe to all the state changes the \a target knows.
510
511	\see StartWatching(BMessenger, uint32), StopWatchingAll(BMessenger)
512*/
513
514
515/*!
516	\fn status_t BHandler::StopWatching(BMessenger target, uint32 what)
517	\brief Unsubscribe this handler from watching a specific state.
518
519	This method will unsubscribe this handler from watching a specific event
520	in a \a target.
521
522	\see StartWatching(BMessenger, uint32)
523*/
524
525
526/*!
527	\fn status_t BHandler::StopWatchingAll(BMessenger target)
528	\brief Unsubscribe this handler from watching all states.
529
530	This method will unsubscribe the \a target from watching all state changes.
531
532	\see StartWatchingAll(BMessenger)
533*/
534
535
536/*!
537	\fn status_t BHandler::StartWatching(BHandler* observer, uint32 what)
538	\brief Subscribe an \a observer for a specific state change of this handler.
539
540	Use this method to subscribe observers to watch this handler. State changes
541	of this handler that match the \a what argment, will be sent.
542
543\code
544	// Handler B wants to observe Handler A
545	BHandler A, B;
546
547	A.StartWatching(&B, kNetworkConnection);
548\endcode
549
550	Since pointers to handlers can only
551	exist in the local namespace, have a look at
552	StartWatching(BMessenger, uint32) for inter-team watching.
553
554	\param observer The observer for this handler.
555	\param what The state that needs to be watched.
556	\return During the call of this method, a notification will be transmitted
557		using the \a observer. If this works, then this method will return
558		\c B_OK.
559
560	\see StartWatchingAll(BHandler*), StopWatching(BHandler*, uint32)
561*/
562
563
564/*!
565	\fn status_t BHandler::StartWatchingAll(BHandler* observer)
566	\brief  Subscribe an \a observer for a all state changes.
567
568	This method performs the same task as StartWatching(BHandler, uint32),
569	but it will subscribe the \a observer to all the state changes this handler
570	tracks.
571
572	\see StartWatching(BHandler*, uint32), StopWatchingAll(BHandler*)
573*/
574
575
576/*!
577	\fn status_t BHandler::StopWatching(BHandler* handler, uint32 what)
578	\brief Unsubscribe an observer from watching a specific state.
579
580	This method will unsubscribe the \a handler from watching a specific event.
581
582	\see StartWatching(BHandler*, uint32)
583*/
584
585
586/*!
587	\fn status_t BHandler::StopWatchingAll(BHandler* handler)
588	\brief Unsubscribe an observer from watching all states.
589
590	This method will unsubscribe the \a handler from watching all state changes.
591
592	\see StartWatchingAll(BHandler*)
593*/
594
595
596//! @}
597
598
599///// State changes /////
600
601
602/*!
603	\name Emitting State Changes
604	If your handler functions as a state machine, and it has observers (which
605	subscribed using the StartWatching() method), you can emit these state
606	changes.
607*/
608
609
610//! @{
611
612
613/*!
614	\fn void BHandler::SendNotices(uint32 what, const BMessage *msg)
615	\brief Emit a state change to the observers.
616
617	The actual state (specified by \a what) will not be transmitted. This is
618	merely for internal bookkeeping. It is not entirely unimaginable that you
619	still want to inform the observers of what actually took place. You can
620	use the \a msg to transmit this, and any other data you want. Note that the
621	message will be copied and slightly altered: the \c what member of the
622	message will be \c B_OBSERVER_NOTICE_CHANGE, and the \c what constant you
623	specified will be stored in the #B_OBSERVE_ORIGINAL_WHAT label.
624
625	\param what The identifier of the state.
626	\param msg Any data associated with the state change. You retain ownership
627		of this data, so make sure you dispose it when you are done.
628*/
629
630
631/*!
632	\fn bool BHandler::IsWatched() const
633	\brief Check if there are any observers watching this handler.
634*/
635
636
637//! @}
638
639