Boost logo

Boost :

From: Edward Diener (eddielee_at_[hidden])
Date: 2004-08-25 19:37:42


John Torjo wrote:
>>> I don't think you'd want any component to catch events generated by
>>> any other component.
>>> What I think you'd like is: handle on a dialog, any notification
>>> coming from its controls. If the dialog does not/cannot handle this
>>> notification, propagate it up the chain (dialog's parent, grand
>>> parent, etc.).
>>>
>>>
>>
>> I heavily disagree with this model. That's MFC/OWL and I would guess
>> plenty of other GUI environments, and it is old. There is no reason
>> why any component shouldn't be able to hook events.
>>
>>
>>
> Please explain "hook events".

Be an event handler for a particular event. C++ Builder is single-cast so to
be an event handler for an event was simply a matter of assigning one's
object's member function to a __closure ( an extension which is dealt very
neatly in standard C++ now using boost::bind ). Managed C++ .NET is
multicast so one essentially "assigns" one's event handler to a delegate,
which encapslates multicast events.

>
>>> This is how win32gui handles events right now.
>>>
>>> And I think this is how C++ Builder/.net handles events as well.
>>>
>>>
>>
>> You are completely wrong on this last point. Any C++ Builder
>> component can hook an event ( called a __closure ). Any .NET
>> component can hook an event
>>
>>
> Do you mean "respond to an event"?

Yes, if by that you mean have any type of function handle an event. In
boost::signal<> this would be a slot, and boost::signal allows anything
which can be a boost::function act as an event handler, which means an
object's member function, a function object, or a global/static function.

>
>> ( called a delegate ). I am not trying to put down what seems to be
>> your excellent work in any way, but you are conceptually following a
>> model for event generation/event handling which has been superceded
>> IMHO. If you like that model, fine. But I want to point out to you
>> that a much better model, and much more in the spirit of C++, is to
>> allow any functor to handle an event. And of course boost::signal<>
>> is built around this idea. If your events are multi-casting, which I
>> am sure they must be, there is no reason putting limitations on who
>> can handle them unless you are using a means of event generation
>> which is in itself restrictive in what it can do. All you end up
>> doing is making programmers who want to use your GUI angry that they
>> must find workarounds for event handling for many cases for which
>> you haven't yet conceived.
>>
>>
>>
> I could really use some examples here ;) Because I really can't think
> of any. Maybe we are mis-reading eachother ;)

Here is a general example of what I mean. I have a class which needs to
respond to some event in your system. The event may be something which
usually happens to a visual widget, but my class may neither be a widget as
you define it, or it may be a widget but a non-visual one. In good
old-fashioned Windows and MFC, only a visual widget ( read "window" or
"control" ) can respond to the event. So you follow this paradigm and my
poor class, or widget, if you will, despite the fact that it needs to
respond to an event for whatever reason, can no longer do so without doing
some exotic tricks. Why ? Because you have established some arbitrary
barrier, something like "only a embedded widget, or another type of related
widget window" can respond to the event. Of course there are no doubt
tricks, such as have been used in Windows from time immemorial to get around
such limitations, ie. creating a dummy window of the correct kind and doing
god knows what other silly but necessary things. But why bother to create
such a system with such limitations.

When I say respond to some event I almost always mean that my event handler
( or slot if you like that term ) will invariably just be notified that a
particular event has occurred, and will do something accordingly within
itself. Yes, I understand that many events have responses which change the
nature of the visual actions drastically, and that you may feel that you do
not want to allow certain classes/widgets to do so, but there is still no
reason for such a limitation even in this case. C++ was created to give the
programmer maximum control and maximum responsibility. You should honor that
design. If the user of your GUI library wants to shoot himself in the foot
by having some weird class handle an event in a way that does something
really idiotic, let him. Putting up barriers such as, "I think that only
X,Y, and Z class member functions should be able to handle this event" is
nonsensical. With boost::signal<> allow any class to handle an event. If you
want to maintain control internally you can use boost::signal<> easily
enough so that your handler is the first to handle an event and can
short-circuit everyone else. But don't limit what can handle events or not
to the outside user.

Here is a real-world situation from my own programming, but because I am
still working on the idea and it may be a product for which I charge
someday, I will give the minimum information. I have a non-visual class ( or
component if you will in certain RAD environments ) which needs to handle
the possible OS change of locale by an end user. It turns out that for a
particular OS for which I am programming, the message which denotes the
change of locale is only sent to a top-level window of a process. So my
non-visual component is forced to do some elaborate tricks to handle this
message. In an OOP GUI system, built on events/handlers ( or
signals/slots ), the system can catch the message and have an event for it
which is signaled each time the message occurs with the appropriate
parameters being passed. In such a system if it is decided that "only other
windows and other specialized window-like widgets" can handle the event, I
am back in square 1. But a truly great system says "anyone function, ie
boost::function<>, can handle this event" and it is a breeze for my
class/component to do so. Why not make that type of system for your end-user
rather than the type which has already existed and caused endless
programmers to waste their time figuring out how to work around its idiotic
limitations.

Edward Diener


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk