08.15.07

LZProject - an OpenLaszlo 4 Blueprint Application

Posted on August 15th, 2007 in General, Documentation by Raju Bitter

OpenLaszlo 4.0 is the only RIA technology capable of generating DHTML/Ajax or Flash out of the same code base. With the announcement of OpenLaszlo 4.0 in March we have triggered a new wave of interest in the OpenLaszlo technology. But still many developers wonder how they can integrate OpenLaszlo with their Java back end system. LZProject will provide answers to some of these questions and give you a good overview of the general architecture of an OpenLaszlo application.

LZProject - OL4 Blueprint App

LZProject includes both the client application, written in LZX, and all necessary back end components, including Java servlets and a small Apache Derby Java embedded database. It’s been designed to be simple to deploy and easy to modify. The application supports English, German and Korean locales at the current stage. We hope that you’ll download and use the application as you read the white paper, and, if you’re a software developer, that you’ll download the sources and play with them too.

You can download LZProject as a Java Web Application (WAR file) and deploy it on your own Java servlet container. The WAR file is the SOLO version of LZProject, containing two SOLO compiled files (SWF/Flash7 and JavaScript) of LZProject. It will run on any system capable of running a Java servlet container such as Tomcat 5.0 or higher. LZProject has been tested to run in DHTML mode in Firefox 2.x, Safari 2, Webkit, Opera 9.22 (still displaying a warning for DHTML runtime). The Flash runtime version will run in any Browser with at least Flash7 support.

The complete source is available from the OpenLaszlo Subversion server at svn.openlaszlo.org/labs/lzproject. Build instructions can be found in the Wiki, including a screen cast showing how to build LZProject.

We hope that the OL4 Blueprint App LZProject and the accompanying white paper will contribute to an even wider OpenLaszlo adoption around the world and are glad for any feedback on the application and the white paper.

07.10.07

OL4 documentation: current status

Posted on July 10th, 2007 in General, Documentation, Development, Community by jgrandy

Since John and I keep getting inquiries about changes made in the OL4 documentation, and many of you are likely to be using OL4 sooner or later, I thought I’d send out one message in the hopes of providing a single point of discussion.

We had four primary goals with the OL4 documentation:

  1. Support the ability to mark content that is runtime-specific. As you know, OL4 supports multiple runtimes (Flash and DHTML, more to come), and while the core OpenLaszlo APIs are the same across all runtimes, there are differences where we can support extra features or where we haven’t yet gotten to strict parity. The documentation must reflect this.
  2. Improve maintainability of the doc tools and the documentation. The OL3 toolchain was extremely proprietary, difficult to understand, and thus had suffered from poor maintenance. In addition, it was possible for the reference material to drift relative to what was implemented in the code, and there were other areas (such as the schema) where we were essentially inviting inconsistency. We decided that it was a very high priority to rebuild the doc tools around standard technologies wherever possible, in order to simplify maintenance, ensure accuracy and consistency, and to better invite participation from the community.
  3. Make it easier to accomplish several important goals: invite community participation in writing and maintaining the documentation, reuse the tools for other projects, localize the documentation, and maintain the live embedded examples.
  4. Produce a unified index across all the documentation.

With these goals in mind, we rebuilt the entire documentation tool chain around two technologies. The first is a homegrown tool called “js2doc” which uses the JavaScript parser in our compiler to extract precise information about the APIs actually found in the source, merges that information with annotations and comments, and generates documentation in an XML format. This tool, which I built, is based on the standard javadoc tool and uses (as much as practical) the same conventions used by javadoc.

The second technology is an open source standard called Docbook. This is currently the most widely adopted documentation standard on the market and is extensively integrated with documentation publishing systems of various kinds. (The OL3 documentation used Docbook, but only as an internal tool.)

