The Sticky Bit

* - *
|

Strut This Way

Oliver Steele posted this excellent article on his blog about the differences between the architecture for a conventional server-side HTML application and that of a rich internet app. Oliver ends up espousing a Service-Oriented Architecture, which is a recieved idea about how to architect network-based applications. Oliver's architecture diagrams are beautiful, but I'm more of a learn-by-example type (Software Architect vs. Client Programmer?) so I wanted to use a practical example that shows how an existing webapp would be modified to incorporate Laszlo.

Most server-side developers who are new to Laszlo have a single, over-riding question, which has a few variants: "How does Laszlo work with my existing web application framework (usually Struts)?" You can see this again and again and again on the Laszlo forums. I don't feel strongly about Struts one way or another, so I don't wish to treat in detail the questions about whether Struts is the right framework for doing MVC in a webapp. The fact is that while many developers aren't using Struts, they have usually built some kind of framework for separating actions and views, because that relationship is so tortured in HTML. The swirl of issues usually boils down to these two or three questions:

  1. How do I embed a Laszlo app into a larger HTML-based application flow?
  2. and

  3. How do I get the data I have on the server into Laszlo?
  4. and sometimes

  5. How do I get some of that good ol' model/view separation within Laszlo?

The answer to these questions is the subject of this entry. I'd like to show in practical terms exactly how to adapt an existing web application to use Laszlo. I'm going to do all of this without using Struts (or, in fact, any MVC framework) but hopefully you'll see how this is relevant to a more complex example.

Let's start with a small webapp. This is my photoviewer, and it is composed of three extremely simple jsps. You can try the webapp here:



In this simple example, login.jsp presents a simple form, whose submission is forwarded to album.jsp. album.jsp then looks for a username passed to it, and if found, stores the username and the user's album in the session. If you look at the code, you'll note that the user identity is not authenticated, and that everyone gets the same album, but hopefully you'll get the idea. Once the album is retrieved, it is stored, along with the user identity, in the servlet session.

I should point out that this example does exactly what a framework like Struts prevents -- which is that login.jsp is hooked directly to album.jsp. We should have the action for the form on the login be more like /do/Login which then calls album.jsp on success -- but hopefully you see how this is relevant to a more complex example. I have worked around this problem by checking for null values passed to album.jsp in the username. If the value is null, the identity and album is retrieved from the session; if it is non-null, the authentication/data retreival code gets run. This allows me to use album.jsp to display the album whether I'm logging in for the first time or coming back to it from picture.jsp, but it's sloppy and fragile and all those J2EE MVC frameworks exist for good reason.

Anway, the picture album is represented in this code as a vector of HashMaps, but the particular implementation is unimportant. The assumption here is that you already have code which can pull database or other backend data into Java.

picture.jsp is similarly simple, and I've included it in the old app only to make a point about the new one. Once again, it retrieves the user name and album data from the session.

Now let's say that we want to employ Laszlo -- in this case to make better use of the extremely limited space for this little app. I'm not going to spend a lot of time on how the laszlo app is built, since I'm much more interested in how the laszlo app will work with the backend.

As a first step, let's leave everything else in tact, and turn the functionality in album.jsp into a laszlo app.

Something like this:



Not the most amazing demo, but at least you can immediately tell which parts are Laszlo. Let's take a second to break down the code.

I've had to rename all the files since all the links are written in to the jsps, but login1.jsp and picture1.jsp are the same, except that their links to the album are written as "album1.jsp".

Now, album1.jsp is simpler than album.jsp was -- its only responsibility is storing the username and album data in the session if it gets passed authentication information. Its other job is to embed the laszlo app, album1.lzx into the page. This is done by using Laszlo's lzEmbed call, which is a function that can write a Laszlo app into a page and is provided in a separate js file that is part of an LPS install.

In album1.jsp, the code that embeds the Laszlo control looks like this:

    <!-- include Laszlo's javascript library -->
    <script type="text/javascript" src="/lps-2.2.1/lps/includes/embed.js">
    </script>
    ...
    <script>
    <!-- Now call the lzEmbed function that's provided in the library-->
    lzEmbed({url: 'album1.lzx?lzt=swf', bgcolor: '#ffffff', width: '550', height: '300'});
    </script>

Again, I'm not going to dwell on the structure of the Laszlo app, which is trivial, but I want to focus on how the Laszlo gets data from the backend. This is done with albumxml.jsp.

This is the exciting part. albumxml.jsp is really simple, and it's just like a normal jsp. Let's take a look at how it works. First, there's this:

<%
    response.setContentType("text/xml");
%>

Which simple tells the requestor that the response will be XML and not HTML. Next, we retrieve the username from the session and send it as an attribute of the dataset:

<album user="<% out.print( session.getValue( "uname" ) ); %>">

Finally, we loop through the data in the album -- just as we did when we were rending for HTML -- but now emit XML, which is remarkably simpler:

    <%
        ArrayList album = ( ArrayList ) session.getValue( "album" );
        for ( int i= 0 ;i < album.size(); i++ ){
            String s = "<picture ";

            /*
            ...
            for ( properties in albumelements )
                s += properties +"='" + albumelements[ properties ] +"' "
                //like this prop='val'

            */

            s += "/>";
            //so s="<picture prop1='val1' ... propn='valn' />
            out.println( s );
        }
    %>

One last important note: Laszlo apps play in a Flash control hosted by the browser. When the Flash player makes HTTP requests, it uses the browser's mechansim, meaning that it sends all of the browser's cookies. This is what allows us to write code that relies on session data even for requests that are made from the Laszlo app. The result is an XML document that contains only the information we need. Its output looks like this.

So, to recap, we've answered the first question in the above list, which was about how we embed a Laszlo app into an HTML application flow. I should point out that a lot of people who think mainly in terms of server-side applications (which is a lot of people) often try to do something like this:

    <!-- BAD EXAMPLE!!! -->
    <!-- put laszlo app with data into a jsp -->
    <canvas width="500">
    <%
        //psuedo code
        for pix in album
            //code that renders laszlo, as if it were a jsp rendering HTML:
            String s = "<view resource='http:" + pix.get( "url" );
            //etc.
            out.print s + "/>";

    %>
    <!-- rest of program -->
    ...
    </canvas>

Often people get struck trying to figure out how to embed the Laszlo code directly into an HTML page. Sometimes they even get as far as figuring out that the jsp that renders Laszlo code has to be separate, with its output handed to the LPS compiler somehow. If they do get this far, they're disappointed with the results. You want to write a Laszlo app that loads dynamic data in a dataset. The app itself should be static. This is not only because Laszlo's compiler is currently dreadfully slow -- this scheme would never work in a high volume production setting -- it's also because it's usually a bad idea to have non-trivial code that writes non-trivial code. (Of course that's essentially what most modern J2EE/DHTML apps do these days, but that's the example that proves the rule.)

Hopefully, my liberal use of <em> tags has gotten my point across about dynamic data, so that answers question number 2 above, which was: how does the Laszlo app get data from the backend? Hopefully that's pretty clear by now:
you can use all the goodies that you're used to in the J2EE environment, including the request object, the session, and any other code that you have, to render XML for consumption by the front end. Of course, there are more exotic options out there such as SOAP and XML-RPC, but custom XML over HTTP is very easy to do, and most production Laszlo apps use this approach.

