Showing posts with label Github. Show all posts
Showing posts with label Github. Show all posts

Tuesday, October 15, 2013

Reflective Interceptor, Monitor in Dart (Part 2)

Here is a sample code using Monitor. This sample was created from dart-tutorials-samples-Master/web/namebadge so that we can compare the differences.

In order to have getter/setter interception, we need to use Mixin with Monitor or extend Monitor.
We need to define monitored private fields, and public getter/setter corresponding to these private annotated fields.
The public getter/setter will call inherited methods get/set defined in Monitor.
This part is sort of mechanical, and may be a bit annoying to repeat, but it is better than using  code generator.
Also we need to define actions to be triggered when setter/getter are called using addSetListener, addGetListner.

When we use setter for private variables, like '_male = true;', then no actions are triggered. but if we use public setter, like 'male = true; ' then, it will trigger the registered actions.

Compared the both code size, Polymer looks better. But this approach is simpler and flexible. we don't have to rely on some convention between Polymer html and dart class bound to the polymer element.
Also there is no need to maintain two files system closely associated with each others. That will become maintenance night mare.

Since this is normal dart code, much more complicated things can be done without struggling with the restriction posed by Polymer.

I don't like ugly JSP style mixing of control in html file.
If we use cascading style to build html Element, the size of code is comparable(may be smaller?) to HTML. And we can do much more flexible thing in dart.

One advantage of using HTML is it uses less dart code. the code size can be smaller than program based one.
but if we develop dynamic web site, such a difference may be ignorable.

And we want to take generic web component approach like Form, Table, Polymer style approach does not work.

This is using my portable_mirror lib,  it works using both dart VM using dart:mirrors lib, and javascript mode with static stubs.

import 'dart:html';
import 'dart:math';

import "../../gui_component/lib/monitor_lib.dart";
import "package:gui_component/gui_component_lib.dart";

class NameBadge extends Component with Monitor {
  static const String APP = "g_namebage";
  TextInputComp textInput;
  ButtonComp button;
  RadioComp maleRadio;
  RadioComp femaleRadio;
  
  Element _div0;
  Element _initDiv0(Element e) => _div0 = e;

  @Monitored()
  String _badgename = 'Bob';
  @Monitored()
  bool _male = false;
  @Monitored()
  bool _female = true;

  String get badgename => get(const Symbol('badgename'));
  void set badgename(String v) => set(const Symbol('badgename'), v);
  
  bool get male => get(const Symbol('male'));
  void set male(bool v) => set(const Symbol('male'), v);
  
  bool get female => get(const Symbol('female'));
  void set female(bool v) => set(const Symbol('female'), v);
  
  NameBadge(Component parent): super(parent, const[APP]) {
    this.textInput = new TextInputComp(this, "Enter New Name:", String);
    this.button = new ButtonComp(this, "Generate pirate name", (e) { badgename = pirateName(); });
    this.maleRadio = new RadioComp(this, "Male", "male", _male, name:"maleOrFemale")..onClick((_, comp){ male = true; });
    this.femaleRadio = new RadioComp(this, "Female", "female", _female, name:"maleOrFemale")..onClick((_, comp){ female = true; });
    
    addSetListener(const Symbol("badgename"), (NameBadge target, String old_value, String new_value){
      textInput.value = new_value;
      _div0.text = new_value;
    });
    addSetListener(const Symbol("male"), (NameBadge target, bool old_value, bool new_value){
      if (old_value == new_value) return;
      if (_male && _female) female = false;
    });
    addSetListener(const Symbol("female"), (NameBadge target, bool old_value, bool new_value){
      if (old_value == new_value) return;
      if (_female && _male) male = false;
    });
  }

  String pirateName() => (_female)?new PirateName.female().name:new PirateName.male().name;
  
  Element createElement() => addSubComponents0(newElem("div"));
  
  Element update() => addSubComponents0(initElem());
  
  Element addSubComponents0(Element elm) => addListeners(
      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))));
}

Following codes are from original dart-tutorials-samples-Master/web/namebadge.
In polymer version, we need to write both dart program and corresponding polymer html files. So this dart part is short compared to my monitor based implementation, but if we compare with dart and html, the code size difference will become less.

import 'dart:html';
import 'dart:math';
import 'package:polymer/polymer.dart';

@CustomTag('name-badge')
class NameBadge extends PolymerElement with ObservableMixin {
  @observable String badgename = 'Bob';
  @observable bool female = true;
  @observable bool male = false;
    
  NameBadge() {
    bindProperty(this, const Symbol('female'), () {
        if (female) {
          male = false;
        }
        notifyProperty(this, const Symbol('name'));
      });
    bindProperty(this, const Symbol('male'), () {
        if (male) {
          female = false;
        }
        notifyProperty(this, const Symbol('name'));
      });
  }

  void pirateName(Event event, var detail, Node target) {
    if (female) {
      badgename = new PirateName.female().name;
    } else {
      badgename = new PirateName.male().name;
    }
  }
}

<polymer-element name="name-badge">
  <template>
    <style>
    .entry {
      padding-bottom: 20pt;
    }
    .outer {
      border: 2px solid brown;
      border-radius: 1em;
      background: red;
      font-size: 20pt;
      width: 12em;
      height: 7em;
      text-align: center;
    }
    .boilerplate {
      color: white;
      font-family: sans-serif;
      padding: 0.5em;
    }
    .name {
      color: black;
      background: white;
      font-family: "Marker Felt", cursive;
      font-size: 45pt;
      padding-top: 0.5em;
      padding-bottom: 0.3em;
    }
    </style>
    <div class="entry">
      <label for="newName">Enter New Name:</label>
      <input type="text" id="newName" value="{{badgename}}">
      <button on-click="pirateName">Generate pirate name</button>
      <input name="maleOrFemale" type="radio" value="male" checked={{male}}>Male
      <input name="maleOrFemale" type="radio" value="female" checked={{female}}>Female
    </div>
    <div class="outer">
      <div class="boilerplate">
        Hi! My name is
      </div>
      <div class="name">
        {{badgename}}
      </div>
    </div>
  </template>
  <script type="application/dart" src="name_badge_element.dart"></script>
</polymer-element>



Saturday, October 5, 2013

Github: Reflective Web dev kit

Since several components based on reflection approach are now integrated, and working fine,  I uploaded the Dart project to Github:

https://github.com/calathus/reflective_web_dev_kit

There are a few more things to do, but this is not bad timing to clean up the project structure and store it to github.

here is the readme file:

Reflective Web Dev Kit

Overview

The goal of this project is to create a small end2end sample application using component based approach. Dart's mirror library will be applied to several area of web application, GUI, Database Access, client/server communication. Thus the project is called 'reflective' web dev kit.
See following blog site: http://dartathus.blogspot.com

1. portable_mirror

right now, darts:mirrors library cannot be used in javascript mode. So if we directly use this library, most of code cannot be run on browser. This lib provides a portable mirror API to support (small subset of) mirror features. There are two implementations for this API class. one depends on static classes, and the other depends on dart:mirror. No code changes are required to run application on javascripts mode or Dartium mode(using Dart VM).

2. json_mapper

json mapping based on mirror library. this automatically map json to corresponding entity instance

3.couchdb

dao api for couchdb based on mirror/json_mapper. this provides server side json_proxy, and client side couchdb dao library

4. gui_component

a framework to create web application using component based design, also table/form are implemented as generic class using mirror.

5. sample_app

This is a sample web application using these libraries. This web application supports CRUD operation using Table and Form.