Programmatically building a UI for any object

gui

#1

Please bear with me if this is a stupid question, but I’m looking for a way to dynamically build editors (components & widgets) based on data at runtime.

Let’s say I have 200 subclasses of some “Generator” base class, each of which needs an editor to configure instances. Obviously, instead of manually coding and hard-wiring 200 custom components, I want to supply each class with a method that declares the widgets and bindings to member functions as some literal data. Pondering this, a few questions arise:

What’s the best way to keep generic components? Would a HashMap or other owning container do? How to distinguish between component types (templates vs. dynamic cast)? How to dispatch change notification messages to member methods symbolically (i.e. by name)?

Has anyone already done this? A few hints as to which direction to take would be very helpful.

TIA


#2

OwnedArray<Component> components;

probably

if( auto* p = dynamic_cast<P*>( components[i] ) ) { }
else if( auto* t = dynamic_cast<T*>( component[i] ) ) { }
//etc

have a look at this talk:


the part about ValueTreeObject is what you’ll be interested in.

It sounds like you’re trying to write something like Reaktor.


#3

Yes, that sort of application. Thanks for your input.

I would like to build the entire application’s UI on a declarative approach that does away with member variables for individual components.

Also the various *::Listener protocols seem overly static. I would much prefer attaching a method to every component individually, so these can be inherited, overridden and maintained on a per-widget basis. The question is just how to establish that link at runtime.


#4

This is very handy during prototyping. Some Components like Button provides std::functions you can populate at runtime, like std::function<void()> Button::onClick.

But the Listeners have also advantages, like once an interface is established, and the listening component wants to react to 5 different signals, a single foo.addListener (bar) does it all…
Also with the lambda approach, it is way too easy to violate the DRY principle.


#5

Just watched the ADC’17 ValueTree talk and must say I’m impressed by that work. ROLI rocks! I think ValueTree could be viable for those generator UIs, as the scope of value types is limited and well defined.

I now wonder if it makes sense to turn an entire app’s data model (e.g. the “song”) into a ValueTree.

I got 50 or so comparatively complex data classes and megabytes worth of data (not audio). My current approach is to have data know nothing about it being edited (no listeners attached to data). It’s just the leanest possible data laying bare.

Then there are tools that navigate and edit the data, taking responsibility for broadcasting change notifications globally. Views and other tools can subscribe to these notifications. Tools know about semantics and higher-level dependencies, so they can condense notifications to a minimum, e.g. collapse multiple changes into one. But this is a different, more general topic, of course.

(Ha! If this was an easy task, it wouldn’t take so many people to chew on it for decades and bring up so many different solutions and approaches)


#6

Agreed, in fact I also started to work on that a few years ago, to create the whole GUI and it’s Layout from ValueTrees.
The Layout part exists and works: github.com/ffAudio/ffLayouts
My plan was to do the Components as well via ComponentBuilder, but I found the serialisation and deserialisation not very well documented, and the communications on the forum gave a strong hint, that there won’t be future development on ComponentBuilder (it’s fate is tied to Projucer’s GUI-Editor).

The other reason against this approach is, it is so convenient to have the actual types of components while writing the business code behind the GUI.

But a fresh take on creating GUI from declarations like XML/CSS or declarative or other options are worthwhile to explore. You will find several threads in the last half year here on the forum.


#7

Thanks for the heads up re ComponentBuilder.

Maybe Projucer’s GUI-Editor will have a second life after a GUI framework emerges, whose editor could re-use much of its code. It may benefit from what ComponentBuilder already does. I think ValueTree XML looks like a good file format to use.


#8

Please don’t use ComponentBuilder! It was a failed experiment and will be removed at some point… it’s just left there for backwards-compatibility for the moment. (…and it could certainly use some comments to explain this too!)