Re: GUI Library Proposal for a Proposal

From: John Torjo <john.lists@torjo.com> Subject: Re: [boost] Re: Points vs Vectors / GUI Library Proposal for
To: boost@lists.boost.org Message-ID: <418F48F8.9050002@torjo.com> Content-Type: text/plain; charset=us-ascii; format=flowed
Back on the subject of a GUI library: I understand the motivation - that's where wxWindows arose. And I realise that nowadays a GUI library could be done in a much more modern C++ style. But my question is: is C++ the right language? I don't want this to descend into a religious war - C++ is my favourite language, but it isn't the best language for
I would say so ;) For instance, you can abstract away a lot of stuff (true binding of data to GUI controls): http://www.torjo.com/win32gui/save_dlg.html
Also, I want to allow, in the future, to bind STL containers directly to GUI list controls.
So, I would say a higher level language won't be of help here - because you would need to convert your data and send it back and forth.
Yes - this was the one major benefit that I could think of when I wrote my original reply. But once you've exposed the data in question to the scripting language of your choice, you gain quite a bit: - By attaching validation routines and the like in your scripting layer, you can tune these without having to rebuild your program, or even restart it if you're lucky. - You can plug data and validation routines into UI elements using your UI design tool! - You can also expose the resulting bindings at the application level for things like scripting support.
I remember the days when I used to do the UI in VB - it was quite a mixed feeling...
Yes, I can see how that might put one off 'higher-level' languages :)
every task. Would a higher-level, more dynamic language be more suitable for GUI work? In a perfect world, I'd do all my back-end stuff in C++
sometimes, certainly
and all the front-end development in, say, Python. By doing all the GUI work in C++ instead of an interpreted language, you: a) spend a lot more time recompiling.
that is unfortunately true :(
b) can less easily tweak a running program to try out different ideas.
We're missing a good GUI designer... But we're slowly getting there ;)
The GUI designer can't help with attaching data, validation routines or anything else, unless those things are exposed to script.
c) have to spend a lot of effort to construct a domain-specific language (c.f Spirit; see (a)).
Not sure what you mean...
Spirit goes to great lengths to make C++ look like a language for declaring grammars. It's a huge chunk of beautifully crafted template magic, that's clearly taken much time and effort. Because of its size, recompiling the parser you build with spirit takes a very long time (hence the reference to (a)). A parser generator such as ANTLR does the same job much quicker[1]. Similarly, you've constructed an elegant way of linking data, validation routines and UI elements together, from C++. Your usage examples are concise and expressive. But does that justify the sheer weight of header files that they require? One could write probably less than half as much code to deliver similar results using Pyrex and Python. It wouldn't run quite as fast as your code. But it would give a smaller, more versatile runtime. In fact, there's an embryonic project to do just that at: http://nz.cosc.canterbury.ac.nz/~greg/python_gui/
d) probably end up with a bigger codebase.
why so?
Because C++ isn't the tersest of languages :) George

- By attaching validation routines and the like in your scripting layer, you can tune these without having to rebuild your program, or even restart it if you're lucky.
true, but that validation is really trivial. When complex things come, you're in the dark. Again, the save_dlg concept I've told you before, it allows validation as well (really complex, if you wish).
b) can less easily tweak a running program to try out different ideas.
We're missing a good GUI designer... But we're slowly getting there ;)
The GUI designer can't help with attaching data, validation routines or anything else, unless those things are exposed to script.
That is not necessary true. I could for instance, create a simple wizard , which given a few C++ classes, allows you to select the data you want to show visually, some validation code, and could generate (some trivial) save_dlg::corresp class.
[...] Similarly, you've constructed an elegant way of linking data, validation routines and UI elements together, from C++. Your usage examples are concise and expressive. But does that justify the sheer weight of header files that
Thanks.
they require? One could write probably less than half as much code to deliver similar results using Pyrex and Python. It wouldn't run quite as fast as your code. But it would give a smaller, more versatile runtime. In fact, there's an embryonic project to do just that at:
If you're just for a few controls on a dialog or so + trivial validation, then I assume you would be better off with a scripting language. But GUI is so much more than that. It's delivering nice-looking dialogs to users, giving them a consistent look, showing them tooltips, etc., and sometimes using every support from the OS to make your app. as visually appealing as possible (for example, this could mean using ::AlphaBlend on Win2000). And lets not forget hyper links, HTML controls, splitters, bitmap buttons, easy tab dialogs, having your application on the sys tray, easy menu handling, and so on. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