Docbook uses a pipelined workflow. Essentially, content is produced in Docbook format, and then transformed by XSLT into any of a number of destination formats. The workflow is optimized for static generation of a traditional book (either a single PDF file or a conventional, static html document web), but before adopting Docbook we made sure that there were solutions available for more dynamic publishing styles. John and I wanted to make sure that multi-pane navigation from OL3 was possible, as well as full-text search and other nifty web publishing techniques found in the online documentation for other languages (e.g. Perl).

Docbook has a clean localization story, and is well itself well documented (there’s even an O’Reilly book for it!).

The reason I am writing this email is that John and I have found ourselves repeatedly explaining our decision to take an architecture-focused approach to this redesign rather than immediately providing all of the user-visible features from OL3. Our conclusion, based on years of interaction with the community, is that it is relatively easy to attract external contributors to the documentation — to write cookbooks, to localize, to edit, to improve the tools — *as long as* the barriers to entry are relatively low. By acting to simplify and normalize the doc toolchain, we open the door to much greater participation from the community. And by making it possible to reuse the tools for other projects, we further increase the potential for real support commitments. The tradeoff is that a few user-centered features are not implemented in the first version of the OL4 documentation, but we absolutely plan to provide those features in the future.

As you approach the OL4 documentation, you are likely to have the following questions, and we’d like to take the time to provide you with answers. Our purpose is to inform, and to open the door to broader input about priorities, not to shut down debate or questions.

Q. What happened to the left-side nav bar?
A. The simplest Docbook publishing mode is to generate a book-style html web, with a table of contents. Our plan from the beginning was to rely on existing doc publishing tools such as Apache Cocoon to provide more sophisticated navigation tools such as multi-frame navigation.
Q. What about search?
A. Search is not currently available within the new documentation. However, we have added a search box to http://www.openlaszlo.org/documentation that provides targeted search of documentation for a range of different OL versions, including OL4. Our current plan is that in-page search will arrive with adoption of a live publishing solution such as Apache Cocoon.
Q. Where is the class/tag index?
A. Due to a bug in the XSL tools for Docbook, automated construction of secondary indices increases the time for generation of the primary index from 8 minutes to 80 minutes. Until a fix is found for this bug, or a maintainable alternative is built — and a hand written class index is not maintainable — we have left this feature out of the documentation. But it is a goal to provide this index.
Q. Why not implement user comments like in the Perl documentation?
A. We like the idea of comments, but are also wary of the problem of staleness. (Stale info in comments is no more helpul than stale or incorrect info in documentation). You also get the problem that you have two virtual forums instead of one, which leads to confusion. We’re considering some kind of commenting mechanism whereby relevant forum topics would be listed within each documentation page. Philosophically, we think the right approach is to keep the docs current, rather than to have them stale and corrected in the comments. We’re looking to set up a process whereby the community can help us fix the documents themselves, not merely comment on them. We welcome input.
Q. Can I use the new toolchain for my own project?
A. Absolutely! The new toolchain is much more reusable than the old one.
Q. How can I get involved?
A. Email John Sundman (jsundman openlaszlo dot org) or myself (jgrandy at openlaszlo dot org) and we’ll get you involved.

05.29.07

OpenLaszlo 4 Programming Tutorial

Posted on May 29th, 2007 in General, Documentation, Development by jgrandy

OpenLaszlo architect and ultimate insider Adam Wolff has recorded a screencast version of his wonderful OpenLaszlo programming tutorial, available below. Besides being a tour de force of ‘vim’ text-editing acrobatics, this tutorial demonstrates construction of a simple client-server application in OpenLaszlo 4, and highlights several of the most exciting features of the OL4 release. The video is about 40 minutes long, and best viewed at full resolution. Enjoy!


Click To Play

03.30.07

How we deal with browser quirks, with a compendium of IE 7 issues

Posted on March 30th, 2007 in Documentation, Development by Max

Anyone who has done serious DHTML development work knows there are many issues and quirks with the browsers out there. Of course, we had to come up with a way to deal with these cleanly for OL 4. First, I’ll talk about how we deal with browser quirks. Next, I’ll list the IE 7-specific issues we ran across during development of the OL4 DHTML runtime.

