xref: /haiku/docs/user/app/Handler.dox (revision 74252cefbcf266291fb069466189b4734eb05455)
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