But GUI is so much more than that. It's delivering nice-looking dialogs to users, giving them a consistent look, showing them tooltips, etc., and sometimes using every support from the OS to make your app. as visually appealing as possible (for example, this could mean using ::AlphaBlend on Win2000). And lets not forget hyper links, HTML controls, splitters, bitmap buttons, easy tab dialogs, having your application on the sys tray, easy menu handling, and so on.
Which is why I like to use the native GUI system if available to develop the GUI. Every platform has its own quarks, and the users really can tell the difference. Jared McIntyre

Jared McIntyre wrote:
But GUI is so much more than that. It's delivering nice-looking dialogs to users, giving them a consistent look, showing them tooltips, etc., and sometimes using every support from the OS to make your app. as visually appealing as possible (for example, this could mean using ::AlphaBlend on Win2000). And lets not forget hyper links, HTML controls, splitters, bitmap buttons, easy tab dialogs, having your application on the sys tray, easy menu handling, and so on.
Which is why I like to use the native GUI system if available to develop the GUI. Every platform has its own quarks, and the users really can tell the difference.
True. I want to make it easy for win32gui to be ported to other platforms. Then, when using win32gui, you'll be able to choose from: - use all of your OS's GUI power (go native) - choose the lowest common denominator (easier to go platform independent) - use a mix of the two Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

Which is why I like to use the native GUI system if available to develop the GUI. Every platform has its own quarks, and the users really can tell the difference.
True. I want to make it easy for win32gui to be ported to other platforms.
Then, when using win32gui, you'll be able to choose from: - use all of your OS's GUI power (go native) - choose the lowest common denominator (easier to go platform independent) - use a mix of the two
Best, John
You may want to change the name as the first part of porting 8-). But seriously, I need to sit down and take a closer look at what you already have so I can understand it better. I've really only had a chance to glance over it. Then I should be able to take more time to get into the discussion. But, what we are talking about is something I've wanted for a very long time, so I'd be very interested in pitching in where I can in whatever project comes out of this. I have a great deal of interest in seeing this developed out for WTL/Win32 and Cocoa (through Obj-C++) as well as GNUStep as a logical extension of the last one. Jared McIntyre

True. I want to make it easy for win32gui to be ported to other platforms.
Then, when using win32gui, you'll be able to choose from: - use all of your OS's GUI power (go native) - choose the lowest common denominator (easier to go platform independent) - use a mix of the two
Best, John
You may want to change the name as the first part of porting 8-).
Of course I will :) In fact - it's one of my near term (1-2 months) priorities. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

George van den Driessche wrote:
Yes - this was the one major benefit that I could think of when I wrote my original reply. But once you've exposed the data in question to the scripting language of your choice, you gain quite a bit: - By attaching validation routines and the like in your scripting layer, you can tune these without having to rebuild your program, or even restart it if you're lucky. - You can plug data and validation routines into UI elements using your UI design tool!
The one area where C++ is weaker than other languages for design time UI, and component, development is in its lack of a general run-time reflection mechanism. That is the only area which I see that is holding it back.

Edward Diener wrote:
The one area where C++ is weaker than other languages for design time UI, and component, development is in its lack of a general run-time reflection mechanism. That is the only area which I see that is holding it back.
A solution I've read about that I like to solve this is a separate 'pre-processor' that can pass your current project and look for certain members/member-functions and generate code to build up the appropriate required run-time information (e.g. it could recognise the '__published:' section of Borland's VCL classes and generate the code containg the list of members in that section which would be accessible at runtime) I'm sure this could be done in a compiler independent way as it would be parsing C++ code and generating C++ code to then be compiled by your compiler of choice. I can't remember where I first read about this idea but perhaps someone else has more information. Thanks Russell

