Sky Style Language
==================

This is a trimmed down version of the API in (style.md)[style.md]
that is intended to be a stepping stone to the long-term world where
there are no hard-coded properties in the engine.

The Sky style API looks like the following:

```dart

  // all properties can be set as strings:
  element.style['color'] = 'blue';

  // some properties have dedicated APIs
  // color
  element.style.color.red += 1; // 0..255
  element.style.color.blue += 10; // 0..255
  element.style.color.green = 255; // 0..255
  element.style.color.alpha = 128; // 0..255
  // transform
  element.style.transform..reset()
                         ..translate(100, 100)
                         ..rotate(PI/8)
                         ..translate(-100, -100);
  element.style.transform.translate(10, 0);
  // height, width
  element.style.height.auto = true;
  if (element.style.height.auto)
    element.style.height.pixels = 10;
  element.style.height.pixels += 1;
  element.style.height.em = 1;

  // each property with a dedicated API defines a shorthand setter
  // style.transform takes a matrix:
  element.style.transform = new Matrix(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
  // style.color takes a 32bit int:
  element.style.color = 0xFF009900;
  // style.height and style.width takes pixels or the constant 'auto':
  element.style.height = auto;
  element.style.width = 100;
  // all properties with a dedicated API can also be set to null, inherit, or initial:
  element.style.transform = null; // unset the property
  element.style.color = initial; // set it to its initial value
  element.style.color = inherit; // make it get its parent's value

  // you can create a blank StyleDeclaration object:
  var style = new StyleDeclaration();
  // you can replace an element's StyleDeclaration object wholesale:
  element.style = style;
  // you can clone a StyleDeclaration object:
  var style2 = new StyleDeclaration.clone(style);
```

The dart:sky library contains the following to define this API:

```dart
import 'dart:mirrors';
import 'dart:math';

typedef void StringSetter(Symbol propertySymbol, StyleDeclaration declaration, String value);
typedef String StringGetter(Symbol propertySymbol, StyleDeclaration declaration);
typedef Property ObjectConstructor(Symbol propertySymbol, StyleDeclaration declaration);

class PropertyTable {
  const PropertyTable({this.symbol, this.inherited, this.stringGetter, this.stringSetter, this.objectConstructor});
  final Symbol symbol;
  final bool inherited;
  final StringSetter stringSetter;
  final StringGetter stringGetter;
  final ObjectConstructor objectConstructor;
}

Map<Symbol, PropertyTable> _registeredProperties = new Map<Symbol, PropertyTable>();
void registerProperty(PropertyTable data) {
  assert(data.symbol is Symbol);
  assert(data.inherited is bool);
  assert(data.stringSetter is StringSetter);
  assert(data.stringGetter is StringGetter);
  assert(data.objectConstructor == null || data.objectConstructor is ObjectConstructor);
  assert(!_registeredProperties.containsKey(data.symbol));
  _registeredProperties[data.symbol] = data;
}

@proxy
class StyleDeclaration {
  StyleDeclaration() { this._init(); }
  StyleDeclaration.clone(StyleDeclaration template) { this.init(template); }
  external void _init([StyleDeclaration template]); // O(1)
  // This class has C++-backed internal state representing the
  // properties known to the system. It's assumed that Property
  // subclasses are also C++-backed and can directly manipulate this
  // internal state.
  // If the argument 'template' is provided, then this should be a clone
  // of the styles of the template StyleDeclaration

  operator [](String propertyName) {
    var propertySymbol = new Symbol(propertyName);
    if (_registeredProperties.containsKey(propertySymbol))
      return _registeredProperties[propertySymbol].stringGetter(propertySymbol, this);
    throw new ArgumentError(propertyName);
  }

  operator []=(String propertyName, String newValue) {
    var propertySymbol = new Symbol(propertyName);
    if (_registeredProperties.containsKey(propertySymbol))
      return _registeredProperties[propertySymbol].stringSetter(propertySymbol, this, newValue);
    throw new ArgumentError(propertyName);
  }

  // some properties expose dedicated APIs so you don't have to use string manipulation
  MapOfWeakReferences<Symbol, Property> _properties = new MapOfWeakReferences<Symbol, Property>();
  noSuchMethod(Invocation invocation) {
    Symbol propertySymbol;
    if (invocation.isSetter) {
      // when it's a setter, the name will be "foo=" rather than "foo"
      String propertyName = MirrorSystem.getName(invocation.memberName);
      assert(propertyName[propertyName.length-1] == '=');
      propertySymbol = new Symbol(propertyName.substring(0, propertyName.length-1));
    } else {
      propertySymbol = invocation.memberName;
    }
    Property property;
    if (!_properties.containsKey(propertySymbol)) {
      if (_registeredProperties.containsKey(propertySymbol)) {
        var constructor = _registeredProperties[propertySymbol].objectConstructor;
        if (constructor == null)
          return super.noSuchMethod(invocation);
        property = constructor(propertySymbol, this);
      } else {
        return super.noSuchMethod(invocation);
      }
    } else {
      property = _properties[propertySymbol];
    }
    if (invocation.isMethod) {
      if (property is Function)
        return Function.apply(property as Function, invocation.positionalArguments, invocation.namedArguments);
      return super.noSuchMethod(invocation);
    }
    if (invocation.isSetter)
      return Function.apply(property.setter, invocation.positionalArguments, invocation.namedArguments);
    return property;
  }
}

const initial = const Object();
const inherit = const Object();

abstract class Property {
  Property(this.propertySymbol, this.declaration);
  final StyleDeclaration declaration;
  final Symbol propertySymbol;

  bool get inherited => _registeredProperties[propertySymbol].inherited;

  bool get initial => _isInitial();
  void set initial (value) {
    if (value == true)
      return _setInitial();
    throw new ArgumentError(value);
  }

  bool get inherit => _isInherit();
  void set inherit (value) {
    if (value == true)
      return _setInherit();
    throw new ArgumentError(value);
  }

  void setter(dynamic newValue) {
    switch (newValue) {
      case initial:
        _setInitial();
      case inherit:
        _setInherit();
      case null:
        _unset();
      default:
        throw new ArgumentError(value);
    }
  }

  external bool _isInitial();
  external void _setInitial();
  external bool _isInherit();
  external void _setInherit();
  external void _unset();
}
```