Capabilities-based browser quirks

1. We keep an object that lists each quirk by name, with a boolean value for whether it’s active in the current browser or not. Here’s a list of all the current quirks, with default values:

LzSprite.prototype.quirks = {
    fix_clickable: true
    ,fix_ie_background_height: false
    ,fix_ie_clickable: false
    ,ie_alpha_image_loader: false
    ,ie_leak_prevention: false
    ,invisible_parent_image_sizing_fix: false
    ,emulate_flash_font_metrics: true
    ,inner_html_strips_newlines: true
    ,inner_html_no_entity_apos: false
    ,css_hide_canvas_during_init: true
    ,firefox_autocomplete_bug: false
    ,hand_pointer_for_clickable: true
    ,alt_key_sends_control: false
    ,safari_textarea_subtract_scrollbar_height: false
    ,safari_avoid_clip_position_input_text: false
    ,reverse_mouse_wheel: false
    ,no_cursor_colresize: false
    ,safari_visibility_instead_of_display: false
    ,preload_images_only_once: false
    ,absolute_position_accounts_for_offset: false
}

2. Next, we use some browser detection code to turn specific quirks on or off depending on the browser we’re running in:

    ...
    if (Lz.__BrowserDetect.browser == 'Opera') {
        // Fix bug in Opera where if any parent of an image is hidden the size is 0
        LzSprite.prototype.quirks['invisible_parent_image_sizing_fix'] = true;
    }
    ...

3. Finally, the sprite checks these quirks at runtime, like so:

LzSprite.prototype.__imgonload = function(i) {
    ...
    if (LzSprite.prototype.quirks.invisible_parent_image_sizing_fix) {
        Fix...
    }
...
}

This has a several benefits:
+ By conditionalizing on capabilities (instead of browser-specific version information) we can turn the quirks on or off once up front when we do the browser test.
+ It runs faster - it’s quicker to test for a boolean value than test for a browser ID/version each time a given chunk of code runs.
+ We can easily and safely turn behavior on or off without touching the rest of the code.
+ Quirks can be cleanly reused when the same issue is discovered across multiple browsers. For example, when I discovered Opera had the same issue as Webkit (images with any parent div whose style.display is set to ‘none’ don’t get valid height and width properties), all I had to do was set the ‘invisible_parent_image_sizing_fix’ quirk to ‘true’ for Opera in the browser detection phase. When this issue is fixed in future browser versions, I can easly turn the quirk back off.
+ The rest of the code is much cleaner because the quirks are ’self-documenting’. Compare these two for legibility/maintainability:

    if (this.quirks.invisible_parent_image_sizing_fix) {
        ....
    }

vs.

    if (browser.name == 'Opera' || (browser.name == 'Safari' && browser.version < 1.5)) {
        ....
    }

I encourage everyone to steal this idiom and apply it to their code! It’ll make the DHTML world a better place. If only we didn’t have to worry about these issues…

Then again, if you use OL 4, we’ll worry about them for you! We’re fond of saying ‘we work hard so you don’t have to.’ :)

IE 7-specific quirks

Okay, on to the second part of the article: IE 7-specific quirks. The IE team is currently in the process of locking down features for the next version of IE. This provides an excellent opportunity for us to list the IE-specific bugs and quirks we ran across during the development of the DHTML runtime for OL 4.

I’m not trying to single out IE here - I intend to talk about quirks in other browsers (there are plenty) in the future. I just learned the IE team is soliciting feedback, and I wanted to provide some in a timely fashion! So, I’ll list only issues that affect IE 7 for now:

+ Can’t set opacity on any div that contains <input type=”text”/> or <textarea/> without getting nasty visual artifacts in the text field.

+ Must use the AlphaImageLoader if we want opacity to apply to a div and all its children.

+ AlphaimageLoader must have its src property set to the URL of an image to prevent a red x/missing image icon from appearing

