Hello World Tutorial Part 1: Boxes and Layout

In this tutorial, we will develop a progressively more illustrative version of the classic “Hello World” application. Our goal here is to discuss the layout of widgets in the window, and talk about how JavaScript code can be made to execute as the result of a button press. We will conclude the tutorial by talking a bit about Trixul DOM, and and showing how it can be interacted with from JavaScript.

As you might guess, the simplest Trixul application consists of a window that displays text, so we will start there. The following XML illustrates just such an application:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
  <statictext string="Hello World!" width="100" height="20"/>
</window>

The XML uses two tags that are defined by Trixul — the window tag, and the statictext tag. All Trixul documents must have, at a minimum, a window tag. Attributes associated with the window tag include the name attribute, which can be used to find the window in the DOM from JavaScript, its width and height attributes, and a title attribute, which is used to define its size. The statictext tag is used to display a string in the window.

Running the sample, we get the following display (all screenshots are from Mac OS X, but you should see the same results on Linux and Windows as well):

Some of you may be wondering, wouldn’t it be nice if the text were centered in the window? To achieve this, we need to talk a little bit about how layout is managed in Trixul. Trixul uses a box layout manager to position widgets in a window. The window itself is a box that lays out its children vertically. If we were to add a second statictext widget to our example:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
  <statictext string="Hello World!" width="100" height="20"/>
  <statictext string="Another Hello World!" width="100" height="20"/>
</window>

it would display immediately below the other one, like this:

The box tag can be used to add further boxes to the window. Boxes can have an orientation of either vertical, or horizontal. A vertical box, like a window, arranges its children vertically, top to bottom, in the order that they are encountered within the box. A horizontal box, on the other hand, arranges its children horizontally, left to right. Let’s play with this by wrapping the first of our statictext elements with a vertical box, like this:

<window name="main" title="Trixul Hello World" main="true" width="250" height="100">
    <box orient="vertical">
        <statictext string="Hello World!" width="100" height="20"/>
    </box>
    <statictext string="Another Hello World!" width="200" height="20"/>
</window>

As you can see, the orientation of a box element is given by its orient attribute. When this XML is parsed and displayed by Trixul, we get exactly the same result. Why is this? Well, the enclosing window tag, as you recall, orients its children vertically. By adding a vertical box, we do nothing to change this. We could nest the statictext element in as many vertical boxes as we like, and we would still see the same thing.

The same holds for horizontal boxes. In fact, if we changed the orient attribute to horizontal, we would still get the same window layout. But this time, it is for a different reason - there is only one child of the horizontal box. We would need a second child to see the impact of the horizontal box. Let’s add one and see:

<window name="main" title="Trixul Hello World" main="true" width="250" height="100">
    <box orient="horizontal">
        <statictext string="Hello World!" width="100" height="20"/>
        <statictext string="Hello World 2!" width="200" height="20"/>
    </box>
    <statictext string="Another Hello World!" width="200" height="20"/>
</window>

Here is the resulting screen shot:

Let’s return to our original problem — creating a window with the text “Hello World!” displayed more or less in the center of the window. Here once again is the source for a window that displays Hello World!:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
  <statictext string="Hello World!" width="100" height="20"/>
</window>

Now, if we were to resize this window, the “Hello World!” text would stay fixed in its location at the upper right hand corner of the window. The remainder of the window not being occupied by the text consists of space that will be filled in with the background color of the window. In order to center the text in the window, what we want to do is divide the unused space of the window so that it is, more or less, equally partitioned above, below, to the left, and to the right of the “Hello World!” text. A Trixul widget known as a spacer can be used to represent a chunk of space remaining in a window (or some other container widget). Let’s experiment with the spacer widget and see how it can be used to solve our problem.

First, let’s add a spacer widget to our document as follows:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
    <statictext string="Hello World!" width="100" height="20"/>
    <spacer/>
</window>

Because the spacer is located below the statictext widget, and both are children of a window widget, which lays its children out vertically, the spacer respresents the free space that is available below the statictext widget in the window. Think of the spacer in this context as being a widget below that static text widget that has a width of one pixel, and a height that is equal to the vertical size of the window minus the vertical height of the static text. As the uer resizes the window, the width of the spacer remains at one pixel wide, but the height increases or decreases as the window is made taller or shorter, respectively.

What if we were to add a second spacer above the static text widget, like this?

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
    <spacer/>
    <statictext string="Hello World!" width="100" height="20"/>
    <spacer/>
</window>

In this scenario, we have two spacer widgets claiming the vertical free space that remains in the window. How should the Trixul layout engine deal with this? it could, perhaps, give the space to the first spacer encountered, and ignore the other. However, what it does is split the remaining space in the window, giving half to the spacer above the statictext field, and half to the spacer below. In general, the layout will count the number of spacers in the innermost containing box (in this case, the window), and divide the free space among these spacers. if there are three child spacers, each gets a third of the free space, and so on. The result, in our example code, is that the “Hello World!” text is centered vertically in the window. As the user changes the vertical height of the window, the layout engine will recompute the vertical height of each sizer, with half of the height going to each child.

We are almost there. With the problem solved vertically, how do we get the same result horizontally? What we need are spacers that consume the remaining horizontal space in the window. As it turns out, spacers placed as children of horizontal box widgets behave just like spacers in vertical box widgets, except they have a height of one pixel, and a width that is a function of the remaining horizontal space in the enclosing box widget. If there are three spacers that are children of a horizontal box, for example, each will be given a width that is one third of the unused space in the window. In out example, we need two spacers to consume the horizontal space in the window, each getting half of the free space remaining.