Russell Hind wrote:
Edward Diener wrote:
The one area where C++ is weaker than other languages for design time UI, and component, development is in its lack of a general run-time reflection mechanism. That is the only area which I see that is holding it back.
A solution I've read about that I like to solve this is a separate 'pre-processor' that can pass your current project and look for certain members/member-functions and generate code to build up the appropriate required run-time information
(e.g. it could recognise the '__published:' section of Borland's VCL classes and generate the code containg the list of members in that section which would be accessible at runtime)
I'm sure this could be done in a compiler independent way as it would be parsing C++ code and generating C++ code to then be compiled by your compiler of choice.
I can't remember where I first read about this idea but perhaps someone else has more information.
.NET actually adds code to the source files using a component, based on design time decisions by the programmer, but it uses .NET reflection on the compiled component in order to do so. What you are suggesting is that one must parse component source code at design time in order to add code to the source which uses that component. This presupposes that the source code for all components used at design time must be available. Sorry if I find that a disagreeable thought. C++ Builder, as I am sure you know, actually uses reflection at run-time to create the correct values for properties and events handlers, without altering the source one sees for the user of the component. I actually feel this is cleaner. However both .NET and C++ Builder use run-time reflection of components and do not need component source in order to set up the correct values. Having to parse C++ code at design-time may be doable but I do not think it is a good way of doing things. Besides needing the source for the component, it is always possible that the source is incorrect and has errors. When run-time reflection can actually be used on the compiled component, there is no need for component source and the compiled component is always correct. For these reasons I much prefer a guaranteed run-time reflection mechanism rather than a source code parser for design time RAD developement. In the area of run-time reflection, Java, .NET, and Python have an obvious advantage over C++. Other than run-time reflection, I find C++ generally equal to, or better, than those other languages and environments, although I have a great fondness for Python nonetheless.

Edward Diener wrote:
C++ Builder, as I am sure you know, actually uses reflection at run-time to create the correct values for properties and events handlers, without altering the source one sees for the user of the component. I actually feel this is cleaner. However both .NET and C++ Builder use run-time reflection of components and do not need component source in order to set up the correct values.
Do you need the source? Aren't the header files enough which you will have for a C++ project? All this would do is generate a temporary cpp files which creates a global object which contains the reflection information which you can then traverse at runtime. I don't see how this is so different from what C++ Builder and .Net do. You don't require component source, only header file. It doesn't insert source code in to your cpp files, but creates temporary C++ files which get linked in to your project each time you build. Maybe I'm missing something here but I don't see the difference here. Cheers Russell

Russell Hind wrote:
Edward Diener wrote:
C++ Builder, as I am sure you know, actually uses reflection at run-time to create the correct values for properties and events handlers, without altering the source one sees for the user of the component. I actually feel this is cleaner. However both .NET and C++ Builder use run-time reflection of components and do not need component source in order to set up the correct values.
Do you need the source? Aren't the header files enough which you will have for a C++ project?
You have made a good point. I still feel uncomfortable about parsing header files to determine type information. If header files were used, since run-time reflection does not exist, one would have to inject the correct code into source files based on design-time decisions. But it does seem as if it could be done since header files in C++ must be distributed to allow a component to be used. Of course one would have to find the correct header file which corresponds to a particular component when one is dropped on a form from a toolbox of components. I also admit I do not relish the correct parsing of header files. The one difficulty of this is that the header file might present different information depending on compile-time options when the component was built, and these options may not be easily available to the design-time environment parsing it. Compile time options could determine what portions of the header file actually represent the component itself, via #defines, #ifs, and #ifdefs, and with headers including other headers the correct parsing may not at all be easy. This could theoretically get very difficult. I think that is why I am much more comfortable with some possible run-time reflection mechanism, which would always reflect the actual types and objects in the run-time code without having to discern them from header file source.
All this would do is generate a temporary cpp files which creates a global object which contains the reflection information which you can then traverse at runtime. I don't see how this is so different from what C++ Builder and .Net do. You don't require component source, only header file. It doesn't insert source code in to your cpp files, but creates temporary C++ files which get linked in to your project each time you build.
Whether one changes the source code or adds temporaray C++ files which then get compiled, is all the same to me. Aside from my objection above, I can not think of an argument why this would not work, but the parsing might be very difficult. I would still prefer a run-time reflection mechanism which was able to find out the internal types and values of a class or object at run-time in order to do property and event binding on the fly from resources. In this area I much prefer C++ Builder's hidden workings to ,NET's source code insertions, probably because a resource file, which encapsulates information into a single concept of resource information seems somehow more elegant than all those injections of code in .cpp files with markings that say "do not touch".

Edward Diener wrote:
Russell Hind wrote:
Edward Diener wrote:
C++ Builder, as I am sure you know, actually uses reflection at run-time to create the correct values for properties and events handlers, without altering the source one sees for the user of the component. I actually feel this is cleaner. However both .NET and C++ Builder use run-time reflection of components and do not need component source in order to set up the correct values.
Do you need the source? Aren't the header files enough which you will have for a C++ project?
You have made a good point.
Except headers are not enough in the face of the very common PIMPL pattern. -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com - 102708583/icq

Rene Rivera wrote:
Edward Diener wrote:
Russell Hind wrote:
Edward Diener wrote:
C++ Builder, as I am sure you know, actually uses reflection at run-time to create the correct values for properties and events handlers, without altering the source one sees for the user of the component. I actually feel this is cleaner. However both .NET and C++ Builder use run-time reflection of components and do not need component source in order to set up the correct values.
Do you need the source? Aren't the header files enough which you will have for a C++ project?
You have made a good point.
Except headers are not enough in the face of the very common PIMPL pattern.
That is very true, thanks for bringing it up as it butresses my argument that headers may not be good enough. However, practically PIMPL is normally used to encapsulate private information and design time programming will not care about that information, only about public properties and events.

Edward Diener wrote:
That is very true, thanks for bringing it up as it butresses my argument that headers may not be good enough. However, practically PIMPL is normally used to encapsulate private information and design time programming will not care about that information, only about public properties and events.
Yes, C++Builder works because the information you can set at design time (and therefore would be a candidate for parsing) is in the __published: section of a class which is basically public: except the compiler generates the reflection information for it. Regarding parsing, pre-processors could be used with correct compilation options to help generate accurate information, but I guess that wouldn't help the case where people have separate compilation options for different source files that would affect the layout of a header file. Have you looked at wxWidgets runtime type information stuff? What I'm thinking of would only provide the same information as that, but without the need for every class you want to have runtime reflection available for, you don't need to put all the members/member functions in defines. Cheers Russell

Hi
Have you looked at wxWidgets runtime type information stuff? What I'm thinking of would only provide the same information as that, but without the need for every class you want to have runtime reflection available for, you don't need to put all the members/member functions in defines.
There were some additional requirements for this kind of runtime information, as it was directed towards RAD-Tools and not for crossing languages - Grouping of properties (e.g. all props dealing with the layout of a control, dealing with the appearance etc) - Additional meta information whether the property should be persisted or not (properties useful for GUI-data binding but not for persistence), construction properties (after creation read-only), always read-only properties, help strings etc Best, Stefan

There were some additional requirements for this kind of runtime information, as it was directed towards RAD-Tools and not for crossing languages
- Grouping of properties (e.g. all props dealing with the layout of a control, dealing with the appearance etc)
- Additional meta information whether the property should be persisted or not (properties useful for GUI-data binding but not for persistence), construction properties (after creation read-only), always read-only properties, help strings etc
I see these on top of reflection. That is, once the RAD-tool has the reflection mechanism, then it can allow the user to say: - this is readonly - this is persistable, etc. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

Hi The wx RTTI was used in the ill-fated Borland RAD-Designer, so there we, as library developers, had to expose this information about our widgets, and we did this using the metadata mechanisms, just adding some more properties to the meta information about the properties... Best, Stefan
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of John Torjo Sent: Freitag, 12. November 2004 20:43 To: boost@lists.boost.org Subject: Re: [boost] Re: GUI Library Proposal for a Proposal
There were some additional requirements for this kind of runtime information, as it was directed towards RAD-Tools and not for crossing languages
- Grouping of properties (e.g. all props dealing with the layout of a control, dealing with the appearance etc)
- Additional meta information whether the property should be persisted or not (properties useful for GUI-data binding but not for persistence), construction properties (after creation read-only), always read-only properties, help strings etc
I see these on top of reflection. That is, once the RAD-tool has the reflection mechanism, then it can allow the user to say: - this is readonly - this is persistable, etc.
Best, John
-- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

You have made a good point. I still feel uncomfortable about parsing header files to determine type information. If header files were used, since run-time reflection does not exist, one would have to inject the correct code into source files based on design-time decisions. But it does seem as
I think reflection in general is very different from reflection for a GUI. When you have a GUI control, you want to apply reflection for a few of its properties. You won't have #ifdefs (or at least I would consider it bad design). Case in point: its interface should be extremely simple and easy to parse. You shouldn't need complex information like reflection for virtual functions, overloading etc. Even reflected property types should be of trivial types: 1. build in types 2. std::string 3. types that can simply be read from /written to strings. For case 3., you might also have a validation function which will be used in design-mode to validate user input. At least that's what I want. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

John Torjo wrote:
You have made a good point. I still feel uncomfortable about parsing header files to determine type information. If header files were used, since run-time reflection does not exist, one would have to inject the correct code into source files based on design-time decisions. But it does seem as
I think reflection in general is very different from reflection for a GUI.
When you have a GUI control, you want to apply reflection for a few of its properties. You won't have #ifdefs (or at least I would consider it bad design). Case in point: its interface should be extremely simple and easy to parse.
That is the ideal. I do not deny that in most situations you are correct but most is not necessarily all. It is possible, after all, to create components which act differently depending on a number of compile time factors although it is obviously quite uncommon.
You shouldn't need complex information like reflection for virtual functions, overloading etc.
Generally not for design-time programming. I agree.
Even reflected property types should be of trivial types: 1. build in types 2. std::string 3. types that can simply be read from /written to strings.
Here is where we disagree. One should be able to make properties which encapsulate classes or data structures themselves. It is quite common to make a property which is a pointer to another component type and allow the programmer at design time to connect that property to another component which has also been dropped into the design time environment and configured separately. Furthermore it is also quite common to make embedded properties which are themselves small components with their own sub-properties. This latter is often a good way to organize properties in a way that makes it easier for them to be understood and set. Event handlers can also take parameters which are components or classes in and of themslves. Often a good creation of components, with their design time properties and events, involves the ability to organize everything coherently and in an easily understood way. This sometimes necessitates grouping both properties and events into sub-components and component pointers. Your idea of "trivial" types sounds nice but to me it is like the C++ programmers who think they can do all they want with only trivial programming. It is a nice dream but eventually runs into a reality in which complexity is actually the correct design.
For case 3., you might also have a validation function which will be used in design-mode to validate user input.
Both .NET and C++ Builder allow one to do validation of a component property at design-time, which is actually run-time for the component. This is another reason why run-time reflection is better than header file parsing. One is already in a run-time environment for components when they are being dropped on a form, so why not use the full abilities of a run-time reflection mechanism.
At least that's what I want.
Best, John

Even reflected property types should be of trivial types: 1. build in types 2. std::string 3. types that can simply be read from /written to strings.
Here is where we disagree. One should be able to make properties which encapsulate classes or data structures themselves. It is quite common to make a property which is a pointer to another component type and allow the
Really? Which would those be? I can only think of the "buddy" property of a spin control.
programmer at design time to connect that property to another component which has also been dropped into the design time environment and configured separately. Furthermore it is also quite common to make embedded properties which are themselves small components with their own sub-properties. This latter is often a good way to organize properties in a way that makes it easier for them to be understood and set.
This can be achieved visually in other ways. That is, once you create a control, you can define (probaly in a easy scripting language) how to group properties together.
For case 3., you might also have a validation function which will be used in design-mode to validate user input.
Both .NET and C++ Builder allow one to do validation of a component property at design-time, which is actually run-time for the component. This is another reason why run-time reflection is better than header file parsing. One is already in a run-time environment for components when they are being dropped on a form, so why not use the full abilities of a run-time reflection mechanism.
You could be right. I need to put more thought into it. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

John Torjo wrote:
Even reflected property types should be of trivial types: 1. build in types 2. std::string 3. types that can simply be read from /written to strings.
Here is where we disagree. One should be able to make properties which encapsulate classes or data structures themselves. It is quite common to make a property which is a pointer to another component type and allow the
Really? Which would those be? I can only think of the "buddy" property of a spin control.
You are thinking of components as only visual GUI classes. Clearly there is a wealth of components, which any good application framework should allow, which has nothing to do with GUI classes but which can be used with a GUI classes or in a data module. Component programming in RAD application frameworks has as much to do with adding non-visual components to a form or data module as it has to do with adding visual components to a form. A typical example is an edit control which would allow validation based on a regular expression having a property which is a pointer to a regular expression component which allows the various possibilities of a regular expression to be also configured at design-time. The end-programmer would drop the specialized edit control onto a form, drop the non-visual regular expression component onto a form ( or data module ), and assign the property of the edit control which is a pointer to a regular expression component to the regular expression component itself. There are endless possibilities in this scenario where disparate components can be configured separately and then united through a property on one of them which points to a type of the other. This can currently be done in all the major RAD environments of which I know. Your "buddy" property is only a minor example of this general RAD programming paradigm.
programmer at design time to connect that property to another component which has also been dropped into the design time environment and configured separately. Furthermore it is also quite common to make embedded properties which are themselves small components with their own sub-properties. This latter is often a good way to organize properties in a way that makes it easier for them to be understood and set.
This can be achieved visually in other ways. That is, once you create a control, you can define (probaly in a easy scripting language) how to group properties together.
Your "easy scripting language" seems like a solution which I do not want to foster on end-users. The usual ability to present properties of a components grouped in a subclass of that component is supported in C++ Builder, .NET, and Java Beans, among the RAD environments which I know well.
For case 3., you might also have a validation function which will be used in design-mode to validate user input.
Both .NET and C++ Builder allow one to do validation of a component property at design-time, which is actually run-time for the component. This is another reason why run-time reflection is better than header file parsing. One is already in a run-time environment for components when they are being dropped on a form, so why not use the full abilities of a run-time reflection mechanism.
You could be right. I need to put more thought into it.
I was making the case of a run-time reflection mechanism as an ideal C++ should pursue in order to promote RAD programming in application frameworks built around C++. Without native C++ for a run-time reflection mechanism it would certainly seem hard for you to do it in your GUI library, but if you could figure out a way, if only within your environment, it would certainly be a coup. But my argument about this was meant originally for Russell Hind in his discussion about possibility providing RAD support via header file parsing. Eddie

You have made a good point. I still feel uncomfortable about parsing header files to determine type information. If header files were used, since run-time reflection does not exist, one would have to inject the correct code into source files based on design-time decisions. But it does seem as
I think reflection in general is very different from reflection for a GUI.
When you have a GUI control, you want to apply reflection for a few of its properties. You won't have #ifdefs (or at least I would consider it bad design). Case in point: its interface should be extremely simple and easy to parse.
You shouldn't need complex information like reflection for virtual functions, overloading etc.
Even reflected property types should be of trivial types: 1. build in types 2. std::string 3. types that can simply be read from /written to strings.
For case 3., you might also have a validation function which will be used in design-mode to validate user input.
At least that's what I want.
I'm not sure that is valid. Take a TreeList as an example. The items in a treelist are almost always sub-classes, based on some type of generic 'TreeItem' class. I'm not sure that a TreeItem can always be represented as a string. Also, the position of a treeitem (within the treelist), may not necessarily be able to be stringified. Mathew

Even reflected property types should be of trivial types: 1. build in types 2. std::string 3. types that can simply be read from /written to strings.
For case 3., you might also have a validation function which will be used in design-mode to validate user input.
At least that's what I want.
I'm not sure that is valid.
Take a TreeList as an example. The items in a treelist are almost always sub-classes,
based on some type of generic 'TreeItem' class. I'm not sure that a TreeItem can always be represented as a string. Each node can be identified by a unique ID (which can be an integer, which can be then converted as a string). Thus, besides all IDs, you need to persist all parent-child relationship - which I think is about it. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

Edward Diener wrote:
very difficult. I would still prefer a run-time reflection mechanism which was able to find out the internal types and values of a class or object at run-time in order to do property and event binding on the fly from
http://www.litwindow.com/Library/Articles/articles.html Data abstraction layer, Part 1 (other parts will follow soon) Data abstraction layer is a run-time reflection mechanism able to find out the internal types and values. It does not require any modification to the original C++ type definition and thus works fine for third-party headers. It also does not require any preprocessor or header parsing. See http://www.litwindow.com/lwl/doc/html/comparison_10x.html at the end of the document "Preparing to use the Lit Window Library" to see the costs you have to invest to create the data abstraction object for an aggregate. Comments welcome Regards Hajo Kirchhoff

On Mon, 8 Nov 2004 19:18:13 -0500, Edward Diener <eddielee@tropicsoft.com> wrote:
The one area where C++ is weaker than other languages for design time UI, and component, development is in its lack of a general run-time reflection mechanism. That is the only area which I see that is holding it back.
I've been toying with using the properties library Reece Dunn recently submitted (in the boost-sandbox CVS) for this purpose. I've got something very sketchy, but it relies on a visitor pattern to "pass" type information to client code in a manner similar to Boost.Variant. I'd prefer a way of storing the type information for each reflectable class statically, and in a generic way, e.g. something like std::map<std::string, property>. This would enable the reflection code could be decoupled from the reflected classes entirely and just operate on this property meta-data. It would also allow client code to lookup individual properties (e.g. by name) instead of having to visit all of them. I'm stumped by how to store this information in any sort of container though, since the properties are of different types. Any thoughts, or is this madness? -- Caleb Epstein caleb.epstein@gmail.com

On Tue, 9 Nov 2004 09:38:35 -0500 Caleb Epstein <caleb.epstein@gmail.com> wrote:
I'm stumped by how to store this information in any sort of container though, since the properties are of different types. Any thoughts, or is this madness?
If I understand what you are asking, I have been using a "type index" container for a while. However, my solution depends on using static data members of a template class. Specifically, I have a mechanism that assigns a unique runtime integral value to each type, and then that value is used to index into a vector or map of boost::any, and then since it "knows" the type, a cast is performed to the appropriate type. Does that sound like what you are asking about, or am I out to lunch?

On Tue, 9 Nov 2004 10:00:48 -0500, Jody Hagins <jody-boost-011304@atdesk.com> wrote:
If I understand what you are asking, I have been using a "type index" container for a while. However, my solution depends on using static data members of a template class. Specifically, I have a mechanism that assigns a unique runtime integral value to each type, and then that value is used to index into a vector or map of boost::any, and then since it "knows" the type, a cast is performed to the appropriate type.
Does that sound like what you are asking about, or am I out to lunch?
Sounds like it could be. Could you send along an example? -- Caleb Epstein caleb.epstein@gmail.com

On Tue, 9 Nov 2004 10:08:43 -0500 Caleb Epstein <caleb.epstein@gmail.com> wrote:
Sounds like it could be. Could you send along an example?
Sure. Give me a little time to try and pull it out. Right now, I use it in what I call a dynamic_tuple, which gives me a structure very much like a boost::tuple, but the tuple can be extended at run time (and still preserve the compile time mechanisms as well). I will see if I can get it posted later today...

I'd prefer a way of storing the type information for each reflectable class statically, and in a generic way, e.g. something like std::map<std::string, property>. This would enable the reflection code could be decoupled from the reflected classes entirely and just operate on this property meta-data. It would also allow client code to lookup individual properties (e.g. by name) instead of having to visit all of them.
Not sure if I understood you correctly, but if I did, why not do this: // define globals in a source file // etc. reflected_property r1(&window::get_enabled, &window::set_enabled, "enabled"); reflected_property r2(&window::get_visible, &window::set_visible, "visible"); Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

On Tue, 09 Nov 2004 22:29:06 +0200, John Torjo <john.lists@torjo.com> wrote:
I'd prefer a way of storing the type information for each reflectable class statically, and in a generic way, e.g. something like std::map<std::string, property>. This would enable the reflection code could be decoupled from the reflected classes entirely and just operate on this property meta-data. It would also allow client code to lookup individual properties (e.g. by name) instead of having to visit all of them.
Not sure if I understood you correctly, but if I did, why not do this:
// define globals in a source file
// etc. reflected_property r1(&window::get_enabled, &window::set_enabled, "enabled"); reflected_property r2(&window::get_visible, &window::set_visible, "visible");
How would one go about associating all of the reflected_properties with the "window" class regardless of their type? I am imagining a repository of properties that users can query and enumerate, e.g.: typedef vector<reflected_property> prop_list; prop_list props = reflection::get_properties ("gui::window"); for (prop_list::const_iterator i = props.begin (); i != props.end (); ++i) cout << i->first << '=' << i->second.get (); I don't see how something like this can be made to work if the reflected_property is templated on the type of data that is being reflected. Conversely, I don't see how reflected_property can be made to handle any type of data without being templated on the data type. I think this is do-able with a visitor-based approach where the reflected class (since it knows its own type info) invokes methods on a visitor object (cf. Boost.Variant visitor), but I just can understand how this can be made to work when turned on its head as in the code above. -- Caleb Epstein caleb.epstein@gmail.com

Caleb Epstein wrote:
On Tue, 09 Nov 2004 22:29:06 +0200, John Torjo <john.lists@torjo.com> wrote:
I'd prefer a way of storing the type information for each reflectable class statically, and in a generic way, e.g. something like std::map<std::string, property>. This would enable the reflection code could be decoupled from the reflected classes entirely and just operate on this property meta-data. It would also allow client code to lookup individual properties (e.g. by name) instead of having to visit all of them.
Not sure if I understood you correctly, but if I did, why not do this:
// define globals in a source file
// etc. reflected_property r1(&window::get_enabled, &window::set_enabled, "enabled"); reflected_property r2(&window::get_visible, &window::set_visible, "visible");
How would one go about associating all of the reflected_properties with the "window" class regardless of their type? I am imagining a repository of properties that users can query and enumerate, e.g.:
Of course. It all happens in the (templated) constructor of reflected_property. There, you can easily add this property to an array of reflected properties. Then, at runtime, you can query them (much like I've done with win32gui events). Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

NB: Subject line changed to better "reflect" this thread's topic On Wed, 10 Nov 2004 11:24:16 +0200, John Torjo <john.lists@torjo.com> wrote:
Of course. It all happens in the (templated) constructor of reflected_property.
So reflected_property itself is not a template class, but has a templated constructor? I wasn't aware that was legal.
There, you can easily add this property to an array of reflected properties. Then, at runtime, you can query them (much like I've done with win32gui events).
Do you have an implementation of this that I can examine? I'm not seeing anything obvious in the win32gui codebase. I'm just trying to understand how this would be implemented, and am drawing a blank. Any examples would be greatly appreciated. I do apologize if this is all plainly obvious to some people, but I'm having difficulty getting it through my thick skull. -- Caleb Epstein caleb.epstein@gmail.com

I do apologize if this is all plainly obvious to some people, but I'm having difficulty getting it through my thick skull.
// simple example struct property_holder_base { virtual ~property_holder_base() {} }; template<class m_class, class m_type> struct get_member_property_holder { typedef ... func; get_member_propert_holder(func f) : f(f) {} func f; }; template<class m_class, class m_type> struct set_member_property_holder { typedef ... func; set_member_propert_holder(func f) : f(f) {} func f; }; struct reflected_property { // templated constructor template<class m_class, class m_type> reflected_property( m_type (m_class::*getter)() const, void (m_class::*setter)(m_type), const std::string & name) { s_getters[name] = ptr(new ...(getter)); s_setters[name] = ptr(new ...(setter)); } typedef boost::shared_ptr<property_holder_base> ptr; static std::map<std::string,ptr> s_getters; static std::map<std::string,ptr> s_setters; }; struct window { bool is_enabled() const; void enable(bool); }; // define a global static namespace { reflected_property r(&window::is_enabled,&window::enable,"window::enabled"); } Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -- v1.5 - tooltips at your fingertips (work for menus too!) + bitmap buttons (work for MessageBox too!) + tab dialogs, hyper links, lite html

Caleb Epstein wrote:
I'd prefer a way of storing the type information for each reflectable class statically, and in a generic way, e.g. something like std::map<std::string, property>. This would enable the reflection
this is *exactly* what the 'data abstraction layer' of the "Lit Window Library" does. It stores a map<string, property> for aggregates and exposes the member information of the aggregate via aggregate::iterator, begin() and end() among other features. Please have a look at http://www.litwindow.com/library (homepage) and download the lwbase package from SF and browse the documentation. A quick introductory article is located at http://www.litwindow.com/Library/Articles/dataabstractionlayer.htm it is the first part of a series. The others will follow soon. Regards Hajo Kirchhoff

Yes - this was the one major benefit that I could think of when I wrote my original reply. But once you've exposed the data in question to the scripting language of your choice, you gain quite a bit: - By attaching validation routines and the like in your scripting layer, you can tune these without having to rebuild your program, or even restart it if you're lucky. - You can plug data and validation routines into UI elements using your UI design tool! - You can also expose the resulting bindings at the application level for things like scripting support.
The majority of my validation occurs in the logic layer of my applications. I don't usually put validation code in the GUI unless it is absolutely necessary, and then I usually design a special control (or a special validation object if the native GUI platform supports that type of idea). Even when I do that, the real validation still happens in the logic layer. I don't ever let my GUI access the data members of my logic layer directly. Perhaps this is why I would like the type of framework I described last week, and why I rather like Apple's Cocoa framework (even though I don't get to use it that often). So, a large use case for a higher level language to manage this code isn't useful for what I want, but some of it still is. It might be nice to use a high level script language to put in GUI dependencies (like, hide/show and enable/disable). But, its simple data binding and event handling I'm really looking for. I want less code if possible. Jared McIntyre
participants (11)
-
Caleb Epstein
-
Edward Diener
-
George van den Driessche
-
Hajo Kirchhoff
-
Jared McIntyre
-
Jody Hagins
-
John Torjo
-
Mathew Robertson
-
Rene Rivera
-
Russell Hind
-
Stefan Csomor