The last question on the list was about how to add something like an MVC controller to a Laszlo app. You probably noted that the last example above did not provide the best user experience -- especially since the picture details were presented on a separate HTML page. Here is a final take on this app, with all of the functionality moved into Laszlo.



Again, not the most impressive application, but for once we're not really focussed on the presentation layer. Instead, let's take a look at how the app changed to accomodate its move completely into the world of Laszlo.

First of all, we changed login.jsp from a form renderer to a responder which takes authentication info and sets up the session with user information and user data. Now it just looks like this:

<%
    response.setContentType("text/xml");
    session.putValue( "uname", (String) request.getParameter( "uname" ));
    session.putValue( "album", album );
%>
<ok/>

This doesn't really do much except store the username and album data in the session, but of course you could imagine that it actually authenticates and tells the Laszlo app whether there was success or failure. For now, it unconditionally sends the success token, and that in turn triggers the request for the album data. You could imagine that a more complex application would do the login step and then make separate backend data requests during its run depending on user actions.

The rest of the backend is the same, with albumxml.jsp still responding with the XML data stored in the backend Java object that's kept in the session. The part of interest here is that we have added a controller to the Laszlo app to help it manage its various states. The controller looks like this:

    <node name="controller">
        <attribute name="state" value="0"/>
        ...

The main thing of note here is that the controller exposes a property called "state", which represents the mode of the app. The various pieces of the UI have constraints on their visible property that look like this:

    <!-- login -->
    <view align="center" valign="middle" visible="${controller.state == 0 }">
    ...
    <!-- album -->
    <view datapath="dsAlbum:/album" width="100%" y="20"
          visible="${controller.state == 1 }">
    ...
    <!-- details -->
    <view visible="${controller.state == 2 }">
    ...

The controller also has several methods that various UI elements talk to in order to change the application state. It stores a reference to the data for the selected picture which the user clicks a thumbnail. Here's the whole thing:

    <node name="controller">
        <attribute name="state" value="0"/>
        <attribute name="picdata" value="null"/>
        <method name="didAuth" args="response">
            dsAlbum.doRequest();
        </method>
        <method name="gotAlbum">
            this.setAttribute( "state" , 1 );
        </method>
        <method name="showDetailFor" args="d">
            this.setAttribute( 'picdata' , d);
            this.setAttribute( "state" , 2 );
        </method>
        <method name="goBackToAlbum">
            this.setAttribute( "state" , 1 );
        </method>
    </node>

You can see the whole program here.

This is a fairly primitive example, but hopefully it begins the to answer the question of how control can be centralized in a Laszlo app. It's worth noting that in general, if you have a Laszlo app with a lot of screens, you probably haven't spent enough time thinking about how you can adapt your user-interface design from HTML to the kind of universal canvas/shared space approach that you can take in a Laszlo application. Still, most apps have some modal sense of state, and that's best handled with a controller like the one in this small application.

Performance Optimism

The Flash player executes bytecode slowly. You can see here that a simple function that adds one to a number takes a significant amount of time to execute.

<canvas height="100">
    <simplelayout/>

    <button>Test
        <method event="onclick">
            tester.doTest();
        </method>
    </button>
    <node name="tester">
        <attribute name="reps" value="50000"/>
        <method name="doTest">
            <![CDATA[
            var f = function ( a ){ return a + 1; }

            var t = new Date();
            for ( var i = reps; i >=0; i-- ){ f( i ); }
            t = ( new Date() ) - t;

            report.addText( ' ' + ( t/reps ) );
            ]]>
        </method>
    </node>

    <text name="report" resize="true">
        Avg function time:
    </text>

</canvas>

Compare this to the JavaScript interpreter in your browser. This is pretty much the same test, and your browser will show you that it takes significantly less time to execute. Depending on your browser/flash player combination this difference may be as much as 400x.


<script>
    function doTest(){
        var reps = 50000;
        var f = function ( a ){ return a + 1; }


        var t = new Date();
        for ( var i = reps; i >=0; i-- ){ f( i ); }
        t = ( new Date() ) - t;

        alert( 'Avg function time:' + ( t/reps ) );
    }
</script>
<button onclick="doTest()">Test</button>

Laszlo targeted the Flash runtime because it's fairly ubiquitous, and because it's a good and consistent software renderer. It also, of course, at least has a bytecode interpreter, which was a requirement for us, but it's not a very performant one -- and that has made it harder than it should be to both evolve the Laszlo platform, and to develop Laszlo apps.

Performance is always a huge consideration when developing client software, but it is especially so for rich internet apps, where the user's expectation has been set by quick rendering HTML pages. Often, the improved experience that an RIA offers ultimately makes a slight pause during startup worthwhile, but if users bail before the app starts up, then they'll never get a chance to know this.

I have spent a lot of time optimizing both the Laszlo runtime and Laszlo applications. The good news is that even the most awful seeming Laszlo app can usually be optimized and made to startup quickly and perform adequately. There are a number of strategies for this, and hopefully I will someday cover all of them here. For this entry, though, I have chosen to focus on Laszlo's initstage attribute, which offers the developer some choices around how portions of a Laszlo program are initialized.

This discussion does not include an overview of Laszlo's Krank feature, which is often an extremely simple and efficient way of optimizing a Laszlo app. Krank does, however, introduce some complications into the deployment path, and it also makes apps significantly bigger.

The basic strategy I want to demonstrate here is to defer the creation of views which aren't needed when a program starts. The example below contains a class which simulates a component that takes a long time to initialize. Note also the use of the <inittimer> tag, which provides an easy way to track app startup time.

For the purposes of demonstration, I've made it so you have to click the HTML button below to load the Laszlo app. This allows you to see a slow starting app without making this whole page sluggish.


<canvas height="200">
    <inittimer/>

    <class name="slowComponent" width="150" height="16" bgcolor="gray">
        <!-- time in ms to wait before initing -->
        <attribute name="extratime" value="500"/>
        <method name="init">
            <![CDATA[
            var d = new Date();
            while ( (new Date() ) - d < extratime ){};
            super.init();
            ]]>
        </method>
    </class>

    <button y="25" onclick="slowin.show()"> Show window
    </button>

    <window name="slowin" x="100" width="200" height="200" visible="false"
            title="slow window">

        <method name="show">
            this.setVisible( true );
        </method>

        <view name="content">
            <simplelayout spacing="2" />
            <slowComponent/> <slowComponent/>
            <slowComponent/> <slowComponent/>
            <slowComponent/> <slowComponent/>
        </view>
    </window>
</canvas>

As you can see, this app takes a little over three seconds to initialize, mostly because of the half-second delay caused by each instance of slowComponent.

Since we don't need the window when the app starts (let's say it's a preferences dialog or similar) we can defer the creation of the window contents by using Laszlo's initstage attribute.



<canvas height="200">
    ...

    <window name="slowin" x="100" width="200" height="200" visible="false"
            title="slow window">

        <method name="show">
            this.setVisible( true );
            content.completeInstantiation();
        </method>

        <view name="content" initstage="defer">
            <simplelayout spacing="2" />
            <slowComponent/> <slowComponent/>
            <slowComponent/> <slowComponent/>
            <slowComponent/> <slowComponent/>
        </view>
    </window>
</canvas>

