Wednesday, October 16, 2013

Implicit Delayed Initialization of GUI Components with Reflection

Previous sample code is a bit inferior compared to polymer HTML GUI specification style since the layout related codes were scattered around many places. It should have more declarative specification gathered in the close places.

One of the main reason for this mess was these sub components need to know the parent and it is impossible to get access in field declaration parts. So they must have been moved to constructor.
Also attribute related specification clutter the codes.

We can fix these issues by introducing two ideas.
  1.  use annotation for sub components in which attribute specification(small GUI related information, will be specified.
  2.  Implicit delayed initialization of sub components. This means when a component is instantiated, it will inspect these annotated sub component fields, and set the parent and additional information depending on the annotation and its parameters. The nice thing about this approach is that this procedure is recursive.
    when  the component is created, it starts initializing the sub components whose sub components are already initialized when the sub component is created.
Followings will be the new way to define layout.

class NameBadge extends Component with Monitor {

  @UI_TextInput(label: "Enter New Name:", String)
  final TextInputComp textInput = new TextInputComp();
  
  @UI_Button(label: "Generate pirate name")
  final ButtonComp button = new ButtonComp();
  
  @UI_Radio(label: "Male", name:"maleOrFemale")
  final RadioComp maleRadio = new RadioComp();
  
  @UI_Radio(label: "Female", name:"maleOrFemale")
  final RadioComp femaleRadio = new RadioComp();
  
  Element _createElement(Element elm) => 
      elm
        ..nodes.add(
            new Element.div()
              ..classes.add("entry")
              ..nodes.add(textInput.element)
              ..nodes.add(button.element)
              ..nodes.add(maleRadio.element)
              ..nodes.add(femaleRadio.element))
        ..nodes.add(
            new Element.div()
              ..classes.add("outer")
              ..nodes.add(new Element.div()..classes.add('boilerplate')..text = 'Hi! My name is')
              ..nodes.add(_initDiv0(new Element.div()..classes.add('name')..text = _badgename)));
  ...

  NameBadge(Component parent): super(parent, const[APP]) {
    this.button.onClick((e) { badgename = pirateName(); });
    this.maleRadio.onClick((_, comp){ male = true; });
    this.femaleRadio.onClick((_, comp){ female = true; });
    ...

No comments:

Post a Comment