Closed Updownquark closed 7 years ago
The big challenge with this one and the reason I took this next is that in order to do this elegantly, I need to tackle the issue of widget models. I need to design a system that makes it easy to implement a widget with a simple or a complex model and to define that model's implementation when instantiating the widget in XML.
Here are some thoughts on how it could be done.
The bottom line is that it needs to be easy to:
From XML one needs to be able to specify something like:
<spinner type="int" min="0" max="100" interval="5" value="model.x" />
in addition to
<spinner value="model.x" increment="model.incX" decrement="model.decX" />
I believe I have settled on a mechanism for implementation of models within templates. The template XML's model value parser will accept references to instance methods (and maybe fields) within the template subclass. So the spinner will specify its text field something like this:
<text-field value="this.getTFValue()" format="this.getTFFormat()" validator="this.getTFValidator()" />
and those methods in the Spinner class will return appropriate observables based on how the spinner is configured in the source MUIS file it is defined in.
This does leave more of the wiring of new widgets to the widgets themselves, but at the moment at least this seems necessary, since the widget implementations need all the power afforded by this responsibility.
I've run into a problem with my latest decision. At the moment, there's no way for me to evaluate "this" to mean the templated parent of a widget defined in a template file. Further complicating this is that conceivably widgets defined in a template file may be for children of other templated widgets within that file. For example, a template may contain a combo box for which it specifies items that the user may select. One of these items may need to refer to the outer template widget (not the combo box). The expression "this.xxx()" is appropriate since it occurs in the definition of the outer template widget, but the information that says "this.xxx()" was defined in the outer template widget's scope is lost when the template widget is instantiated.
I was thinking that maybe having the context in which the string of an attribute was defined might not be a bad thing. So when parsing from a normal MUIS file, this context would always be the parent element or possibly the document. In style files, the context would be the toolkit or maybe the environment. In template files the context would be the template widget. And of course variables available in higher contexts would be available from lower ones. It makes sense that the string given for an attribute should be parsed and evaluated in the appropriate context where it was specified, not just the element's general context at runtime. Now I'm trying to think whether there are any problems with this.
So I think that's done. Now I just have to decide how to actually evaluate the model getters on a template widget since those getters probably should not always be public.
I haven't been tagging this issue with recent commits, since they have nothing to do with the spinner in particular. But now I want to write a comment and I don't have a better to issue to write it under, so it's going here.
After gutting styles to make them observable, and after gutting attribute parsing similarly, I've run into a conceptual problem. Right now, MUIS is throwing an error on startup with parsing "raised-round" in styles. The reason for this is that it's being parsed as a subtraction expression, where it's intended to be parsed as a MUIS type. If I'm going to keep generic expression parsing (like subtraction) available for parsing attributes, then I'm not going to be able to specify identifiers with a dash in them like this. I'm not sure at the moment what the best solution is for this.
I have worked around this. I increased the priority of the muis identifier to be above subtraction to enable the use of muis types with dashes in them. If subtraction is needed, parentheses can be used, which will not be parseable as muis types.
Spinner works now!
I think a spinner would be a good widget to do next. It's not as complex as a combo box but it has several internal widgets that affect the value. I need to implement or perfect the scheme for having an internal model in a templated widget.