The call to completeInstantiation in the window's show method ensures that the window contents get created when the window is shown. As an aside, you might imagine that the instantion of a declarative program (especially one which can include constraints where a refers to b and b refers to a) is somewhat complex. It certainly is, and I don't want to cover how a Laszlo program initializes here. However, the initstage tag simply governs how a node and its parent initialize.

"Defer" on a view means that the view's parent should not create that view until completeInstantiation is called. Since the semantics of 'init' are such that a view calls init when all of its subviews have inited, you will note that the content view in the example above is not inited until completeInstantiation is called. I encourage you to copy and edit this program to verify this for yourself. Finally, it's worth noting that it's fine to call completeInstantiation repeatedly.

So this fixes the startup time problem, but we're still left with an ugly pause when the user hits the button. There's another improvement we can make here, which is to show the window before all of the slowComponents have inited. Again, Laszlo provides a fairly simple construct to make this possible.



<canvas height="200">
    <inittimer/>

    <class name="slowComponent" initstage="late">
        <!-- time in ms to wait before initing -->
        <view width="150" height="16" bgcolor="gray">
            <attribute name="extratime" value="500"/>
            <method name="init">
                <![CDATA[
                var d = new Date();
                while ( (new Date() ) - d < extratime ){};
                Debug.write( 'init' );
                super.init();
                ]]>
            </method>
        </view>
    </class>

    <button y="25" onclick="slowin.show()"> Show window
    </button>

    <window name="slowin" x="100" width="200" height="200" visible="false"
            title="slow window">

        <method name="show">
            this.setVisible( true );
            content.completeInstantiation();
        </method>

        <view name="content" initstage="defer">
            <simplelayout spacing="2" />
            <slowComponent/> <slowComponent/>
            <slowComponent/> <slowComponent/>
            <slowComponent/> <slowComponent/>
        </view>
    </window>
</canvas>

Note that the structure of slowComponent had to change a little to make this possible. The reason for this change turns on the meaning of initstage="late". This can be confusing, and in fact, when I went to write this last example, I simply tried this:

<class name="slowComponent" width="150" height="16" bgcolor="gray"
    inistage="late">
    ...

But this has no effect. Why? The answer is that initstage="late" means: "init my children in the background, and allow my parent to init without me." However, completeInstantion means: "force my children to init right now." When completeInstantiation is called on the content view, it forces the initialization of all of the slowComponents. Since the slowComponents have no children, they simply apply their attributes and run their init routine, even though they are inistage="late".

