Closed bob-white closed 6 years ago
In other words:: I'd like to write a class without too much custom code where my compound thing has a tree of widgets:
Root
- label
- field
-form
-up-button
-down-button
and have a nice, clean and clear way of setting properties on root.form.down-button
wiithout needing to know that internal strucuture -- something like compound.decrement.backgroundColor = xxx
from the user side even though its root.form.down-button.backgroundcolor = xxx
under the hood
The tricky bit is how to make inot too painful to set up, ideally with a nice metaclass to make it really uncluttered
So something along these lines
class CompoundControlMeta(type):
# Some magic will happen here
pass
class CompoundControl:
__metaclass__ = CompoundControlMeta
class IntSpinner(CompoundControl):
_CONTROLS = {
'root': HorizontalStretchForm,
'field': IntField,
'label': Text,
'decrement': Button,
'increment': Button,
'form': VerticalStretchForm,
}
_HIERARCHY = {
'root': (
'label',
'field', {
'form': (
'increment',
'decrement'
)
}
)
}
CompoundControlMeta
would need to walk _CONTROLS
to generate the widget properties for routing those properly. It would also need to be able to walk _HIERARCHY
to generate the actual internal layout.
Other issues:
**kwargs
for each sub-widget?repr
return?CompoundControls
have a widget
field? If so which widget?wrap
/find
?Also something like this might benefit from #65. Or maybe something closer to the kv DSL from kivy.
I think I'm OK with the compound widget assembly process being code rather than data -- the list classes, which are effectively examples of compound widgets, needed some finagling to work the way I liked. At this early stage of the idea it feels like the main issue is a painless way for the owning compound object to expose properties correctly -- some of them will be unique to the compoiund and need custom code but some will basically be pass-throughs of properites on lower level stuff.
I've been assuming that the widget
of the compound is going to be the root of the underlying pieces, so you can set things like position, size and so on easily
Updated the PR with just another thought. Instead of subclassing any mGui object, this acts more as a facade.
It uses __getattr__
and __setattr__
to route attribute lookup to the root object, if a field happens to exist there, otherwise it defaults to normal behavior. Also, given the way __getattr__
works, anything that already exists on the facade gets precedence.
Each of the controls is exposed as a public field, so no need to generate properties to route information to them.
Still have to manually generate any IntSpinner
specific code though, which seems like a place where we can probably get a metaclass involved to simplify it.
Initial example is an IntSpinner. Based on the conversation over at TAO
Basically just expands the
IntField
with a newstep
value, and links the two buttons to increment and decrement the value.If we want to further expose the button commands, we'd need some kind of descriptor to route the
Events
from the sub commands, but that should be fairly simple.