Wednesday, December 9, 2009

A Sliding Random Collage Layout

Here's a simple random collage layout in OpenLaszlo that also "slides" each of the subviews into the view from the left. It demonstrates how to create your own custom layout.

This demo defines a simple "box" class and then displays the boxes using a layout that randomly places them within the view. The boxes slide in from the right into their respective positions, and can overlap. You can press the "Redraw" button to update the layout, which will generate new random positions.

First, we define a simple OpenLaszlo class for displaying boxes.

<class name="box" bgcolor="blue" width="40" height="40"/>

Next, we define the redraw button, which will call the layout's update method to redraw the view:

<button x="10" onclick="collage.mylayout.update()">Redraw</button>

Now we define a parent view named "collage" that will contain the boxes:

<view id="collage">

Within this view, we define its layout using the layouttag:

<layout name="mylayout">

Layouts always need to define their addSubview method:

<method name="addSubview" args="s">
super.addSubview(s);
this.update();
</method>

We can now define the main part of the layout algorithm in the layout's update method. First, we check to see if the layout is locked; if it is, we return. If not, we lock it, and proceed.

<method name="update" args="e">
if (this.locked) return;
this.locked = true;

Now, we loop thru all of the boxes (subviews) we want to display. For each box, we calculate a random x and y position, clipping it to fit in the view:

for (var i=0;i<subviews.length;i++) {
 var view = this.subviews[i];
 var x1 = Math.random()*(canvas.width-60);
 var y1 = Math.random()*(canvas.height-60);

// set the position
 view.setAttribute("y",y1);

Now we slide the box in from the left to its position by using an animation:

view.animate("x",x1,canvas.width,false,{from:-200});

Finally, we unlock the view:

this.locked= false;

Here's a link to the full source code for the collage layout demo. Enjoy!

Tuesday, December 8, 2009

A Force-Directed Graph Using OpenLaszlo

This component shows a force-directed layout graph. The graph nodes and connections are specified in an XML file, and can contain any number of links between the nodes. The graph is displayed such that the distances between the nodes dynamically "balance", giving the maximum display space to each node. Also each node can "pop up" after a predetermined delay time, allowing the graph to be incrementally constructed in front of the viewer. The font size, foreground color, and background color of each node can be defined.

Both the nodes and the links are active. Nodes are draggable; you can select one with the mouse, left-clicking, and dragging the node to a new location while all the connected nodes follow it. If a node is dragged beyond the image limits, it automatically snaps back to within visible range. Nodes can contain hyperlinks to other web pages (in the example below, double-click on Node1 to go to our homepage); they also have tooltips that are visible by hovering the cursor over the node. Links can be clicked to display a popup window with additional information.

The graph is defined by a simple input XML file that contains information about each node and link (edge). For example, here's some of the XML that defines this graph:

<?xml version="1.0"?>
<graph delay="1000" >

<!-- nodes -->
<node id="node1" fgcolor="white" bgcolor="blue" href="test.txt">
<text>Node1</text>
<tip>This is node1</tip>
</node>

<node id="node2" fgcolor="white" bgcolor="blue">
<text>Node2</text>
<tip>This is node2</tip>
</node>

<!-- edges -->
<edge fgcolor="blue" from="node1" to="node2">
<label>link1</label>
<info>This is link1</info>
</edge>

</graph>

I'll post more of a discussion of how this is coded soon.

Monday, December 7, 2009

Neon Sign

This OpenLaszlo component simulates a pulsing neon sign with a "neon glow" effect and tubular glass font. In the demo below, the sign uses a black background and red text that pulses once every second:

I'll describe the programming of this in more detail soon. For now, here's a link to the OpenLaszlo source code.

OpenLaszlo Typewriter Text Effect

This code implements a typewriter effect that writes character-by-character messages onto a screen. It reads text items from an input XML file, types each item out to the screen, and then repeats from the start.

In this demo, the sign uses a blue-grey background, 38pt white text, a 150ms duration for each character, and a 4 second duration for each line being written:

Here's the XML that defines the typed text:

<typewriter fgcolor="white" fontsize="38" keyduration="150" duration="4000">
<text>Now is the time</text>
<text>For all good men</text>
<text>To come to the aid</text>
<text>Of their country.</text>
</typewriter>

To implement this, first we use the courier font, to look like a typewriter:

<font name="myfont" src="c:\\windows\\fonts\\cour.ttf"/>

Next we define a new class called "typetext" which inherits from regular text but defines new attributes for the item to be typed, the start position(0), the key duration (default 150ms), and the overall duration to type each line (default 4sec):

<class extends="text" name="typetext" >
<attribute name="s" type="string"/>
<attribute name="i" type="number" value="0"/>
<attribute name="keyduration" value="150"/>
<attribute name="duration" value="4000"/>

The heart of this class is a method called "type" which will type out the text:

<method name="type" args="e"><![CDATA[
var s0 = this.s;
var s1 = this['text'];
var c = s0.substr(this.i,1);
s1 += c;
this.i++;
setAttribute("text",s1);
if(this.i <= this.s.length) {
 del = new LzDelegate( this, "type" );
 lz.Timer.addTimer(del,this.keyduration);
}
]]>
</method>

Also we need a reset method to reset the display when we want to repeat all the lines again (to infinity):

<method name="reset">
this.text='';
this.i = 0;
</method>

In the main program, we want a method called "show" that will read the XML file, loop thru each text message, and show it:

<method name="show" args="e"> dp.getNodeCount()) this.i2 = 1;
del = new LzDelegate( this, "show1" );
lz.Timer.addTimer(del,this.duration);
]]>
</method>

Finally, we call "show" from the "ondata" event of the main program, fired when we have loaded the XML file:

<handler name="ondata">
dp = canvas.datasets.mydata.getPointer();
dp.setXPath("mydata:/typewriter");
var fontsize = dp.xpathQuery("@fontsize");
var fgcolor = dp.xpathQuery("@fgcolor");
this.keyduration = dp.xpathQuery("@keyduration");
this.duration = dp.xpathQuery("@duration");
this.setAttribute("fontsize",fontsize);
this.setAttribute("fgcolor",fgcolor);
show();
</handler>

Here's a link to the full source code for the typewriter effect.