Here's a simpler approach that should work. I define a new kind of init expr that is a subclass of constraint but has a special wired-in installer in applyConstraint. This lets you write default style bindings with a minimum of overhead. This is untested, but I think you get the idea. In each LFC class where you want to default an attribute to a CSS style property, you will write:

attributes.attrname = new LzDefaultStyleExpr('attrname', 'css- property', 'attr-type', attr-default-default)

this is storing a default init expr into the class default attributes (which get merged in above any instance and subclass attrbutes). The arguments are the attribute to bind, the css property name to control that attribute, the LZX type of the attribute, and the fallback default value if there is no matching css property declaration.

Actually, we could probably use this simpler formulation in the tag compiler too to reduce the overhead of CSS bindings specified in LZX.

Index: core/LzNode.lzs
===================================================================
--- core/LzNode.lzs     (revision 14951)
+++ core/LzNode.lzs     (working copy)
@@ -1554,6 +1554,11 @@

   /** @access private */
   function applyConstraintExpr(expr:LzOnceExpr) {
+    if (expr instanceof LzDefaultStyleExpr) {
+      var se:LzDefaultStyleExpr = (expr cast LzDefaultStyleExpr);
+ this.__LZstyleBindAttribute(se.attribute, se.property, se.type, se.fallback);
+      return;
+    }
     // Apply the constraint method
     var constraintMethodName:String = expr.methodName;
     if ($debug) {
Index: core/LzDefs.lzs
===================================================================
--- core/LzDefs.lzs     (revision 14951)
+++ core/LzDefs.lzs     (working copy)
@@ -138,6 +138,23 @@
 };

 /**
+ * Private class used to define default style bindings in the LFC
+ * @access private
+ */
+class LzDefaultStyleExpr extends LzConstraintExpr {
+  var attribute:String;
+  var property:String;
+  var type:String;
+  var fallback:*
+ function LzDefaultStyleExpr(attribute:String, property:String, type:String, fallback=(void 0)) {
+    this.attribute = attribute;
+    this.property = property;
+    this.type = type;
+    this.fallback = fallback;
+  }
+}
+
+/**
  * Private class used to define an 'always' constraint (which also has
  * a dependency method)
  * @access private
Index: views/LaszloView.lzs
===================================================================
--- views/LaszloView.lzs        (revision 14951)
+++ views/LaszloView.lzs        (working copy)
@@ -1073,6 +1073,9 @@
  * The background color of the view.  Setting <code>bgcolor</code> to
  * <code>null</code> will make the view transparent.
  *
+ * The background color of the view is controlled by the CSS property
+ * <code>background-color</code>
+ *
  * May be set to any valid CSS color specification.  When read, will
  * be read as the equivalent numeric value.  To retrieve a CSS color
  * specification, use <code>this.presentAttribute('bgcolor',
@@ -1097,6 +1100,8 @@
   this.bgcolor = bgc;
   if (this.onbgcolor.ready) this.onbgcolor.sendEvent( bgc );
 };
+  // Install default CSS style
+ attributes.bgcolor = new LzDefaultStyleExpr('bgcolor', 'background- color', 'color', null);

 /** The horizontal offset of this view's upper left corner from the

On 2009-10-07, at 10:55, P T Withington wrote:

The key issue is making inheritance work.

The _only_ way to have it work is to mimic the way default attributes work in the tag compiler. They get compiled into an alist that gets merged with subclass lists.

The old way, where default values came in one list and constraints came in another, and styles in another, etc. Never really worked. There were always bugs where a constraint overrode a style that was closer when it should have taken the default, etc. Now, everything comes in one list, and there are special objects in the alist that become constraints or styles or databindings, but the inheritance is one uniform computation -- subclass values shadow superclass values as expected -- and you just run down the merged list and install the values (or bindings) that surface.

So, whatever we do in the kernel has to work with that model. There's no easy way. The tag compiler does a lot of work to build the attribute list from a tag spec. We either have to do that all by hand in the LFC, or we'd need to invent some new syntax and implement that in the script compiler. Or, as Henry has suggested (and you just reminded me), we could start allowing LZX into the LFC. This might be the way to go in the long run, but will require some changes to our build system, and obviously, we can't allow just _any_ LZX in the LFC, it has to be carefully bootstrapped. But you could imagine that LzView becomes something like LzViewInternal in the LFC, 99% implemented in Javascript, and then we write the actual <view> tag in LZX, with documentation and default values. This would probably make our documentation system much simpler too, since it would not have to parse Javascript for documentation. Seems like a nice long-term project for remodularization.

In the short term, here is a sketch of something you could flesh out that should give us most of what you want. There is the issue of how we document this -- I think it means editing the documentation of each attribute that you want to bind by default to a CSS attribute. This is the brute force way. We might be able to come up with a better solution where we create a new subclass of LzConstraintExpr that just records the correspondence between an attribute name and the CSS property name and builds a closure at runtime to install the correct constraint. I'll have to think about that a little more...

Reply via email to