From: James Grandy (jgrandy_at_[hidden])
Date: 1999-12-14 10:35:58
On Mon, Dec 13, 1999, Dave Abrahams <abrahams_at_[hidden]> wrote:
>> I don't think adding a windowing toolkit to boost is a good idea; it's
>> hard to come up with an integrated cross-platform framework that everyone
>> is going to be happy to use -- too many design tradeoffs at every level
>> of the job.
>A windowing toolkit is not a complete GUI framework. You could use other
>toolkits if things are loosely integrated enough. You seem to agree with me
>that too much integration is bad (at the end of the message), but do you
>really grasp the upshot of that idea?
I understand the difference between a 'toolkit' and a 'framework,', yes.
My language above was sloppy: you and I are both arguing for a toolkit,
I'm just saying that the toolkit doesn't have to be complete to be useful
-- it can include just a few more or less standard libraries that support
the construction of a larger GUI project.
><BeOS-like messaging facility snipped>
>This is an important concept, but not neccessarily the best design. Messages
>should just be member functions on an abstract base class, e.g.
[design sketch omitted]
>Possibly I'm not really talking about the same kind of facility you are,
Not quite. I'm not really talking about a callback facility, here.
Callbacks are useful, yes, but aren't the best way of doing event
dispatch; for this, I prefer a more traditionally object-oriented
approach. I'd like to use this kind of message-passing facility to do the
sort of complex event handling required in a well-built desktop
application. Here, we have to be able to dispatch events in complex ways,
track whether they have been "handled" by a given receiver, store them
for undo/redo, etc. BeOS uses stored messages to reconstitute a view
hierarchy, for example.
These protocols and conventions vary from platform to platform, and from
application to application, but the need to send a message through a
dispatcher to a possibly unknown recipient is, I think, close to a
universal need. The BeOS-style interface has the advantages that, (1)
messages can be arbitrarily dispatched (it's hard to determine the event
type of a function pointer), (2) messages can be stored and replayed, (3)
messages can be tracked (you can legislate a policy for return messages
and for knowing when a message has been 'retired') and (4) the facility
is thread-friendly and can even wrap an MPI-style multiprocessor
>> - classes for point, and rectangle. I template by scalar type, to support
>> "device" coordinates, which are usually integers, as well as "view"
>> coordinates, which can be integers (shorts or longs), fixed point
>> numbers, or floats. Conversion to platform-specific structures is
>> efficient here (even if coordinates have to be swapped), since the data
>> structures are so small.
>The most important thing missing from most of the coordinate classes I've
>seen (which mine support, though) is operators for the common, simple
>operations. For example, point classes should support vector arithmetic.
>Rectangles should be composable of two points, etc.
Agreed. Perhaps this is the clearest candidate for a boost library --
suitably templated, of course. (I just looked at my point class, and it
is doubly templated -- one for scalar value type, the other a bool
specifying row-major or column-major coordinate order. I'm not sure this
is really necessary -- swapping the coordinates when converting to a
platform-specific struct should be pretty efficient.)
>> - a class that encapsulates what I call "input state" -- mouse position,
>> keyboard state, etc. An instance of this class would be generated
>> whenever an interface event is raised, and passed around as a way of
>> encapsulating access to the input state at the time of the event. A
>> similar class is possible that encapsulates output state -- coordinate
>> system transforms, platform-specific references to drawing context, etc.
>I am firmly opposed to the existence of output state in APIs. More drawing
>bugs have been caused by relying on such environments being left in place
>than I can count. My APIs have no state. For coordinate transformation, you
>create new canvases by applying the transformation to existing canvases.
I've done it both ways. I didn't mean to raise the retained-state /
immediate-mode debate -- that's still a religious issue, IMHO. I'm
currently working with a 2D graphics package in which you draw by
invoking a member function of a Device class, passing it view, style, and
geometry. Here it's convenient to pass around just the Device reference;
it lets you do things like double-buffering at the appropriate level
without the views knowing. Of course, an immediate-mode API like OpenGL
lets you do this as well, without passing anything around at all. Perhaps
an output state class is not universally useful, because different
graphics libraries have different requirements in this area. (Note that
there will always be state -- if you use the same drawing code for screen
rendering and printing, you'll need to query something to find out, e.g.,
the DPI of the current device.)
>> Even if the input/output attributes are platform-specific, encapsulating
>> those details in one object is very useful when building event-driven
>> frameworks -- you can pass the object around without knowing what's inside
>A basic idiom I have tried to use for many platform-specific resources, etc.
>Passing references around is always easy.
>> I think there is potential to build a larger set of interface tools, but
>> I agree with Dave Abrahams that any such "framework" should use C++
>> idioms, and make use of namespaces to hide platform-specific details. I
>> strongly believe that the most successful UI framework is no more than a
>> composable set of cleanly separated sub-libraries; too much integration
>> is bad, in my opinion. I'd love to see generic programming used to design
>> a set of generic interfaces that support UI programming; I'm not yet sure
>> what it would look like, but I'm convinced it's worth the effort.
>There's some use for generic programming in UI design, but polymorphism
>really is an important concept in this domain. I don't think you can get too
>far away from traditional OOP here. Maybe I'm missing something?
Probably not :-) I was just wondering out loud. I've always been
interested in ways of statically legislating event-handling policy,
rather than relying on documentation. The classic error here: you write
an event handler and forget to call up the inheritance hierarchy, or make
the inherited call at the wrong point in your event handler. Another
place: the sometimes complex tangle of initialization code that often
builds up in view systems.
-- James Grandy Colorfield Digital Media, Inc. jgrandy_at_[hidden] 1.412.422.7516
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk