[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
GUI draft - signals and events
Hi,
Same procedure as last mail ;)
Please comment.
------------------------------------
<h1>Inter-component communication and timing: signals and events</h1>
<em>Page under construction</em>
<br>
<h3>Introduction</h3>
<p>If you already have some experience with signals and events in GUI
systems, you should directly jump to the <a href="#advancedintro">advanced</a>
section. If not just read on.</p>
<p><em>Event</em> obviously describes something that has happened -
something someone (an object) could be interested in. But as a C++ object
does not have ears and events in a computer don't make a crash or other
sound (well, at least they should not do that ;), there must exist some
other way to notify interested objects of the event.</p>
<p>This way is usually (and again quite obviously) called <em>signal</em>.
So each time an event occurs the entity detecting it has to send signals
to all interested objects. At this point some things have to be considered:
</p>
<ul>
<li>The signal sender has to know which objects are interested in
which events.</li>
<li>The user/implementer should not need this knowledge (he in fact
should not even be able to access it).</li>
<li>It has to be possible to modify these dependencies (sender -
interested object) at run time.</li>
<li>In many cases the notification <em>that</em> something has
happened is not enough - additional data describing details
of the event have to be transmitted, too.</li>
<li>While the entire PenguinPlay library uses events, the GUI events
will usually be substantially different from e.g. system
events.</li>
</ul>
<p>To further illustrate the matter, here are some events that will be
used in a GUI system:</p>
<dl>
<dt>MouseEnter</dt>
<dd>The mouse pointer "enters" the area occupied by the widget</dd>
<dt>MouseLeave</dt>
<dd>The mouse pointer "leaves" the area occupied by the widget</dd>
<dt>MouseDragStart</dt>
<dd>The User started to "drag" something with the mouse</dd>
<dt>MouseDragEnd</dt>
<dd>The user releaded the object he has been dragging</dd>
<dt>MouseClick</dt>
<dd>The user clicked with some mouse button(s)</dd>
<dt>MouseDoubleClick</dt>
<dd>The user double-clicked with some mouse button(s)</dd>
<dt>KeyboardModifierChange</dt>
<dd>The state of the keyboard modifiers (shift, ctrl, ins, ...) changed</dd>
<dt>CharEntered</dt>
<dd>Some character has entered the keyboard buffer</dd>
<dt>DNDIncoming</dt>
<dd>Some dragged object is offered to the receiving object</dd>
<dt>RecieveFocus</dt>
<dd>The receiving object becomes the "current" control</dd>
<dt>LoseFocus</dt>
<dd>The receiving object loses the "current control" status</dd>
<dt>ShortCut</dt>
<dd>The user pressed a possible shortcut key</dd>
<dt>StateChange</dt>
<dd>The main property of the sender changed</dd>
<dt>Destroy</dt>
<dd>The sender is being destroyed/deallocated/...</dd>
</dl>
<a name="advancedintro"></a>
<p>I looked through some existing GUI toolkits, widget libraries etc
(e.g.Gtk, Qt, FL) and "took" the IMHO best aspects of them.
Something like the signal/slot concept of Qt is really elegant but
(besides the copyright problems) it needs a seperate preprocessor,
and this IMHO defeats this elegance.</p>
<p>Gtk and FL use a quite similar concept for connecting signals
and handlers, but none of them looked really good to me. Gtk is
too procedural and FL stores the event data in some central place
and thus should have some problems with multithreading etc.</p>
<br>
<h3>The Design</h3>
<p>Obviously almost all GUI components are at least potential signal
senders (just consider the StateChange event). So it would be convenient
to inherit all from a common base class providing an interface and a minimal
implementation for signal handling. This base class would also be the only
entity keeping track of the signal dependencies of its child class.</p>
<p>As this list of dependencies should be dynamic, i.e. it has to be
possible to modify it at run time (in fact this should be the only
valid way as for compile-time dependency setting the programmer would
need access to the internal dependency management), this base class has to
provide methods to <em>connect</em> signals and handlers and to remove
these connections again.</p>
<p>Furthermore the objects themselves should not have to care about
what connections exist and how these have to be treated. So we
introduce a method to simply <em>emit</em> a signal of a certain type
to all connected handlers.</p>
<p>It could be best to provide some mechanism allowing specialized
signal handlers to be "plugged" into the default one. This method
seems to be in this case more versatile than inheritance, but it's
not quite as robust. Any comments ?</a>
<p>The additional information needed with some events is propably
best packed into some versatile data structure containing information
about the signal type it's used for, some fields for simple data types
and a pointer for every other data. To minimize stack usage and time overhead
for (de)allocation a set of such structurs could perhaps pre-allocated
somewhere with only a pointer being passed between signal sender and handler.
</p>
<p>One feature used in FL looks really interesting: every signal handler
returns a value indicating whether it accepts the incoming event.
With this, there could e.g. all known handlers for "shortcut" events
be checked, thus leaving the knowledge of who-reacts-to-what to the
individual widgets.</p>
<br>
<br>
<p><font size=-1><a href="index.html">Back to main GUI page</a></font></p>
<br>
<p><font size=-1>This document was written by
<a href="mailto:warewolf@chris2.mayn.de">Christian Reiniger</a>. Last
modification: 19.03.1998</font></p>
---------------------------------------
Cu
Christian
Christian Reiniger (Germany)
e-mail: warewolf@chris2.mayn.de