
On 06/07/2009, Gottlob Frege <gottlobfrege@gmail.com> wrote:
On Fri, Jul 3, 2009 at 4:34 PM, Felipe Magno de Almeida<felipe.m.almeida@gmail.com> wrote:
Sorry for the long delay, [snip]
Ok. I'm buying. How should we procede? I think cppgui should be only a widget system with signals, coordinate systems, etc. The layout and property systems should be decoupled. Cppgui should be be workable with eve, and with a new layout system as well.
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. If the widget uses overload to use some properties. Then using the parameters becomes a hell if/else code. 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 this means a DSEL would be crucial. What do you think?
- note that X, Y isn't really the widget's problem. The widget can calculate its size, but something else will tell it where to be.
Ok.
- measurements need to include more than just size - it is also worthwhile to know what the text *baseline* is, and where the ':' is (if any) in a text label (ie think of a label like "File Name:"). This is so we can align by ':' and by baseline. In general, widgets should be able to return a set of 'guidelines' (probably *named* guidelines like "baseline", etc), that a layout system can choose (or not) to align widgets to.
Ok. So we must define what must be returned by widgets. These should be defined for the layout, and the free functions required should mirror this. I don't understand why ':' position is required. Couldn't end of the widget be used instead?
We need to concentrate on properly describing the data first. A language (c++ or other) that says 'this data is a number (with min max etc)' or not only is this a string, but it is an email address (so that interfaces like the iPhone can adapt with @ symbols etc).
How do you intent this to work, without having to define all possible cases up-front, allowing extensibility?
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.
- 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.
"NumberEditor". Eventually we build up a standard set of descriptions, similar to standard 'concepts' in STL, type-traits, etc. ie, we can have 3 different widgets that all advertise as "NumberEditor", and that would mean they all implement the concept (and interface) of NumberEditor. I suppose a widget might need to advertise multiple interfaces that it implements, we would need to support that as well.
I would expect very few multiple interfaces. I think a adaptor to use multiple different I/O controls to the widget would make the system more scalable.
That's it for the widgets. The hard part is the 'widget selector' that matches the required widget to the data model. Currently, the 'widget selector' is usually the coder (via hand-written code, or RC files, or Eve, etc), or maybe the UI designer if you can teach them Eve (which I recommend you do!). But with descriptions, the 'widget selector' can be automated code. Consider an example:
struct Date // a poor date struct { int year; int month; string day; };
I think using fusion here would be great.
This struct needs to be described to the widget system: - the struct needs a descriptor string: "Date" // I'll comment about the naming later
How about a tag?
- the struct needs to be flagged as a 'struct' or 'aggregate' or 'record' - ie that it has members fields
Or everything that isn't a primitive as our terms (std::string would be a primitve, for example) we could consider a fusion sequence. Which means it is a aggregate of other aggregates and primitives. Which would give more information to the widget selector as the grouping of these primitives.
- each item within needs a descriptor "Year", "Month", "Day"
I guess a date would have sub-elements year, month and day. These descriptions could be derived from a date primitive.
- each item needs to be described by type - int, int, string - each item optionally gets min/max/default and/or an array/enumeration of possible values (ie [ "Monday", "Tuesday",...] )
I have to think about this type duality, where something could be a enumeration of strings or numbers.
Now, the point is that the 'widget-selector' system can look at this struct and do: 1. do I have a "Date" widget? if yes, use that and be done (or if I have more than one to choose from, check other constraints to decide the best one) 2. if I don't have a "Date" widget, I need to make a group of widgets, one for each member of "Date". ie: 2.1 Do I have a "Year" widget? 2.2 If not, do I have an "int" widget? (should, it is a base type) etc
Yes, but these should static information IMO.
Note that the widget-selector can decide on the proper selector not only by the descriptor tag "Day" or just type "string", but also be the optional criteria - if the string has an enumeration ("Monday", "Tuesday",...) then the choice might be a pop-up list box (or even a group of radio buttons if the list is short), or it could just default to an edit box (and force the validation to happen later).
Yes.
** As for naming - obviously, if I named my struct up there "Date" and your widget advertises that it can edit a "Date", then we had better be talking about the same structure. So maybe it would need "namespacing" like "MyApp.Date", and then an appropriate widget is unlikely to be found. - But think about "Boost.DateTime". You can write a widget that understands "Boost.DateTime" (and maybe a few people will write competing widgets) and my code will use the boost DateTime library, and we'll understand each other.
Or the widget could be reused with a adapter. But different widgets could be written for the same thing.
The important part is that, for the widgets, it isn't really more work - it is just communicating (in some agreed upon way) what it is that the widget is already doing.
I think a adapter layer would be appropriate too.
Then the layout engine can pick the best widget given the data model and the space constraints. For example, you might pick 3 radio buttons for clarity of choice or a dropdown list if little space is available. This should be decided at the layout level.
That would be really cool.
This is all doable. I've seen and/or built all the necessary building blocks to make it so.
Ok. Then there should be 3 libraries? Widget system, layout system and a data model system?
Yep. With the widget system being the easiest and first. Once the widget system describes itself enough, we can move on to layout and data model. (In fact, for a given widget set, layout info and data info can actually be completely separate. ie given a widget system that I can't modify (eg Win32 widget set), I could write complimentary functions to return metrics and data descriptions, and then hook all the pieces together independently.)
Yes, I think non-intrusiveness is important.
I guess the real interesting (first?) step is agreeing what the model/interface for a particular widget is or should be. ie why write a number-editing-widget before we can figure out how it should work. Once we figure out the interface and behaviour, then not only can we go and write it, but we can also label it "Boost.Number" and then away we go...
I think that some adapter is necessary, so that we don't need to derive a huge amount of widgets to different types.
Tony
I do like where this is going. Regards, -- Felipe Magno de Almeida