+ AlphaimageLoader does not send onload/error events - instead we have to use the img tag mentioned above

+ IE 7 still has memory leaks for apps loaded in iframes

+ Empty divs with style.backgroundColor set appear ~10px tall unless they contain an img (for less than 2px tall) or have style.fontSize = ‘0px’ applied.

+ IE does not support &apos; when setting a div’s innerHTML property

+ IE does not send onclick/onmouse* events for divs without a blank image attached

Thanks for all the hard work on IE 7 - it’s miles ahead of IE 6 in almost every way. And we all love the IE developer toolbar! Of course, let me know if you need more specifics about any of these.

Best of luck, and I hope some or all of these issues can be addressed in an upcoming release!

12.25.06

Tools for Porting 3.x Applications to 4.0B1

Posted on December 25th, 2006 in Documentation, Development by benshine

Going from a working Open Laszlo 3.x application to a blank screen in 4.0 can be frustrating; what do you do once you’ve downloaded and installed the new server, and your app just doesn’t show up? This handy guide should help you get your app to appear.

  1. Eliminate any errors or warnings that appear when compiling or running your app in the version of OL you had previously developed with, in the flash runtime of course.
  2. Eliminate compilation errors or warnings in the flash runtime in OL4B1. (lzr=swf8)
  3. Run in the flash runtime with debug=true. Eliminate any warnings or errors that appear in the Open Laszlo debugger. lzr=swf8&debug=true
  4. Replace any swf resources with stand-in png’s. (Don’t go through a laborious swf to bitmap conversion yet; just use some medium-sized png’s you have sitting around.)
  5. Eliminate any <font src=”foo.ttf”/> tags.
  6. Now run in Firefox 2 with lzr=dhtml. (It probably won’t work on the first try.) Same as above, eliminate compilation errors and warnings, then runtime errors and warnings.
  7. Install Firebug! Firebug is a totally crucial DHTML debugger. As of this writing, we’re using 1.0b7. It’s subtle though; it installs itself as disabled. Right-click on the little red x or green check in the bottom-right corner of the status bar, and select “Enable Firebug.”
  8. Run your app with firebug enabled. Firebug will almost certainly detect errors. Click on the Firebug error count to bring up the Firebug console. The console shows you the “compiled” javascript code, not your lzx source, so you have to be clever to find out where that code is actually coming from. It might be in the LFC, not your code; then you have to figure out where your code is invoking that part of the LFC. Usually you can fix these errors by taking out calls to unsupported API’s or adding a check for null. (See the release notes on dereferencing null pointers.)
  9. Use the “Net” tab in Firebug to monitor network traffic. Fix any 404s.
  10. Cycle through running with Firebug, the OL DHTML debugger, and the OL swf debugger, eliminating errors and warnings until there aren’t any more, while still making sure that you haven’t broken the swf code. Your app should start to appear at this point.
  11. Try running your app in the browser of your choice; for the best experience, stick to Firefox and IE7. Everything should work in IE6 and Safari, too. (list of supported browsers.)
  12. Still hosed? Read the release notes, consult the laszlo-user and laszlo-dev lists, ask a question in the forums.
  13. Find a bug? Great, we love bugs. Check the bug database to see whether someone else has reported it, and if not, file a bug.
Hope this helps; let us know if you get stuck… and thanks for trying us out.

01.09.06

Another Approach to State

Posted on January 9th, 2006 in Documentation by Oliver

The OpenLaszlo platform contains a <state> tag. A <state> encapsulates a collection of properties (methods and attributes) and children that can be atomically attached to or removed from a node during program execution. This is actually pretty powerful, especially since a state can contain constraints. This is how dragging is implemented, for instance.

OpenLaszlo <state>s are independent from each other. Any number of <state>s may be applied to a view at once, or none.

In problem domains, some states really do combine this way. For example, a view may be being dragged, or not, independently of whether it contains unsaved data or not; and so on.