To house these spacers, we need a horizontal box. Within the horizontal box, we place two spacers around the statictext field. The horizontal box, in turn, is made a child of the window with a spacer above and below it. The resulting document looks like this:
execute as the result of a button press. We will conclude the tutorial by talking a bit about Trixul DOM, and and showing how it can be interacted with from JavaScript.

As you might guess, the simplest Trixul application consists of a window that displays text, so we will start there. The following XML illustrates just such an application:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
  <statictext string="Hello World!" width="100" height="20"/>
</window>

The XML uses two tags that are defined by Trixul — the window tag, and the statictext tag. All Trixul documents must have, at a minimum, a window tag. Attributes associated with the window tag include the name attribute, which can be used to find the window in the DOM from JavaScript, its width and height attributes, and a title attribute, which is used to define its size. The statictext tag is used to display a string in the window.

Running the sample, we get the following display (all screenshots are from Mac OS X, but you should see the same results on Linux and Windows as well):

Some of you may be wondering, wouldn’t it be nice if the text were centered in the window? To achieve this, we need to talk a little bit about how layout is managed in Trixul. Trixul uses a box layout manager to position widgets in a window. The window itself is a box that lays out its children vertically. If we were to add a second statictext widget to our example:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
  <statictext string="Hello World!" width="100" height="20"/>
  <statictext string="Another Hello World!" width="100" height="20"/>
</window>

it would display immediately below the other one, like this:

The box tag can be used to add further boxes to the window. Boxes can have an orientation of either vertical, or horizontal. A vertical box, like a window, arranges its children vertically, top to bottom, in the order that they are encountered within the box. A horizontal box, on the other hand, arranges its children horizontally, left to right. Let’s play with this by wrapping the first of our statictext elements with a vertical box, like this:

<window name="main" title="Trixul Hello World" main="true" width="250" height="100">
    <box orient="vertical">
        <statictext string="Hello World!" width="100" height="20"/>
    </box>
    <statictext string="Another Hello World!" width="200" height="20"/>
</window>

As you can see, the orientation of a box element is given by its orient attribute. When this XML is parsed and displayed by Trixul, we get exactly the same result. Why is this? Well, the enclosing window tag, as you recall, orients its children vertically. By adding a vertical box, we do nothing to change this. We could nest the statictext element in as many vertical boxes as we like, and we would still see the same thing.

The same holds for horizontal boxes. In fact, if we changed the orient attribute to horizontal, we would still get the same window layout. But this time, it is for a different reason - there is only one child of the horizontal box. We would need a second child to see the impact of the horizontal box. Let’s add one and see:

<window name="main" title="Trixul Hello World" main="true" width="250" height="100">
    <box orient="horizontal">
        <statictext string="Hello World!" width="100" height="20"/>
        <statictext string="Hello World 2!" width="200" height="20"/>
    </box>
    <statictext string="Another Hello World!" width="200" height="20"/>
</window>

Here is the resulting screen shot:

Let’s return to our original problem — creating a window with the text “Hello World!” displayed more or less in the center of the window. Here once again is the source for a window that displays Hello World!:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
  <statictext string="Hello World!" width="100" height="20"/>
</window>

Now, if we were to resize this window, the “Hello World!” text would stay fixed in its location at the upper right hand corner of the window. The remainder of the window not being occupied by the text consists of space that will be filled in with the background color of the window. In order to center the text in the window, what we want to do is divide the unused space of the window so that it is, more or less, equally partitioned above, below, to the left, and to the right of the “Hello World!” text. A Trixul widget known as a spacer can be used to represent a chunk of space remaining in a window (or some other container widget). Let’s experiment with the spacer widget and see how it can be used to solve our problem.

First, let’s add a spacer widget to our document as follows:

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
    <statictext string="Hello World!" width="100" height="20"/>
    <spacer/>
</window>

Because the spacer is located below the statictext widget, and both are children of a window widget, which lays its children out vertically, the spacer respresents the free space that is available below the statictext widget in the window. Think of the spacer in this context as being a widget below that static text widget that has a width of one pixel, and a height that is equal to the vertical size of the window minus the vertical height of the static text. As the uer resizes the window, the width of the spacer remains at one pixel wide, but the height increases or decreases as the window is made taller or shorter, respectively.

What if we were to add a second spacer above the static text widget, like this?

<window name="main" title="Trixul Hello World"
    main="true" width="250" height="100">
    <spacer id="0"/>
    <box orient="horizontal"/>
        <spacer id="1"/>
        <statictext string="Hello World!" width="100" height="20"/>
        <spacer id="2"/>
    <box/>
    <spacer id="3"/>
</window>

The result is this. The children of the window are layed out vertically, with the spacer with id=0 and id=3 splitting the vertical space not consumed by the box element between it. Within the box element, the spacer with id = 1 and id=2 split the horizontal space not consumed by the statictext widget. In the end, the sum height of the embedded box widget is just the height of the statictext (plus two pixels, one from each of the spacers id=1 and id=2). The width of the embedded box is the width of the window. The width of the embedded box is the width of the static text, plus the free remaining space, distributed evenly among spacers 1 and 2.

The width of the window widget is the width of the embedded box, which is equal to the actual width of the window. The height is the height of the box widget (which is the height of the static text field + two pixels), and the sum of the remaining free space, split among spacer 0 and spacer 3.

There is a large amount of flexibility that using boxes and spacers provides someone trying to come up with a layout for a dialog. I encourage you to experiment by embedding boxes within boxes, along with widgets, in toy applications, and observe the results and, in particular, what happens when the containing window is resized.