Boost logo

Boost :

From: David Turner (dkturner_at_[hidden])
Date: 2004-03-03 13:06:28


Hi Peter

> Looks very promising!

Thanks :-).

> Why is cast<> using a what looks like a homebrew RTTI system?
> Is there something that makes
> dynamic_pointer_cast<T::element_type>(w) inappropriate?

Mm, er, um, ah... Yes, it is a homebrew RTTI system. It does nothing
that could not be achieved with dynamic_cast, but it's a bit less
weighty. By the way, the widget types already have names (the static
type() members) anyway, as a consequence of the use of window_base as a
factory. More on that below.

> Still on the cast<> subject, it should probably signal
> failure by throwing an exception derived from std::bad_cast,
> or maybe just return NULL, to allow the usual
>
> if( grid g = cast<grid>(w) )
> {
> // ...
> }

Yes, perhaps :-). I have no strong feelings on this. I suspect
exceptions are slightly better, since the primary use of cast<> is when
you already know what the widget type is. In fact, just about the only
place user code uses it is implicitly, when creating a widget:

    button = cast<button>(window.spawn(button_base::type()));

I should be very surprised if the cast failed in this scenario.

>
> Have you considered the 'on_delete', 'on_change' naming
> scheme for signals (events)? It seems more GUI/RAD-like.

Yes, but I think I'd rather name it after what it is (delete_signal)
than after when it happens (on_delete).

> Finally, when I see
>
> test->contain(create_label(test,
> "You pressed the \"Click me!\" button!\nHow clever!"));
>
> I wonder whether it would be feasible to eliminate the inner
> 'test', as it's logically redundant (a window probably can't
> contain something that is parented by another window).
> Although this would probably turn the architecture on its
> head, as it would require a new concept, a 'free widget'.
>

This comes down to a technical issue. First, I *really* don't want to
introduce "free widgets". Apart from anything else, it keeps the
implementation simple, creating the widget in the constructor and
destroying it in the destructor. However, there is a deeper problem:

On the Win32 platform, everything is a window. Windows have "parent"
windows, and "owner" windows. You can change the "parent", but you
can't change the "owner", which must be specified at creation.
Furthermore, funny things start to happen when you make a window a child
of a window that does not own it. This means you have to destroy the
HWND in order to reparent it properly. I can't necessarily guarantee
that this will be an easy process.

In order to avoid this (and similar problems on other platforms), I've
turned to the document object model. Essentially, a window models a
document, which then contains a hierarchy of nodes or widgets. You can
rearrange the hierarchy, but you can't take an element from one document
(window) and put it in another. The window_base class acts as a factory
for all the other widget types; thus there is really only one library
function of any significance: create_window().

So, in the code you underlined, what's actually happening is:

   // create a label belonging to the test window
   widget a = test->spawn("label");
   label b = cast<label>(widget);
   // set the text for the label
   b->set_text("blah blah blah");
   // make the label the immediate child of the window
   test->contain(b);

Compare this with the DOM:

   div = document.createElement("div");
   div.id = "links";
   body = document.getElementById("body");
   body.appendChild(div);

Regards
David Turner


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