But there’s another sense of “state”, which is the state in a state machine. These states are mutually exclusive1. And they’re a pain to implement with the <state> tag. You end up writing a code that turns on one state and turns off the others, in order to switch from one state-machine-state to another. Note the verbosity of the three state-changing lines in the fragment below:
<view>
  <state name="s1">...</state>
  <state name="s2">...</state>
  <state name="s3">..</state>

  ...s1.apply(); s2.remove(); s3.remove(); ...
  ...s1.remove(); s2.apply(); s3.remove(); ...
  ...s1.remove(); s2.remove(); s3.apply(); ...
</view>
Here’s the cool thing, though. You can turn the states on and off automatically with constraints. Just add an attribute that names the state, and make the states conditional on the value of that attribute[2]:
<view>
  <attribute name="myState" type="string" value="s1"/>

  <state apply="${this.myState=='s1'}">...</state>
  <state apply="${this.myState=='s2'}">...</state>
  <state apply="${this.myState=='s3'}">...</state>

  ...this.setAttribute('myState', 's1'); ...
  ...this.setAttribute('myState', 's2'); ...
  ...this.setAttribute('myState', 's3'); ...
In fact, if the states are only used to hide and show views and layouts (and not to attach methods and attributes), you don’t even need the <state> tag at all. You can simply conditionalize the views’ visibility on the value of the attribute that holds the state:
<view visible="${this.myState=='s1'}">...</view>
<button visible="${this.myState=='s2'}">...</view>
<text visible="${this.myState=='s3'}">...</view>

It gets better. The views don’t even need to be in the same node that holds the state variable. In expialidocio.us, I create a global “application state” object, and constrain views all over the canvas to the value of its “state” attribute:

<node id="application">
  <attribute name="state" type="string" value="login"/>
</node>
...
<loginView visible="${application.state == 'login'}"/>
<view id="progress" visible="${application.state == 'waiting'}"/>
<view id="username" visible="${application.state == 'running'}">...

You can switch the visibility of views at any level of hierarchy, conditional on the value of application.state or other state variables. You can also switch the values of other attributes, such as position or opacity. And finally, you can conditionalize these attributes on more complex expressions, such as whether an application is either in “login” state or “running”.

<view visible="${application.state == 'login' || application.state == 'running'"$}"/>
<view opacity="${application.state == 'running' ? 1.0 : 0.5"/>
<view y="${application.state == 'running' ? 0 : otherView.y+otherView.height}"/>
<view visible="${application.state == 'login' &amp;&amp; login.hostType == 'remote'}"/>


Notes

1 States are mutually exclusive in the case of a deterministic state machine. And this is what’s usually used for modeling software and user interface components.

2 You can use numbers for state values instead of strings, but I recommend strings for readability, unless you can prove that it makes a performance difference to your application. And in a real application I use strings such as “login”, “processing”, and “running”, instead of “s1″, “s2″, etc.

01.08.06

Conditionalize Visibility with Constraints

Posted on January 8th, 2006 in Documentation by Oliver

The button bar on my project page has a “Powered by OpenLaszlo” watermark. It’s at the right edge of the window. Positioning it there was easy1:
<text x="${canvas.width-this.width}"><u>Powered by OpenLaszlo</u></text>

A problem with this implementation is that the logo overlaps the search field when the window is narrow:

I wanted it to disappear instead.

Here’s the version that does that. The new code is the “visible” attribute, on the first line.
<text visible="${this.x > searchField.x+searchField.right}"
      x="${canvas.width-this.width"><u>Powered by OpenLaszlo</u></text>

This hides the view whenever the layout rules or (in this case) other constraints would have moved it over the view to its left. Here I’ve hardwired the name of the view to its left, but for this application, that’s okay.

1 The actual source is longer than this, since it has a click handler to go to the OpenLaszlo home page, and mouse handers to dim the watermark when the mouse isn’t over it. But this much handles the visuals.

01.05.06

