Boost logo

Boost :

Subject: Re: [boost] [rfc] cppgui
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2009-07-16 02:19:59


On Sat, Jul 11, 2009 at 2:33 PM, Felipe Magno de
Almeida<felipe.m.almeida_at_[hidden]> wrote:
>
>>>
>> Yep, decoupled.  So for any layout system, widgets just need to
>> describe their measurements.  width, height, etc.  A few things to
>> learn from Eve and other experiences:
>> - widgets (or static/free functions related to the widget) should be
>> able to calculate their sizes based on inputs - ie a text label widget
>> should be able to return its size for a given text string
>
> Ok.I like the free functions idea. To use ADL and allow non-intrusive
> interoperability.
> But I didn't like the Eve approach. Creating the assemblage code
> for Eve is just too hard.

It is a bit to set up. But once set up, it becomes easy to do UI.
Image a company like Adobe where 20 or even 200 developers (or maybe
one day all Adobe dev) are all using the same GUI system. One where
you write some eve-script code, and the UI just pops up. And think of
how much UI there is in each Adobe app!! The cost of that one
developer to get eve connected to the GUI/widget system is nothing
compared to the savings.

That doesn't necessarily help the 'little guy', and it would be nice
if it was easier, but at least it helps see where it comes from.

The other place it 'comes from' is that is that it is another form of
an 'abstraction penalty'. Not a speed penalty, but a speed of coding
and understanding penalty. Highly abstract code (which is all Sean
Parent seems to write :-) often requires extra effort to bring it back
down to earth. Often it requires a couple of levels of 'narrowing' to
bring it back to concrete items.

> If the widget uses overload to use some
> properties. Then using the parameters becomes a hell if/else code.

I've had a static lookup table/map { property -> boost::function } to
help with this.

> I think the only manageable way to create a assemblage code is using
> some static information as well. To allow some metaprogramming and overload
> to help.

I think static info is good. I think there will also be cases that
need to be dynamic, but they can always uses switch or if/else to get
to the static info. More about static vs dynamic later.

> I don't understand why ':' position is required. Couldn't end of the
> widget be used instead?
>

Well, eve (and Adobe UI 'police', I mean UI designers) tend to be
quite fussy, so eve aligns to the ':' (I think). But forget about
that - alignment guides should be more generic and configurable. For
the widget, it should just somehow expose what alignments it has and
what type/category/tag each one is (and where they are, of course :-).

>> A few thoughts:
>> - Start at the bottom - with known data types (int, float, string).
>> - use a capabilities hierarchy.  ie a generic string-editing-widget
>> can be used as a number-editing-widget, just not the best one.
>> Similarly it can be a date-editing-widget, etc.
>
> I would think a I/O layer for edition would fit here.
> Where a string button would be a int button with a I/O controlling
> the string editing.
>

Adaption:
-------------

Two different sides of the coin here. Or levels of the problem, maybe.
eg: I need some data. So I write:

   get_data_input(data); // which calls
      present_ui_to_user(data); // which calls
          for each datum in data:
              show_widget(datum)

Somewhere in there, show_widget might find exactly the right widget,
or maybe it finds a more generic widget, and then uses an I/O layer to
customize it.
Or maybe it isn't so automatic, and the 'for each datum' isn't a loop but:
             create_custom_number_button(datum1)
                 which calls create_button, then sets some 'adapter' points

<snip>
> Or the widget could be reused with a adapter.
<snip>
> I think a adapter layer would be appropriate too.
<snip>
> Yes, I think non-intrusiveness is important.
<snip>
> I think that some adapter is necessary, so that we don't need to derive
> a huge amount of widgets to different types.
<snip>
>

Yep. Overall, we make some widgets, describe (somehow) what they do,
and then leave it at that. From there they can be adapted to more
specific contexts (by the end coder, but with some common/useful
adaptions living in boost).

Overall, you want the client coder to be able to make adaptions that
fit in seemlessly with the boost:: widgets.
Sometimes the adaptions will be one-time cases (ie pass in a
boost::function for input validation),
other times the adaptions will be reused enough by the client that
they decide to wrap them into separate widget classes.

Static vs Dynamic...
---------------------------

>> - As a widget-author, all you need to do is to "publish" your widget's
>> abilities.  ie a single string that describes your widget.
>
> string? I think we should do that by type_traits/concept_maps. As much
> static information as possible the better.
>
>> Consider an example:
>>
>> struct Date  // a poor date struct
>> {
>>    int year;
>>    int month;
>>    string day;
>> };
>
> I think using fusion here would be great.
>

YES. I was thinking code from Boost.Python/LangBinding but I see that
fusion has struct-to-fusion adaptor stuff, which would work great.

>
> How about a tag?
>
....
> Yes, but these should static information IMO.
>

Since the widgets are coded and compiled, then obviously their
capabilities are static (until someone writes a widget that does
nothing but load and execute Python code or something....)

But the 'build_ui_for_data(data)' tends to be more dynamic. Or a
combination of the 2. ie the data is statically typed, but some of
the UI decisions are dynamic (ie from RC file or script file etc).

Lots to think about here. I've written code where the data types and
widgets are 'plug-ins' - ie from DLLs. Think of video effects
plugins, or 3rd party Photoshop image filters - Photoshop knows very
little about the data params required by the plugin, nor what widgets
the plugin needs to use. (Or look at something like the OpenFX API for
an example.) Traditionally the answer to this has been to see the
data as a black-box and get the plugin to do all the UI itself. But
if the plugin could describe the data (or at least some of it) and/or
describe the widgets it could supply, then you could mix the custom
plugin UI with the standard Photoshop (or whatever 'host' app) UI.
This is particularly important for apps like AfterEffects, that want
to animate each x/y/z datum separately.

Anyhow, just saying there is a place for the dynamic side.
but that doesn't mean we can't have both:

lower layer: static info:
   <int_tag, etc>

higher layer: dynamic info:
   "int type", etc

the higher level then needs to do (ugly) if/else code to convert high
level to static level (and add checks, assertions, etc).

>
> I do like where this is going.
>

It might be going in many different directions - we need to be careful here.
It is at least *coming from* many different directions.
For me, I'm familiar with writing UI scripts, *which I can edit while
the program is running* (ie as long as the dialog being edited isn't
up) without changing my C++ code. Very dynamic! (I also want to let
the end-user modify the UI)

I suspect your cases are more static - possibly hard-coding all the UI
in C++. I DSEL would definitely be useful here.

Each direction has its uses. I've used both in a single interface
actually. (Interestingly, the static (DSEL in fact) case, for me, was
when I could create the entire section of UI (something like a 'tool
palette' in my case) 'automatically'. ie given the data to be
displayed, the widget selection and layout was automatically
determined. My goal would be to have all the UI be created this
way...)

Either way, coming at it from different directions can be a great
thing if we can make it work for each direction! It would be a good
sign of something useful.

Lastly, just because the 'ideal' is some large (impossible?) goal, it
doesn't mean you can't write something useful now. Looking at the big
goals just helps keep the small steps going in the right direction.

Tony


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