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...