Boost logo

Boost :

Subject: Re: [boost] [rfc] cppgui
From: Domagoj Saric (dsaritz_at_[hidden])
Date: 2009-08-27 02:42:22


"Felipe Magno de Almeida" <felipe.m.almeida_at_[hidden]> wrote in message
news:a2b17b60906121714g6d209b47sd77f6c2d1a7aece6_at_mail.gmail.com...
> I've been working the past two years, on and off, unfortunately more
> often not, in a GUI library. But I have gotten back to it. And I
> wanted to make it usable. I believe there are some great things in it.
> This library has a named parameter interface which is extensible by
> the backend implementation.
> I've been working on a QT port, which have been fairly easy so far.
> My intention is to rework some parts of it, finish most widgets and
> the surface concept I've been working on and submit to review to
> boost.

> The library is in http://www.assembla.com/wiki/show/cppgui
> There's a svn and trac there that I use.
> The library requires the boost/funcitonal/factory.hpp library reviewed
> and accepted (?), which is not yet part of any boost distribution to
> compile.
> You will also need fusion to compile.
> I've tested with GCC 4.4.0/4.3.3 with QT and win32 with visual C++ 9.0.
> But should be pretty portable, including qt in visual C++.

hi, my first post here so an in-advance-apology if i "step on a 'house rule or
two'" ;)

> ...
> But I wanted some ideas on the controller interface and whatever might
> be useful too in improving the design before submitting.

i'm sorry i'm a bit late but...

..after a long, exhaustive, and frustrating, search for a 'proper'
cross-platform gui framework this post was a real sign of hope (finally, a
"booster" doing gui :)...your library is, with the exception of the
windows-only wtl, the only one (i found) using the crtp so an immediate
thumbs up for that one

as with any _c++_ library i expect/want it to be 'properly designed' in both
the 'effectivness' and the 'efficiency' fields (while i found no existing
library that would be even remotly satisfying...the worst 'offender' probably
being wx and qt with macros, 'exception-agnosticism',
"reinventing-the-universe" and binary sizes approaching/breaching the 10MB
mark)...

with that said i have a few wishes/suggestions:
 - make the library more configurable with a policy based design (oh the
buzzwords :)...some of the following points will give examples...

 - do not 'force'/'hard code' the use of boost::signals: i would argue that the
vast majority of guis "out there" are static in nature in the sense that
dynamic/runtime attachment/dettachment of possibly-multiple observers/handlers
is simply not necessary...making boost::signals an overkill for that 'majority
of cases' (if i remember correctly, adding a single boost::signal added ~50kB
to my binary, with all the optimizations available in msvc-9.0, and, as it was
previously mentioned, using the signals method can be overly verbose in cases
where it is not needed)...it would be ideal if it could be made to be a matter
of policy whether to use boost::signals, 'plain' boost::functions,
functors/function pointers as template parameters or, the 'old school',
deriving (static/crtp or dynamic polymorphism)

 - similar thing goes for child/parent "holding policy"...again i'd argue that
'most guis are static in nature' in the sense that their children or parent do
not change dynamically (their number and type, not that they themselves, as in
their internal state, do not change)...so it would be great if children could
be, for example, specified and/or held with mpl/fusion compiletime/static
containers as well as boost/stl runtime/dynamic containers/ranges

 - duplicating os provided functionality should be avoided as much as possible:
   - most (if not all) os gui implementations already use the handle/body idiom
(the C variant of the interface/implementation idiom) coupled with a messaging
system and/or a system of global functions that 'do' something on a handle (the
C variant of virtual functions, e.g. the SetWindowPos() win32 call that
sizes/moves any window, regardless of its 'type'/'class')...that makes the
typical/'traditional' 'c++' gui library approach of duplicating all that by
(always/'as a rule') 'newing' all widgets and accessing them through pointers
and virtual functions ('mostly') unnecessary and ('very') inefficient (if
anything stops/kills a compiler's and linker's optimization oportunities then
those are surely function pointers/virtual functions/collections of those like
signals and heap allocated 'forests of pointers').....with that said, even if a
particual ui requires access to widgets through a base class interface it still
does not imply that the interface must (always) be virtual (because the
underlying os api already made it that way)...in any case it would be nice if
it could, again, be a matter of policy whether to use an abstract
base/interface for a widget/widget set/hierarchy of widgets or not...
   - child/parent lists should not be separately maintained (like in member
containers) when that housekeeping information is already being maintained by
the os (e.g. win32 EnumChildWindows() )
   - thunks (like wtl) and extra 'user memory' for window classes (win32
WNDCLASS.cbWndExtra) can be used to avoid dual memory allocation (one by the
os when it creates the window and the other by the 'framework' for its os
window handle wrapper class)

 - stack allocated/local/temporary windows/widgets should be possible...for
those that must always be, from a design perspective, heap based/non local
intrusive_ptr should be used instead of shared_ptr when shared semantics is
also a must-by-design (making the design both more obvious and light(er)weight)

 - related to the above point is the welcome existence of both
'proper'/full/implementation window classes as well as 'attachable/hwnd
wrapper' classes (like in wtl) that have most of the same interface but
different usage scenarios

 - issues with basic types and structs (like Point and Rect) differing between
different OSs could perhaps be solved by using a wrapper class (for example
class boost::gui::rect : private RECT {..} on win32) which use the native
type(s) for storage and thus a no-op conversion to the native type when calling
os functions while providing member getters and setters for different types
(rect.size<int>(), rect.size<float>, rect.size<native_type> or something along
those lines)...

 - along with native implementations there could also be a universal opengl
implementation...and/but opengl windows/widgets/functionality 'should' also be
available when using a native implementation (for mixing/embedding opengl
windows in/with 'normal' ones)...

 - the library and/or its widgets should be able to work in plugin like
applications where you get a native handle for your (parent) window from the
host application and have to work from/with that...

- a knob/dial widget please ;)

 - (std::)streams, as a horrible horrible example of bloat and inefficency (i
dare anyone to step through a simple declaration/default construction of a
std::xstream object in release mode looking at the asm output), should be
avoided at all cost...if they are used somewhere care should be taken that the
compiler and linker can freely remove std::xstream crt code from the binary if
that particular (gui) library functionality is not used (not using them in
virtual functions and avoiding 'spaghetti' code is usually enough)

 - xml/layout/designer files and dynamic runtime ui construction functionality
is by all means very welcome as a powerfull feature but, as in the previous
remark, it should be implemented so that if one does not use it one also does
not end up with xml&co. code in one's binary

 - it would be welcome if the library's error handling/sensitivity/paranoia
could be configured. for example that the paranoid/'defensive programmers' can
say 'throw on even the least sign of trouble' while other can say
throw/check-for-and-report-an-error only when it is reasonable to expect that
it can actually happen (e.g. getting the string contents of a list box item
with a known valid index and a known valid list box handle into a preallocated
buffer 'cannot'/has no reason to fail even though the functions used to perform
the said action can return an error code...such cases should be 'handled' with
an assert imho)
   - furthermore it would be very welcome if the library could also properly
work with BOOST_NO_EXCEPTIONS (and use error codes for error reporting)...for
example if i'm writing a small utility and just want to bring up a simple
dialog i do not want to be forced to link with the crt, and double my binary
size, only to get exception handling...

 - ...as always..."you do not pay for what you do not use" ;)

--
 "That men do not learn very much from the lessons of history is the most
important of all the lessons of history."
 Aldous Huxley

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