Deploying OpenLaszlo Applications with Rake

Posted on January 5th, 2006 in Documentation by Oliver

Compiling and debugging an OpenLaszlo application is just part of the picture. Often there are assets that need to be compiled into an application, and things that need to be done with the application binary once it is complete.

At some point, once you reach a certain level of application or site complexity, you need a build script to automate the build and deployment steps. For side projects, I've been using Rake.

Here's how to use Rake to build an OpenLaszlo application. Once you do this, you'll be able to type rake hello.swf to compile an OpenLaszlo source file. More to the point, Rake can also create whatever other XML and image files your application depends on (provided you tell Rake how to build them), and you'll be able to type commands such as rake deploy to both compile the application and copy to a server -- provided, again, you've told Rake how to do this. There are examples of all of this below.

Installation

First, install Ruby, and Rake. The easiest way to install Rake is to install rubygems and then type gem install rake. If you're on a Mac you'll need to type sudo gem install rake instead. (And if you're on a Mac, you probably already have Ruby. It comes pre-installed.) Update: You should install rubygems. It's now the endorsed way to install the ruby OpenLaszlo module, below.

Second, download openlaszlo.rb, and copy it into a directory on your Ruby library path. (You can examine your library path by executing ruby -e 'puts $:'.) You may need an admin password to do this.1

Second, install the ROpenLaszlo gem:
gem install -r ropenlaszlo
Finally, you need to set some shell environment variables. OPENLASZLO_HOME is the location of the OpenLaszlo SDK on the file system. If you're using the binary install, set it to /Applications/OpenLaszlo Server 3.1. OPENLASZLO_URL is the URL of the OpenLaszlo server; for example, http://localhost:8080/lps-3.1. You can set these from the shell, or place this in your .bashrc_profile or the equivalent:
export OPENLASZLO_HOME=/Applications/OpenLaszlo Server 3.1
export OPENLASZLO_URL=http://localhost:8080/lps-3.1

That does it for system setup. Here's what you do for each project:

Usage

A project needs to live in a directory inside your OpenLaszlo server directory. For example, if you're using the OpenLaszlo 3.1 binary install on a Mac, you might use to /Applications/OpenLaszlo Server 3.1/Server/lps-3.1/my-apps. I build from a source tree that is synced to ~/laszlo/lps-dev, so I keep my projects in subdirectories of that.

Go ahead and make a new subdirectory inside the server directory, say hello. Put two files in this directory. The first is an OpenLaszlo source file, hello.lzx:
<canvas><text>Hello Rake</text></canvas>
The second is Rakefile:
require 'openlaszlo'
require 'openlaszlo'
rule '.swf' => '.lzx' do |t|
  puts "Compiling #{t.source} => #{t.name}" if verbose
  OpenLaszlo::compile t.source, :output => t.name
end
Type rake hello.swf into the shell, and you'll get a file hello.swf in the same directory:
> rake hello.swf
(in /Users/oliversteele/laszlo/lps-dev/hello)
Compiling hello.lzx => hello.swf
> ls -l hello.swf
-rw-r--r--   1 oliverst  www  73035 Jan  5 12:49 hello.swf
Execute rake hello.swf, and nothing will happen:
> <kbd>rake hello.swf</kbd>
...until you change the source file or delete hello.swf:
> touch hello.lzx
> rake hello.swf
(in /Users/oliversteele/laszlo/lps-dev/hello)
Compiling hello.lzx => hello.swf

Why Bother?

That was a lot of trouble just to do the same thing you could already do with lzc. Why bother?

One reason is that it's faster. I told you to set the OPENLASZLO_URL environment variable. That tells the OpenLaszlo module (and therefore the Rake task which uses it) to use the OpenLaszlo server to compile applications, and this can be a lot faster than using lzc[2]. For example, on my 1.5MHz PowerBook, rake hello.swf takes 18s, as compared to 35s for lzc hello.lzx.3

Of course, you could get the same speed by using the browser to run your application, and you're doing this anyway when you debug it, so what's are the real advantages?

As with any task automation, they're repeatability, and single-stop shopping. Let's take the second first.

Complex Builds

First, Rake goes beyond browser-based compile and lzc, in that it can be used to build files that the swf file depends on. For example, my home page button bar depends on an XML file for configuration, and some static text images to work around the problem that the Flash player can't apply opacity to client fonts. (And since I've only got a little bit of text in my application, I don't want to bother embedding a font.)

I use a rakefile similar to the one above for this application, but with the following additional lines:
file 'nav.swf' => ['projects.xml', 'label.png']

file 'label.png' do |t|
  sh "convert -background transparent label:'(enter search text here)' #{t.name}"
end

file 'projects.xml' => ['index.rb', 'projects.yaml'] do |t|
  require 'projects.rb'
  make_xml t.name
end

The first line supplements the *.lzx -> *.swf rule above, with the information that this particular file additionally depends on the files projects.xml and label.png. The next two forms tell Rake how to use ImageMagick, and a function defined in another file, to make these.

Now I can execute rake nav.swf to rebuild whichever of label.png, projects.xml, and nav.swf is required.

A word of warning: Unlike the browser-based compiler, Rake doesn't know any more about your source file dependencies than what you tell it. For example, if nav.lzx includes mylib.lzx and functions.js, Rake won't know to recompile nav.swf if either of these files changes (but nav.lzx doesn't). You'll need to add:
file 'nav.swf' => ['mylib.lzx', 'functions.js']
to your rakefile to tell it about them.

Deployment

The other reason to include your OpenLaszlo application builds in a build system is that that way you can automate deployment too. My deployment set consists of HTML files, PHP files, OpenLaszlo swfs, and auxiliary images, some created by hand, and some produced by other tools. I build them all locally, so that I can test them in a staging directory, but at some point I upload them to a web site -- and that's when I notice the typo, and need to do it all again. Adding a deploy task makes this easy:
FILES = %w{index.php header.php footer.php nav.swf}
STAGING_URL = 'ows@osteele.com/staging.osteele.com'
DEPLOYMENT_URL = 'ows@osteele.com/osteele.com'

task :staging => FILES do
  sh "rsync -avz -e ssh #{UPLOADS.join(' ')} #{STAGING_URL}"
end

task :deploy => FILES do
  sh "rsync -avz -e ssh #{UPLOADS.join(' ')} #{DEPLOYMENT_URL}"
end

And now rake deploy builds everything locally, and then copies everything that's changed to a deployment server.

And I can get back to actually writing code.

Updated 2006-01-11: The OpenLaszlo module is now available as a gem.


1 Alternatively, you can add a directory where you have write permission to your search path (add export RUBYLIB=~/lib/ruby to your .bash_profile or equivalent), and copy openlaszlo.rb there.

The OpenLaszlo ruby library is only a day old. After it's baked for a while I'll turn it into a gem, and then these installation instructions will be simpler.

2 First, because it doesn't have to start a JVM process for each compile, and second, because the JVM process doesn't have to load the script cache when it starts up. (Loading the script cache is slow, but compiling without it is even slower.)

3 All of these times are for a recompile -- after the file has been compiled once, and then trivially changed. The initial compile is slower -- sometimes a lot slower -- but isn't as representative of the edit-compile-debug cycle.

12.25.05

Device Text vs Embedded Text

Posted on December 25th, 2005 in General, Documentation, Development by benshine

Due to a limitation in the Flash player, device text can only be visible or invisible; any non-zero opacity values for text will be drawn as opacity=1. “Device text” means text drawn by the Flash player using the client operating system’s underlying font technology. Device text is inexpensive both in runtime cost and download cost; it uses the font already present on the client machine, so no font description needs to be downloaded. However, device fonts are handled slightly differently on different operating systems; the font dimensions may not be the same across runtimes, and some OS’s may not even have fonts you expect. (Notably, most linux machines lack Verdana.)

Embedded fonts are more flexible, but they cost more, in runtime and download size. The OpenLaszlo platform ships with several TrueType fonts, which can be found in lps/fonts. Specify a font for embedding by using the font tag: <font name="timmons" src="timmonstb.ttf" /> This includes the timmons TrueType font in the swf built from your lzx code. If you’re counting bytes (and you should be) just that one font adds 58624 of ‘em to your download. Ouch. If you’re design-focused, embedded fonts are worth it for two reasons: one, you can be sure they will look the same on every flash runtime, and two, they can be rendered semi-opaque.

There are two workarounds, both of which increase the download size:

  • Turn the text into an image; render it as an image with dynamic opacity. This is a huge pain to maintain.
  • Use embedded fonts.

The difference between embedded and device fonts has been bothering me for a while, so I put together a little example. It constrains the opacity of various text objects to the value of a slider.


<canvas width="600" >
    <font name="Arioso" src="ariosor.ttf">
    </font>
    <font name="timmons" src="timmonsb.ttf"/>
	
    <view name="inset" x="20" y="20">
        <simplelayout axis="y" spacing="10" />
	
        <view name="controls" layout="axis:y; spacing:30" width="100%" height="140" >
            <text multiline="true" x="10" width="${parent.width-20}" >
                This slider controls the opacity of each of the text objects below, as
                well as the right half of the rectangle at the bottom of the canvas.
                Opacity varies from 0 (slider=0) to 1 (slider=100).
                The text using embedded fonts (timmons and arioso) can have fractional
                opacity; the text using device fonts can only be visible or invisible.
            </text>
            <slider id="gSlider" minvalue="0" maxvalue="100" value="50" x="10" width="${parent.width-20}" />
        </view>
	
        <view height="130">
            <simplelayout axis="y" spacing="10" />
            <text  id="gText" height="24" font="timmons" fontsize="18" opacity="${gSlider.value/100}">
            some text in timmons (an embedded font)
            </text>
	
            <text height="24" font="Arioso" fontsize="18" opacity="${gSlider.value/100}">
            some text in arioso (an embedded font)
            </text>
	
            <text height="24" font="Verdana" fontsize="18" opacity="${gSlider.value/100}">
            some text in verdana (a device font)
            </text>
	
            <text height="24" font="Sans" fontsize="18" opacity="${gSlider.value/100}">
            some text in Sans (a device font)
            </text>
        </view>
	
        <view width="200" height="100" layout="axis:x">
            <view bgcolor="black" width="100" height="100" opacity="1" />
            <view bgcolor="black" width="100" height="100" opacity="${gSlider.value/100}" />
        </view>
	
    </view>
	
</canvas>

Here’s the app:

[EDIT: Sorry, this text was not valid HTML. Now it is, thanks to the webdeveloper firefox extension]
Valid XHTML 1.0 Transitional

12.23.05

Roundrect

Posted on December 23rd, 2005 in Documentation by Oliver

The nightly build contains a roundrect library. This makes adding a roundrect to your application as simple as this:
<roundrect />

Here's a sampler of roundrect features:







And here's the program that draws it:


<canvas width="210" height="210" fontsize="16">
  <include href="incubator/roundrect.lzx"/>
  <wrappinglayout spacing="5"/>
  
  <roundrect backgroundStartColor="blue">
    <text>Gradient</text>
  </roundrect>
  
  <roundrect borderColor="yellow"
             borderWidth="5">
    <text>Border</text>
  </roundrect>
  
  <roundrect borderColor="green" boxShadowColor="green">
    <text>Shadow</text>
  </roundrect>
  
  <roundrect backgroundStartColor="#d00000"
             backgroundStopColor="#400000"
             borderColor="red"
             borderWidth="5"
             boxShadowColor="red"
             boxShadowX="8">
    <text multiline="true">All<br />together</text>
  </roundrect>
</canvas>

« Previous entries ·