piever/Widgets.jl

Design discussion: options and styling

Opened this issue · 0 comments

This issue is to discuss how to store options (meaning orientation of the widget, whether some things should be displayed etc.). and how to style / customize existing widgets.

Regarding the options discussion, overall I have the impression that the design originally proposed by @shashi in #16 works very well in the new framework, as using a Dict of Observable objects would be a simple way to allow modifying options from other widgets.

Options

I've realized that having some observables play a role in the layout function is a very good solution. For example, let's say that we have two children :a and :b and a third children :vertical (Observable of Bool), then one can simply do:

@layout! wdg $(:vertical) ? vbox(:a, :b) : hbox(:a, :b)

However I wonder whether :vertical and similar keyword arguments should be stored among the children or if it is better to have a separate options field. That would remove name conflicts and ambiguities and organize things a bit better but would require a different syntax (meaning in all these macros I should somehow distinguish whether a symbol refers to a child or an option). My personal preference is to have one unique OrderedDict with all the relevant information (either subwidgets, options, data that should be stored). Then @layout! can be used to only display some of them. The only thing to change is that I should maybe rename the fieldname as children is no longer very appropriate. I'm not sure what a better options would be though. Maybe wdg.arguments as it is where I'm storing all the widget's arguments?

Styling

Concerning styling and changing Node properties, my take is that the user should normally style in place the children of the widget that are nodes. To simplify this process, we should decide what is the "primary node" of a widget.

One option is that each widget would define which of its children is "primary" and styling the widget would by default style that node (it makes sense in a lot of widgets, for example in a slider widget it'd be the input node). In this case props(wdg) could maybe refer to props(node(wdg)).

Another option is that the node of a widget would basically be what is rendered, meaning wdg.layout(wdg). In this case the user would work with layout pretty much like with dom in a Scope, and one could consider forwarding all Node like functions to it, meaning:

style(wdg::Widget, dict) = (wdg.layout = x -> style(wdg.layout(x), dict); wdg) 

If one node is very important, it would simply be given an important name and be accessed by that name.