Sky defines the following properties, currently as part of the core,
but eventually this will be moved to the framework:

```dart
class LengthProperty extends Property {
  LengthProperty(Symbol propertySymbol, StyleDeclaration declaration) : super(propertySymbol, declaration);

  double get pixels => _getPixels();
  void set pixels (value) => _setPixels(value);

  double get inches => _getPixels() / 96.0;
  void set inches (value) => _setPixels(value * 96.0);

  double get em => _getEm();
  void set em (value) => _setEm(value);

  void setter(dynamic value) {
    if (value is num)
      return _setPixels(value.toDouble());
    return super.setter(value);
  }

  external double _getPixels();
  // throws StateError if the value isn't in pixels
  external void _setPixels(double value);

  external double _getEm();
  // throws StateError if the value isn't in pixels
  external void _setEm(double value);
}

const auto = const Object();

class AutoLengthProperty extends LengthProperty {
  AutoLengthProperty(Symbol propertySymbol, StyleDeclaration declaration) : super(propertySymbol, declaration);

  bool get auto => _isAuto();
  void set auto (value) {
    if (value == true)
      _setAuto();
    throw new ArgumentError(value);
  }

  void setter(dynamic value) {
    if (value == auto)
      return _setAuto();
    return super.setter(value);
  }

  external bool _isAuto();
  external void _setAuto();
}

class ColorProperty extends Property {
  ColorProperty(Symbol propertySymbol, StyleDeclaration declaration) : super(propertySymbol, declaration);

  int get alpha => _getRGBA() & 0xFF000000 >> 24;
  void set alpha (int value) => _setRGBA(_getRGBA() & 0x00FFFFFF + value << 24);
  int get red => _getRGBA() & 0x00FF0000 >> 16;
  void set red (int value) => _setRGBA(_getRGBA() & 0xFF00FFFF + value << 16);
  int get green => _getRGBA() & 0x0000FF00 >> 8;
  void set green (int value) => _setRGBA(_getRGBA() & 0xFFFF00FF + value << 8);
  int get blue => _getRGBA() & 0x000000FF >> 0;
  void set blue (int value) => _setRGBA(_getRGBA() & 0xFFFFFF00 + value << 0);

  int get rgba => _getRGBA();
  void set rgba (int value) => _setRGBA(value);

  void setter(dynamic value) {
    if (value is int)
      return _setRGBA(value);
    return super.setter(value);
  }

  external int _getRGBA();
  // throws StateError if the value isn't a color
  external void _setRGBA(int value);
}

class Matrix {
  const Matrix(this.a, this.b, this.c, this.d, this.e, this.f);

  // +-     -+
  // | a c e |
  // | b d f |
  // | 0 0 1 |
  // +-     -+
  
  final double a;
  final double b;
  final double c;
  final double d;
  final double e;
  final double f;
}

class TransformProperty extends Property {
  TransformProperty(Symbol propertySymbol, StyleDeclaration declaration) : super(propertySymbol, declaration);

  void reset() => setTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);

  void translate(double dx, double dy) => transform(1.0, 0.0, 0.0, 1.0, dx, dy);
  void scale(double dw, double dh) => transform(dw, 0.0, 0.0, dh, 0.0, 0.0);
  void rotate(double theta) => transform(cos(theta), -sin(theta), sin(theta), cos(theta), 0.0, 0.0);

  // there's no "transform" getter since it would always return a new Matrix
  // such that foo.transform == foo.transform would never be true
  // and foo.transform = bar; bar == foo.transform would also never be true
  // which is bad API

  external Matrix getTransform();
  // throws StateError if the value isn't a matrix
  // returns a new matrix each time
  external void setTransform(a, b, c, d, e, f);
  external void transform(a, b, c, d, e, f);
  // throws StateError if the value isn't a matrix
}

external void autoLengthPropertyStringSetter(Symbol propertySymbol, StyleDeclaration declaration, String value);
external String autoLengthPropertyStringGetter(Symbol propertySymbol, StyleDeclaration declaration);
external void colorPropertyStringSetter(Symbol propertySymbol, StyleDeclaration declaration, String value);
external String colorPropertyStringGetter(Symbol propertySymbol, StyleDeclaration declaration);
external void transformPropertyStringSetter(Symbol propertySymbol, StyleDeclaration declaration, String value);
external String transformPropertyStringGetter(Symbol propertySymbol, StyleDeclaration declaration);

void _init() {
  registerProperty(new PropertyTable(   
    symbol: #height,
    inherited: false,
    stringSetter: autoLengthPropertyStringSetter,
    stringGetter: autoLengthPropertyStringGetter,
    objectConstructor: (Symbol propertySymbol, StyleDeclaration declaration) =>
                         new AutoLengthProperty(propertySymbol, declaration)));
  registerProperty(new PropertyTable(   
    symbol: #width,
    inherited: false,
    stringSetter: autoLengthPropertyStringSetter,
    stringGetter: autoLengthPropertyStringGetter,
    objectConstructor: (Symbol propertySymbol, StyleDeclaration declaration) =>
                         new AutoLengthProperty(propertySymbol, declaration)));
  registerProperty(new PropertyTable(   
    symbol: #color,
    inherited: false,
    stringSetter: colorPropertyStringSetter,
    stringGetter: colorPropertyStringGetter,
    objectConstructor: (Symbol propertySymbol, StyleDeclaration declaration) =>
                         new ColorProperty(propertySymbol, declaration)));
  registerProperty(new PropertyTable(   
    symbol: #transform,
    inherited: false,
    stringSetter: transformPropertyStringSetter,
    stringGetter: transformPropertyStringGetter,
    objectConstructor: (Symbol propertySymbol, StyleDeclaration declaration) =>
                         new TransformProperty(propertySymbol, declaration)));
}
```