With the change made in the last example above (where it's the child of slowComponent that takes a long time to init,) the content view instructs its children to initialze, but those children are themselves initstage="late", meaning that their children get put on a trickle queue, and their construction and initialization happens in small slices in the background, even while the program takes user-input and processes other interrupts. It should finally be noted that initstage="late" views can be forced to init completely by calling completeInstantiation on them, just like deferred views.

Fortunately, a real component that takes a long time to initialize is usually just a container for complex, slow-to-initialize contents. This means that it's often enough to set initstage="late" on classes or intstances of classes.

One last note about initstage="late": it may be tempting to simply use it on, say, the window that is not shown when the program starts. In practice this is usually a bad idea because the views that are getting contructed and initialized in the background slow down the flash player to a user-perceptible degree. It's almost always preferable to defer the creation of a container for views that aren't needed at startup-time, and then to use initstage="late" on those contents.

We used some of these techniques to speed up the start of Laszlo's homepage app. You'll recognize the behavior of the dropdown windows, where you can see the late initialization of the window contents when they are first dropped down.

The Working Class

I've been critical of classic, class-based OOP in this forum, so I decided it was time to point out a place where I think it works really well in Laszlo. I really don't like iterators in Java -- I think they're cumbersome, and it irritates me that I need a whole object just to represent what is essentially a counter. However, a layout in Laszlo is an iterator that works well as an object, because it has meaningful state.

A layout tends to control its siblings. Even novice Laszlo users are familiar with a construct like this:

<canvas>
    <class name="box" width="100" height="10"/>
    <box bgcolor="red"/>
    <box bgcolor="blue"/>
    <box bgcolor="green"/>
    <simplelayout name="myLayout" spacing="2"/>
</canvas>

(EDIT PROGRAM)

Here myLayout operates on the colored boxes that are its siblings. One thing that's nifty about layouts is that they can be active -- they can be written to respond to changes in the attributes that affect the layout. Simplelayout, for instance, knows that it is affected by changes to the size of a view in the layout axis. The layout in the example below responds as the boxes change height when they are clicked.

<canvas>
    <class name="box" width="100" height="10"
           onclick="this.animate( 'height' , 10 , 300 , true )"/>
    <box bgcolor="yellow"/>
    <box bgcolor="teal"/>
    <box bgcolor="maroon"/>
    <simplelayout name="myLayout" spacing="2"/>
</canvas>

(EDIT PROGRAM)

Simplelayout is aptly named: it has fairly simple behaviors, and if it didn't have a few important optimizations; it'd be less than 30 lines. A layout has several useful members that are provided by the base class:

  • An abstract update routine
  • This is the meat of the layout.

  • A subviews array
  • The list of views controlled by the layout.

  • A handy API
  • That makes it easy to reorder or change the subviews array.

So using the basic features of layout, I can reconstruct simplelayout in about 10 lines of code (and demonstrate my familiarity with the more obtuse CSS colors).

<canvas>
    <class name="box" width="100" height="10"/>
    <box name="box1" bgcolor="silver"/>
    <box name="box2" bgcolor="fuchsia"/>
    <box bgcolor="navy"/>

    <button onclick="with( parent ) aLayout.swapSubviewOrder( box1, box2 );">
        Swap
    </button>

    <layout name="aLayout">
        <attribute name="spacing" value="2"/>
        <method name="update">
            <![CDATA[
            var pos = 0;
            for ( var i = 0; i < subviews.length; i++ ){
                subviews[ i ].setY ( pos );
                pos += subviews[ i ].height + spacing;
            }
            ]]>
        </method>
    </layout>
</canvas>

(EDIT PROGRAM)

Note that all of the heavy lifting of registering added subviews and calling the update routine is done for me -- I just have to add the logic that knows what do when the layout updates.

From this, it should be clear that layouts do not have to be solely position related, and multiple layouts can apply to a given view. Here's a layout that sets the background colors of the views it controls:

<canvas>
    <class name="box" width="100" height="10"/>
    <box/> <box/> <box/> <box/> <box/> <box/> <box/> <box/>

    <simplelayout/>

    <layout>
        <attribute name="colorIncrement" value="0x202020"/>
        <method name="update">
            <![CDATA[
            var color = 0;
            for ( var i = 0; i < subviews.length; i++ ){
                subviews[ i ].setBGColor ( color );
                color += colorIncrement;
            }
            ]]>
        </method>
    </layout>
</canvas>

(EDIT PROGRAM)

Some people are surprised that layouts are themselves objects. This was, in fact, a design choice that was made during the development of language. Laszlo provides some syntactic sugar to allow developers to specify a layout as an attribute (<view layout="class: 'wrappinglayout'">) but heavy users of LZX understand that by making layouts share the API of the Laszlo base class (LzNode), and by giving them access to such features as constraints and events, layouts can be much more abstract and powerful.

For instance, here's a layout that extends simplelayout to make it fill its container with instances of a class that is passed to it as an attribute.

<canvas>
    <class name="box" width="100" height="10" bgcolor="red"/>

    <class name="fillLayout" extends="simplelayout">
        <attribute name="fillClass" when="once"/>

        <method name="update">
            <![CDATA[
            super.update();
            var lastsub = subviews[ subviews.length - 1 ];
            while( !lastsub || lastsub. y < immediateparent.height ) {
                var lastsub = new fillClass( immediateparent );
            }
            ]]>
        </method>
    </class>

    <window height="200" width="100" resizable="true">
        <fillLayout fillClass="box" spacing="5"/>
    </window>
</canvas>

(EDIT PROGRAM)

This is almost embarassingly easy to write, and you should experiment with editing the source to make the fillLayout create, say, buttons instead of boxes. If you play with this, though, you'll note that if you resize the window, the layout doesn't create new views. This is because the layout has not registered its dependency on the size of its immediate parent. Lucky for us, the layout base class comes with an updateDelegate, which is a callback that can be registered with events that, when sent, make the layout run its update routine. All we have to do is register this callback with the onheight event of the immediate parent, like so:

    ...
    <class name="fillLayout" extends="simplelayout">
        <method event="oninit">
            updateDelegate.register( immediateparent , 'onheight' );
        </method>
    ...

(EDIT PROGRAM)

and now the layout responds as the window resizes.

Hopefully, you're now convinced that layouts are fairly easy to write. Experience has also shown that layouts tend to be a useful optimization tool. Some relationships are just easier to express in a for loop than in a web of declarative code, and layout provides a useful bridge between the worlds of declarative and procedural coding.

Ultimately, I think the layout base class works well for a few reasons:

  1. it's abstract
  2. A layout does not try to model user-land; a layout tries to model developer-land. It makes sense for a tool used by a developer to have a constrained and well defined API; it doesn't make that much sense for a user. It's interesting that a relatively complex thing like fillLayout (above) is much shorter than the extensions made to the basebutton class by Laszlo's concrete button class. OOP is poorly suited to the idiosyncratic and somewhat whimsical demands of user-experience.

  3. it's a container
  4. I think OOP is best suited to containers. This is the essence of the C++ STL, and it makes it all the more ironic that the princess of OOP, Java, has (up 'till now at least) had such problems with genericity. No one wants to have to write a hash map or an indeterminite-length list over and over (although it seems like in most languages, we still do.)

  5. it's unambitious
  6. Essentially, a layout is just an array of items -- wrapped with some useful methods and hooked into the Laszlo runtime instance hierarchy in useful ways. Layouts don't try to proscribe what a developer can do with them, nor do they make any assumptions about what purpose they ultimately serve.

I wish I could say that classes work this well for more of the Laszlo components, but in general, I think class-based OOP is bad for UI programming.

State of the State

Oliver Steele has written about the way in which Laszlo's use of prototypes enables what he calls "instance-first development." I'm glad he did, because it lays the groundwork for what I wanted to write about in this entry: Laszlo's state tag, and its meaning within Laszlo's meta-object framework.


That may sound like a lot of fancy talk, but it's not that complicated, and it cuts to the heart of the declarative programming model. We made a simple observation early on in the development of LZX: declarative programming is great for declaring the initial state of an application, but subsequent state was relatively difficult to represent.


For a little while, our story was simple: declare the initial state of your program with tags, and then manipulate it with code. This was acceptable, but there was a problem.


We had built a powerful declarative language, but developers could only use its features to express initial program state. This was particularly true of animators and constraints. Constraints are especially powerful, and they are difficult to add programatically, as they tend to involve some tricky function-as-datatype business that can be unsavory. For instance, here's a small program where the blue box follows the mouse:

<canvas>
    <view bgcolor="blue" width="20" height="20">
        <attribute name="x" value="${parent.getMouse( 'x' ) - 10}"/>
        <attribute name="y" value="${parent.getMouse( 'y' ) - 10}"/>
    </view>
</canvas>


(EDIT PROGRAM)

While this is an especially nice way of expressing this kind thing (made possible by Laszlo's constraint system,) it's rarely useful in a program. Usually, objects only follow the mouse when they're being dragged. Clearly we needed a way of writing declarative LZX nodes that could be applied to and removed from program state.


We introduced the state tag to make this possible. Here's a rewrite of the above program using states, to make the blue box drag only when the mouse is down:

<canvas>
    <view bgcolor="blue" width="20" height="20"
          onmousedown="this.setAttribute( 'mouseIsDown' , true )"
          onmouseup="  this.setAttribute( 'mouseIsDown' , false )">
        <attribute name="mouseIsDown" value="false"/>
        <state apply="${parent.mouseIsDown}">
            <attribute name="x" value="${parent.getMouse( 'x' ) - 10}"/>
            <attribute name="y" value="${parent.getMouse( 'y' ) - 10}"/>
        </state>
    </view>
</canvas>


(EDIT PROGRAM)

Note that the syntax of the constraints hasn't changed; they're just inside a state tag. This is useful, but it's also a little strange: the state tag is essentially an invisible node of hierarchy. You can see this in the fact that the parent in the apply constraint for the state is not the same object as the parent in the drag constraints inside the state.


This example highlights the metaphysical nature of states -- they modify the meta-object protocol enough so that their contents can be stored and applied elsewhere. This could conceivably be a feature of the system as a whole (there's a feature request in our bug DB for anLzNode.setParent( otherLzNode ),) but it's not.


Anyhoo, here's the interesting bit: what should happen when I write this?

    <class name="myDragState" extends="state">
        <attribute name="dragMin" value="2"/>
        <attribute name="dragMax" value="20"/>
        ...
    </class>

The question is: do the attributes dragMin and dragMax pertain to the state itself, or to the state's container? The former is more powerful: it would allow for developers to extend the special behavior of states, say by over-riding the state's apply method. The latter, though, is more consitent with the lzx idiom, where, as a first-order approximation, a class behaves like a macro.


For now, the behavior is the latter. Here's a little test program that shows that.

<canvas>
    <class name="constrainedDragState" extends="state">
        <attribute name="dragMin" value="100"/>
        <attribute name="dragMax" value="300"/>
        <attribute name="mousePos" value="${parent.getMouse( 'x' ) - 10}"/>
        <attribute name="x"
                   value="${Math.max( Math.min( this.dragMax , this.mousePos),
                                      this.dragMin )}"/>
    </class>

    <view bgcolor="blue" width="20" height="20" x="100" y="50"
          onmousedown="myDrag.apply()"
          onmouseup="  myDrag.remove()">
        <attribute name="mouseIsDown" value="false"/>
        <constrainedDragState name="myDrag"/>
    </view>
</canvas>


(EDIT PROGRAM)



Note that the references to dragMin, dragMax and such are all made within "this."


One way this could be clarified would be to make the somewhat arbitrary, but sensible, distinction that any attribute for which the state has a setter belongs to the state itself, whereas any attribute that doesn't belongs to the state's apply target. This makes sense, because any setter for an attribute which is intended to be applied by the state (and not kept by the state) can be written in the apply target. By something of a coincidence, this is how it currently works in Laszlo. Here's a little program that proves that:

<canvas debug="true">
    <class name="testState" extends="state">
        <attribute name="countApplies"  value="0"
                   setter="this.countApplies = countApplies"/>
        <method name="apply">
            this.setAttribute( 'countApplies', ++this.countApplies );
            super.apply();
        </method>
    </class>
    <button >Try it
        <method event="onclick">
            ts.apply();
            Debug.write( "applies:" + ts.countApplies) ;
            ts.remove();
        </method>
        <testState name="ts"/>
    </button>
</canvas>


(EDIT PROGRAM)



One last thing: developers are often surprised to find that one pays the instantiation cost of a regular node of hierarchy for a state, whether or not it is applied. This is because the state is itself an LzNode, which must be processed by the LzNode constructor. The advantage of limiting the ways in which a developer can modify a state itself is that then a given state can have a limited number of attributes, which are controlled by the runtime. This would allow for an optimization: every instance of a class could share a single instance of each state it contains. Allowing developers to muck with the semantics of "state" by attaching attributes and methods to it would make it harder to make this optimization.

It's the classic story: features or performance?

Why I like JavaScript, Part f()

First-class functions should be a part of every language. It's funny that this incredibly powerful idea is usually the basis of the computer science curriculum, but it finds little application in modern programming practice.


There's an obvious reason for this: the dominant programming languages (Java and C++) don't have 'em. The lack of them in C++ is excusable; functions-as-a-datatype is a little beyond the close-to-the metal features one expects from C++, but I think their absence in Java is bizarre.


I think there's another, more subtle, reason that you don't see wide adoption of first-class functions in commercial software: the closure idea is hard to grok, and it feels obtuse in languages where you can even treat a plain 'ol int as an object.


I like Javascript's implementation of functions (though once again the syntax is a little off-putting.) There are two ways I can write a function in Javascript. One is like this:

    function highPass( x ){
        return x > 10 ? x : 10;
    }



The other is like this:

    highPass = function( x ){
        return x > 10 ? x : 10;
    }



Either way, these statements are true:

    highPass( 12 ) == 12;
    highPass( 5 )  == 10;

These are in every way equivalent; the name-in-the-declaration syntax is just a special case of assigning a function to a global slot.


One interesting note: if I define an object

    var o = { n : 10 };

And then attach a function to it:

    o.lowPass = function ( x ){
        return x < this.n ? x : this.n;
    }

I can call that function as a method of o. So

    o.lowPass( 12 ) == 10

is true. However, a reference to o.f is not bound. So if I write this:

    var g = o.lowPass;

This statement is true:

    g( 12 ) == undefined;

The reason for this is that there is no 'this' context for the function g. The global g slot is a reference to f, not a reference to f-in-the-context-of-o.


Here's a little Laszlo unit test to make sure I'm not making any of this up:


VIEW PROGRAM



The ECMA-262 spec includes syntax for emulating a bound reference, although you have to remember both the function to call, and the object to call it on.

    //call is unimplemented in Laszlo
    var p = { n : 15 };
    g.call( p , 12 ) == 15;

The call syntax is nice becuase the original function doesn't even have to be a slot in the object p for this to work, but as I noted, "call" is not implemented in the Flash player.


One thing that's funny about "call" is that it is a little backward from the usual OOP paradigm. Usually, you want to ask an object which function to call based on its name, which is the basis of polymorphism. With the call syntax, the programmer retains a reference to a specific function, which may or may not be the one that the given object or class wants to define as this-is-what-I-do-when-you-call "f()".


As a side note, this deficiency in Javascript is the basis for Laszlo's delegates, which are essentially a little datum containing a callback context (the object) and the name of a function to call on it.


Anyway, there is a way to attach data to a function without any of this fancy object business, and I think it's pretty nifty. Although the ECMA spec includes closures, alas the Flash player does not. If the Flash player supported closures, you could write a function generator this way:

    //this won't work in Laszlo
    function makeFilter ( low, high ){
        return function ( x ){
            return x < low ? low : ( x > high  ? high : x );
        }
    }

This relies on the magic binding of the anonymous function created inside the makeFilter to the scope in which it was created. Admittedly, if you've written an interpreter, this isn't quite as arbitrary as it seems, but if you're just an everyday programmer, it doesn't make a ton of sense, especially given the way that you can just add properties to just about anything in Javascript. Also, closures have the problem that the data which is bound to the function is implicit; there's no easy way to poke at the values for high and low once you've generated the closure.


Javascript offers a nifty alternative, wrapped (as usual) in bad syntax. Within the context of a function, the function itself can be referenced by using the callee property of the implicit arguments array. Here's a rewrite that uses arguments.callee:

    function makeFilter ( low, high ){
        var f = function ( x ){
            var low = arguments.callee.low;
            var high = arguments.callee.high;
            return x < low ? low : ( x > high  ? high : x );
        }
        f.low = low;
        f.high = high;
        return f;
    }

This has the additional advantage that I can later inspect and/or change the values for low and high. Here's a little program that puts this to use filtering an array of random numbers.


I call the return type of makeFilter a pseudo-closure. If the Flash player followed the ECMA spec, I probably wouldn't have adopted this idiom, but now that I have, I prefer it to closures. I think it's easier to understand and maintain.


Here's a little program that adds a filter capability to arrays and then uses pseudo-closures to take advantage of it.


<canvas height="200">
    <script>
        <![CDATA[
        Array.prototype.filter = function ( f ){
            for ( var i = 0; i < this.length; i++ )
                this[ i ] = f( this[ i ] );
        }
        ]]>
    </script>
    <method name="initArray">
        <![CDATA[
        var a = [];
        for ( var i = 0; i < 20; i++ )
            a[ i ] = Math.floor( Math.random() * 100 );
        return a;
        ]]>
    </method>
    <method name="makeFilter" args="low, high">
        <![CDATA[
        var f = function ( x ){
            var low = arguments.callee.low;
            var high = arguments.callee.high;
            return x < low ? low : ( x > high ? high : x );
        }
        f.low = Number( low );
        f.high = Number( high );
        return f;
        ]]>
    </method>

    <attribute name="anArray" value="$once{ canvas.initArray() }"/>
    <simplelayout spacing="10"/>
    <text text="${canvas.anArray}" width="400"/>
    <view>
        <text y="2">Low: </text> <edittext id="lo" x="40" width="40" text="20"/>
    </view>
    <view>
        <text y="2">High:</text> <edittext id="hi" x="40" width="40" text="80"/>
    </view>
    <button>Add filter
        <method event="onclick">
            var f = canvas.makeFilter( lo.getText() , hi.getText() );
            canvas.anArray.filter( f );
            //make the text field update
            canvas.onanArray.sendEvent( );
        </method>
    </button>
</canvas>

(EDIT PROGRAM)

Programs as Data

I love runtimes. Leveraging increasing processor speed to create useful abstractions for the programmer is an idea which (I think) is just in its infancy, but which will ultimately become the basic model of software construction.

The runtimes for Java and C# have at their core a single feature: a memory manager. That alone has proven so worthwhile that it has created a tectonic shift in modern software development. It's interesting (and a little sad) to me that this is really the only abstraction built into these runtimes, as I think that loose (or at least non-overt) typing, combined with more flexible data types (I want to be able to add numbers to strings, for example) make for shorter, easier to read, and less buggy programs.

This is my bias, and I don't want to argue it right now. The thing that really interests me about runtime technologies is that if the runtime designer can identify a few core, powerful constructs and then build those constructs into the runtime in native code, then she can create a runtime which will have decent performance characteristics even though it offers very high level constructs.

Something I've been thinking a lot about lately is the way in which a program which is run by a runtime is actually just data. This is somewhat obvious, but it is rarely formalized. In fact, runtime languages usually do a lot to look like the compiled languages that preceeded them. The fact that I have to think about whether I want an int or a float in Java strikes me as ridiculous. If I don't care, I shouldn't have to think about it.

This is a side note, but I also think it's interesting that performance issues often keep real programs from taking full advantage of Java's built-in garbage collector. In theory, it's great that everything in Java is and should be an object; in practice, programmers often have to write their own object pools to workaround the slowness of allocating memory. This is another way in which the full power of the Java runtime cannot be exploited.

Anyway, back to the main point, which is that to date, the virtual machine abstraction has been relatively weak: the Java and MS.NET runtimes are essentially idealized versions of modern computer architecture that don't leak memory or crash (at least, they're not supposed to leak memory or crash.) This reminds of me of something I heard about the early days of cinema: there was a while, before Eisenstein and others invented a cinematic vernacular, where people made movies by just locking down a camera and filming a play.

Functional programming is the closest match to the kind of abstractions that I'm talking about, but I find that purely functional languages are cumbersome for all but the most trivial applications. XSLT is the functional language that's probably most widely used today, and I think that anyone who has used it will testify to its deficiencies. It's good at simple things, but the exceptional cases, the idiosyncracies in the data model, and the inevitable mid-project changes, tend to be very difficult to deal with using XSLT. More importantly, the missing if...then and for...in type of logic that is honestly the bread and butter of most production code is hard to recreate in functional languages, and the implementation tends to be fragile, so that making a change to logic forces large rewrites to the program.

Laszlo currently has an interesting mix of functional and imperative programming. I've written about Laszlo's use of XPath before, but here's how it relates to program transformation.

(EDIT PROGRAM)

<canvas layout="spacing: 2">
    <dataset name="myData">
        <people>
            <Tim> Nice guy.  </Tim>
            <Ron> Not so bright.  </Ron>
            <Kelly> Tall.  </Kelly>
            <Adam> Bombastic.  </Adam>
        </people>
    </dataset>

    <view datapath="myData:/people/*" layout="axis:'x'">
        <text datapath="name()"/>
        <text datapath="text()"/>
    </view>

</canvas>

Here at Laszlo, we call this effect "data replication." This program essentially says: for each of the nodes in myData:/people, make a view which has two children, which are text's, the first of which has the text of the node's name(), etc.
The nice thing about Laszlo is that I can do this:

(EDIT PROGRAM)

<canvas layout="spacing: 2">
    <dataset name="myData" src="mydata.xml"/>

    <view fontstyle="bold" layout="axis:'x'" name="title">
        <text>Name</text>
        <text>Comment</text>
    </view>

    <view datapath="myData:/people/*" layout="axis:'x'" name="people">
        <text datapath="name()"/>
        <text datapath="text()"/>
    </view>

</canvas>

This is a simple exception to the main program logic -- I want column headers in a slightly different presentation style -- but I can add them to my program without having to add them to my data model and then try to identify that data in my for..each transformation. Again, if you've used XSLT, you know how hard it can be to add these types of things at just right spot in the middle of a complex transformation.

I'm pretty happy with the way that data replication works with Laszlo, but it's a little bit ad-hoc. The transformation of the people view happens at runtime, meaning that in order to know whether or not there are one or many people view's, the first people view has to be made. In practice, this makes for some messy programming, because the first people view is subtly different from the others. This can be especially frustrating, because often the programmer knows at design time whether or not she intends a given data-mapped view to replicate.

What we've been talking about lately is making it so that the runtime is essentially a big data replication engine. In Laszlo as it is implemented now, there isn't really an abstraction layer between the part of the above program that specifies the title view, and the runtime objects which are created to represent it. The transformation from the declaration of that view to a constructor call happens in the compiler. What I've been thinking about is the idea of passing a Laszlo program to the runtime as data. The Laszlo language, then, is a default mapping that tells the runtime how to map data to constructor calls. The default mapping is:

XML node Laszlo instance
name class
attributes attributes
children children (recursive)

A datapath declaration is way of using other data as program data, and changing that mapping. In the above program, the replicated row does this:

XML node (of myData:/people) Laszlo instance
"view" class
"people" name attribute
"axis:'x'" layout attribute
text (with separate mapping) first child
text (with separate mapping) second child
name ignore
attributes ignore
children ignore

I think it would be so nice if this was built into the core of the Laszlo runtime. (Instead, right now, the people view is responsible for figuring out whether it needs to replicate. The program really is a program, and the data is fed into it.)

When we've talked about this at Laszlo, people's reaction has been either "that's too abstract for me to understand how it's useful" or "it sounds right, although I don't know specifically what it would buy us."

I think that the main advantage is that this would remove the distinction bewteen data-backed parts of program and non-data backed ones. Any part of a Laszlo program hierarchy could be read back out as data, and more importantly, component writers would not have to write special code for the data-backed case.I think it would eliminate a whole class of bugs, and it would open the door to a much more formal description of Laszlo programs, which might lead to compile-time optimizations. Besides, it's just really cool.

Class Warfare

I'm as much of an OOP adherent as the next person. You say to me: "encapsulation, polymorphism and inheritance" and to you I say, "right on." But I find it interesting and somewhat disappointing that the notion of "object-oriented" is conflated with the notion of "class", which I consider an implementation detail.

I'll get back to some of those implementation details in a second, but let me lay out the two reasons why I don't like classes.

First, classes are too big to be truly atomic. If you consider the spectrum between a single function or data type, and the whole of a program, classes land very near to the latter. Every working programmer knows this problem, and there are any number of informal and formal strategies for dealing with it. Aspects recognize this problem, but I find the Aspect notion complicated, too tied to the particulars of the Java language (even though it's not supposed to be,) and in practice, only useful for a limited number of applications.

The second problem with classes is that they don't allow very well for the fact that objects change over time. If I take a UI element in my program and drag it from one window to another, it's likely that some fundamental aspects of what it is will change at the end of that operation. As a class designer, though, I have two unappealing choices when specifying the class. One is to write a single class that encompasses all the possible behvior that the object could have (along with the requisite switch statements.)

The other possibility is to write several classes to express the various possibilities for its end state, and then to write the n! constructors for those classes so that I can create an instance of any once class from an instance of any other. I could try to solve some of this problem by giving all the possible end-states a common superclass, but then I have to choose either only to represent the particular object as a class hierarchy, or to represent the abstract notions of 'draggable', 'inwindowA', and 'inwindowB' as classes, but not both. No matter what else happens, I'm going to have to destroy and re-create the object, which is likely to be slow.

Multiple inheritance was supposed to solve some of this problem, but it has become something of a dirty word in modern programming with the advent of Java and C#. This is not (in my opinion) because multiple inheritance wasn't a useful concept, but because it was too hard to use and because it leads to all sorts of unexpected behaviors and errors. This is my thesis statement, tucked into in aside: I'm basically saying that classes don't really do a good job of representing abstract things at all -- they ultimately always must represent instances -- which is antithetical to the highest aspirations of OOP.

Now it may seem strange to criticize classes and endorse OOP, but in fact the two are almost completely separate. Classes make it easier to write compilers, and (arguably) easier to write interpreters, but otherwise, they're pretty 20th century. Consider this snippet of Javascript:

    function f (){ Debug.write( "My name is" + this.name ) };
    var o = { name : "Object o" , sayName: f };
    o.sayName();

That's encapsulation. Here's polymorphism:

    function g (){ Debug.write( "I don't have a name." )};
    var n = { sayName: g };
    list = [ o , n ];
    for ( var slots in list )
        list[ slots ].sayName();

Note that we've done all this without creating a template for these things. The call-by-name semantics of Javascript, combined with its first-class functions, make this possible.

Now inheritance is trickier. I've written about __proto__ before, and this is where it comes into play. I could add a method to both o and n by giving them the same __proto__ and then manipulating that.

    var sup = {};
    sup.enumerate = function {
        for ( var keys in this ){
            Debug.write( keys, this[ keys ] );
        }
    }
    o.__proto__ = sup;
    n.__proto__ = sup;
    o.enumerate();
    n.enumerate();

Note that there are some important differences between __proto__ and classes. The first is that __proto__ is a post-hoc operation. I can set and change my __proto__ well after I've been created. Second, my __proto__ can be an instance of an Object. This gives me several powerful options, like transforming a set of objects by calling a function on their __proto__, and it gives me a fast way to clone an existing object. It also lets me do exotic stuff, like configure a class at runtime.

This is a side note, but it's worth taking a second to think about the fact that runtime-interpreted languages have a curious property. Terse syntactic constructs tend to run faster than longer ones, because in general, most of the time spent running a program is in reading and dispatching the bytecodes. This essentially means that the more power in the constructs that are built into the runtime, the faster its programs can run.

Anyway, Javascript isn't perfect. __proto__ solves problem #2 above (the fixed-ness of classes), but not problem #1 (the bigness of classes.) My big complaint with __proto__ is that it is a single slot. This makes multiple inheritance hard to implement and much less efficient than it could be. What I really want to be able to do is to define a set of very small atoms which can by combined in arbitrary ways. What follows is not real syntax in any language, but hopefully you'll get the idea:

    Draws = {};
    Draws.draw = function (){ ... }
    Draws.invert = function (){ .... draw() .... };
    ...

    LoadsMedia = {};
    LoadsMedia.load = function ( url ){ ... };
    LoadsMedia.draw = funtion () { ...super.draw()... };

This is very similar to the inheritance pattern, but with an important difference, because I could do this:

    View = new LoadsMedia,Draws;
    aview = new View;

Here's another thing I could do

    Minimized = {};
    Minimized.draw = function(){ /*make smaller*/ ... super.draw() .... };

    aview.pushProto( Minimized );
    aview.draw();

I think you can imagine what I think pushProto should do.

The big ? (read "question mark") in the above code revolves around the exact semantics of "super." I have some ideas about that, but I think I've gone on long enough for this particular installment. Hopefully, I'll get around to treating that at a later date.

I've been calling these little objects that represent parts of classes "transformers." People laugh at me, but I'm used to it. As usual, I've written some code that shows what you get from Javascript.

VIEW/EDIT PROGRAM

<canvas debug="true" height="250">
    <debug height="240"/>
    <script>
        function f (){ Debug.write( "My name is" + this.name ) };
        var o = { name : "Object o" , sayName: f };
        o.sayName();
        Debug.write( "---------" );

        function g (){ Debug.write( "I don't have a name." )};
        var n = { sayName: g };
        list = [ o , n ];
        for ( var slots in list )
            list[ slots ].sayName();
        Debug.write( "---------" );

        var sup = {};
        sup.enumerate = function (){
            this.sayName();
            for ( var keys in this ){
                Debug.write( "   " +keys+ ":", this[ keys ] );
            }
        }
        o.__proto__ = sup;
        n.__proto__ = sup;
        o.enumerate();
        n.enumerate();
    </script>

</canvas>

Laszlo and XPath

Laszlo implements a subset of the XPath W3C Standard XML Path Language. It's pretty sensible, and, I think, fairly intuitive.

For instance, given a dataset that looks like this:

    <dataset name="dset">
        <root>
            <anode/>
            <anode v="0"/>
            <anode v="1"/>
            <anode v="0"/>
            <anode v="1"/>
            <anode v="0"/>
            <anode v="1"/>
        </root>
    </dataset>

I can make selections on it. I can select the first node this way:

    dset:/root/anode[1]

The symbol "*" means "any node", so I can write

    dset:/root/*[1]

and acheive the same effect (XPath offsets are 1 based.) The token '[1]' is a predicate, which narrows the set selected by the path that preceedes it. I can use other tokens in predicates as well. For instance, to select all of the nodes that have an attribute 'v', I can write:

    dset:/root/*[ @v ]

And I can combine predicates, so that this:

    dset:/root/*[ 6- ][ @v = "1" ]

Selects the last anode.

One thing that's interesting about XPath expressions is that they can return either null (for no match,) a single element, or a list. The general consensus in implementations appears to be that these possibilities should be modeled with overloaded return types -- null, a single datanode, or a list of datanodes respectively. This can be extremely inconvenient, since there isn't a great way to tell the type of an object at runtime. In general, you have to write code like this:

    var r = dp.xpathQuery( "dset:/*/*" );
    if ( r instanceof Array ){
        //multiple matches
        ...
    } else {
        //single or no match
    }

Alternatively, you could do this:

    var r = dp.xpathQuery( "dset:/*/*" );
    if ( ! ( r instanceof Array ) ){
        r = [ r ];
    }

    //array processing
    ....

Of course, if that's how you handle it, then xpathQuery should probably have just returned an array in the first place.

One final note about all this stuff. XML in general obviously is very order-sensitive, and the original order of an XML document often matters a lot. However, the position() operator in XPath returns the position of the element within a selection. For instance, you might expect this query:

    dset:/root/*[ @v='0' ]/position()

to return the array [ 2, 4, 6]. Instead it returns the array [ 1, 2, 3]. This is often useful behavior when processing additional predicates, such as:

    dset:/root/*[ @v='0' ][ position() = last()]
    //(this is currently unimplemented in Laszlo)

but as far as I know, there's no way to get the original position of a node in the document. Perhaps this is because that information can at times be ambigious. For instance, in the selection '*/*', the nodes might have the absolute positions [1, 2, 1, 2, 3, 1, 2] in the case where there are multiple top-level nodes and multiple subnodes. Obviously, if there were such an absolute position operator, a simple number would not really be enough to unamibiguously represent a node's position within the original data. Either the programmer would have to keep track of that, or the absolute position operator would have a more complex return type. In the above example, something like this perhaps: [ [ 1,1], [1,2], [2,1], [2,2], [2,3], [3,1], [3,2] ]

XPath isn't bad, but I think I would always prefer a more script oriented way of working with data. BEA is working on some interesting stuff in this area -- they call it Native XML Scripting.

Anyway, here's a little laszlo program that let's you type an XPath query against the dataset at the top of this page and see what the results are:

VIEW/EDIT PROGRAM

Laszlo's Coordinate System

Most viewsystems use a 3x3 transformation matrix to represent the way in which a container modifies the coordinate system of its contents. This is usually very close to the implementation of such coordinate systems, and it's very powerful -- by modifying the transformation matrix, you can change rotation and stretch in an axis, as well as skew.

In designing Laszlo's coordinate system, we wanted to create an API that would be easy to use without thinking about it, but also provide enough power so that it would be relatively easy to do more complicated things. Alas, the transformation matrix was not really an option, because the Flash runtime doesn't have skew APIs.

In Laszlo, I can put a picture in my app as shown below. If I don't say otherwise, this view will be the size of its contents, which (in this case) is its resource. I've demonstrated this by putting a gray mask over the picture which has its width and height.

EDIT PROGRAM

<canvas bgcolor="silver" height="275">
    <view name="demoview" resource="gandalf.jpg"/>

    <view bgcolor="black" opacity=".2"
          width="${demoview.width}" height="${demoview.height}"/>
    <button x="200">
        Shrink
        <method event="onclick">
            demoview.setWidth( demoview.width - 10);
            demoview.setHeight( demoview.height - 10 );
        </method>
    </button>
</canvas>

Also of note in the above example is the fact that I can change the view's size without affecting how it appears. This is, in fact, the default meaning of the 'width' and 'height' properties in lzx -- unless you say otherwise, they don't actually effect how a view gets drawn. This can be very useful for reasons (such as layout) that I won't go into now.


Here's a similar program, modified so that it has the behavior you were probably expecting.

<canvas bgcolor="silver">
    <view name="demoview" clip="true" resource="gandalf.jpg"/>
    ....
</canvas>

By adding the clip="true" attribute, I have told the Laszlo runtime that this view should be clipped to its size. This is one way in which a view can be forced to be drawn at its given size. The other way is to tell the view to stretch (in "both" axes):

<canvas bgcolor="silver">
    <view name="demoview" stretches="both" resource="gandalf.jpg"/>
    ....
</canvas>

One common issue when dealing with resources is the desire to keep the aspect ratio of an image. In simple cases (such as this one) it can be enough to know a resource's size and to use that to calculate an aspect ratio. In Laszlo, however, because the size of a view can be complex function of its contents, it is often necessary to know what size the view would have been, had it not been stretched. This information can be gleaned from the built-in properties "unstretchedwidth" and "unstretchedheight". Here's a program that preserves the aspect ratio of the image as it shrinks:

EDIT PROGRAM

<canvas bgcolor="silver" height="275">
    <view name="demoview" stretches="both" resource="gandalf.jpg"
          height="${aspectRatio * width}">
        <attribute name="aspectRatio"
                   value="${unstretchedheight/unstretchedwidth}"/>
    </view>


    <button x="200">
        Shrink
        <method event="onclick">
            demoview.setWidth( demoview.width - 10);
        </method>
    </button>
</canvas>

I mentioned earlier that a view is the size of its contents. That holds true even when the view doesn't include a resource. Take a look at this case. Note that you can resize the enclosing yellow box by dragging the small boxes within it.

EDIT PROGRAM

<canvas bgcolor="silver" height="275">
<class name="dragger" width="10" height="${width}"
onmousedown="ds.apply()" onmouseup="ds.remove()">
        <dragstate name="ds"/>
    </class>

    <view name="demoview" stretches="both" bgcolor="yellow">
        <dragger x="15" bgcolor="teal"/>
        <dragger y="15" bgcolor="red"/>
    </view>
</canvas>

You can see here that moving the draggable boxes inside the yellow box affects its size. This whole discursive enterprise has been an attempt to explain the seemingly curious behvior exhibited below. As you move drag the teal box, you're resizing the stretched view, but since you've set stretches, the apparent size of the box doesn't change -- just the extent to which it is scaled.

EDIT PROGRAM

<canvas bgcolor="silver" height="275">
    <class name="dragger" width="10" height="${width}"
           onmousedown="ds.apply()" onmouseup="ds.remove()">
        <dragstate name="ds"/>
    </class>

    <view name="demoview" stretches="both"
          width="100" height="100"
          bgcolor="yellow">
        <dragger bgcolor="teal"/>
    </view>
    <text text="${ 'unstretchedwidth: ' + demoview.unstretchedwidth }"/>
    <text text="${ 'unstretchedheight: ' + demoview.unstretchedheight }"/>
    <simplelayout/>
</canvas>

Why I like JavaScript (Part I)

I really like a lot of things about JavaScript. With the exception of a few bizarre syntactic constructs, I think it's the most sensible thing going. Of course, I have a loose-typing, runtime bias so you can send me your flames about how that proves I'm a drooling, barely computer-literate script kiddie, but I promise that I won't read them.

Anyway, here's one thing that I find particularly nifty about JavaScript. It's a concept that I've seen referred to as "protection."

Given an object o which has slot n set to 6

    var o = { n : 6 };

I can create another object, oprime, which uses o as its __proto__. (Remember I mentioned the bizarre syntactic constructs? Well this is an example of bad syntax for a useful feature.)

    var oprime = { __proto__ : o };

If an object is your __proto__, that means that when the runtime goes to look for the value of one of your slots, if you haven't defined it, then the runtime looks for that slot in your __proto__. If it's not there, then the runtime looks in that object's __proto__, and so on. The object Object (ok, there's another bizarre syntactic construct -- every object in a JavaScript ultimately descends from the object named... "Object". Bad name, but decent idea) is at the root of every __proto__ chain.

Anyway, this is the essence of inheritance, but boiled down into something very pure and simple. So given the statements above, the expression:

    oprime.n == 6

is true. Also, I can affect the value of oprime's n slot by changing the value of o's n slot. So this:

    o.n++;
    oprime.n == 7;

is also true, even though oprime has no slots, and technically the runtime hasn't even had to allocate any memory for it yet. (In fact, the runtime probably has already allocated a bucket for its slots, and the global slot oprime is a pointer to that bucket.)

Now, consider what happens when I write this:

    oprime.n++;
    oprime.n == 8;

(The last statement is true by the way.) What happens here? Well, I think this is pretty nifty. The runtime gets the value for the n slot, which is 7, and then sets it on oprime, so now oprime has its own n slot, which masks the value of o's n slot. We could prove this a couple of ways, but the easiest is to simply delete the slot in oprime.

    delete oprime.n;
    oprime.n == 7;

Pleasant, no? Also pleasant is the fact I won't affect o by calling stuff on oprime. So for instance, if I try to delete n again:

    delete oprime.n;
    oprime.n == 7;

The last statement is still true.

I wrote a little unit test using Laszlo to prove all of this. Feel free to play with the source.

EDIT PROGRAM

<canvas>
    <include href="lzunit"/>
    <TestSuite>
        <TestCase>
            <method name="test">
                var o = { n : 6 };
                var oprime = { __proto__ : o };
                AssertEquals( 6 , oprime.n );
                o.n++;
                AssertEquals( 7 , oprime.n );
                oprime.n++;
                AssertEquals( 8 , oprime.n );
                delete oprime.n;
                AssertEquals( 7 , oprime.n );
                delete oprime.n;
                AssertEquals( 7 , oprime.n );
            </method>
        </TestCase>
    </TestSuite>
</canvas>
|
* * *
Syndicate content