XUL provides a way to create tabular or hierarchical lists using a tree.
One of the more complex elements in XUL is the tree. A tree is used for creating lists of items. The tree element is also used for creating hierarchical lists and tables. For example, the list of messages in a mail application, or the Edit Bookmarks window in Mozilla can be created using a tree.
There are two ways that the contents of a tree can be created. The simplest is by putting tree items directly in the tree. We'll look at this method in this section. The other method, which is actually more common and useful allows you to create the tree contents from a data source. This means that the tree can be filled with information from the user's bookmark list, from a directory on disk, or from the results of a search, or a number of other places.
The tree involves a number of new elements. Much like menus, each element is nested inside each other. The tree element is much like the table tag in HTML. It is actually a specialized type of grid. The elements that make up a tree are described briefly below:
Let's start by looking at how to create a simple table with multiple columns. This could be used to create a list of mail messages. There might be multiple columns, such as sender, subject and date.
First, the entire table is surrounded with a tree element. This declares an element that is used as a table or tree. In this case, we'll use it like a table.
There are three parts to a tree's syntax. The first is used to declare the content of the tree. Like HTML tables, the data is organized into rows. The table data is created by placing a row or rows of data inside a treechildren element. The second part of a tree is used to declare the header row, which is optional. The table headers are created by placing a row of data in a treehead element. The third is used to specify what columns you want in a tree, using the treecolgroup tag.
The outermost treechildren element in a tree should be flexible, so that the rows in a tree always fit fully with-in the tree. If you don't add a flex attribute, the items in the tree will not appear properly.
Both the header and body are similar in what they contain but are drawn differently and have some different functionality. Inside these elements you will put rows of data. Each row of data is created using the treerow element. For example, by placing five treerows in the table, five rows of data will appear in the table. Think of this element as the equivalent of the HTML tr table tag.
Inside the rows, you will put individual tree cells. These are created using the treecell element. Whatever you put in treecells will be displayed as the data of the table. The first treecell determines the content that will appear as the first column, the second treecell determines the content that will appear as the second column, and so on.
The treecell element can be declared in two different ways depending on what you want to put inside it. The first method involves a similar syntax to buttons, by using the value attribute to specify the text to appear in the cell. This syntax is useful if cells contain only text.
The attributes that be placed on the treecell element are listed below:
Treecells are similar to buttons in syntax but they are not the same. The example below shows the syntax of a single treecell element.
<treecell value="Hamburger"/> |
There is another syntax that you can use for treecells that is useful if you would like to include other types of content besides text. This is commonly used to include images or check boxes in a tree. To do this, put other elements inside opening and closing treecell tags. The example below shows how to add a check box to a tree.
<treecell> <checkbox checked="true"/> </treecell> |
Here, instead of using a value attribute, an HTML checkbox has been declared as the cell's contents. You should use the syntax that suits what you need to do. You shouldn't combine the two however as only one is used (the second syntax will override the value). The other attributes of a treecell such as align only apply to the first syntax.
The sample below shows a tree created with the syntax so far.
<tree flex="1">
<treechildren flex="1">
<treerow>
<treecell value="joe@somewhere.com"/>
<treecell value="Top secret plans"/>
</treerow>
<treerow>
<treecell value="mel@whereever.com"/>
<treecell value="Let's do lunch"/>
</treerow>
</treechildren>
</tree>
|
| Make sure that you make the treechildren element flexible (by adding flex="1") or your trees won't appear properly. The tree element should be made flexible if you want it to resize to fit its container. |
The sample above can be displayed, however it will not be formatted very well. The text in each cell will be right next to each other, instead of in columns. To fix this, we need to add some columns by using the treecol element.
The syntax of a typical set of tree columns is as follows:
<treecolgroup> <treecol flex="1"/> <treecol flex="4"/> </treecolgroup> |
By placing this code in a tree (as a direct child of the tree element), it defines two columns, the second of which will take up more space than the first. You should always specify that columns are flexible so that the size of each column can be determined. You can also supply widths with the width attribute. You should include the same number of treecol elements as there are columns in the tree. Otherwise strange things will happen.
The example below demonstrates a simple message list created using a tree.
Example 6.2.1
<tree>
<treecolgroup>
<treecol flex="1"/>
<treecol flex="1"/>
</treecolgroup>
<treechildren flex="1">
<treerow>
<treecell value="joe@somewhere.com"/>
<treecell value="Top secret plans"/>
</treerow>
<treerow>
<treecell value="mel@whereever.com"/>
<treecell value="Let's do lunch"/>
</treerow>
</treechildren>
</tree>
|
As can be seen in the image, the tree has been created with two rows of data.
The addition of the columns make the cell data align itself. Next, let's add
a header row to display the titles of each column.
The syntax of the header row is similar to the body. Just create a row where the treechildren element is replaced with a treehead element. Of course, the header row should normally only have one row in it, although it is valid to have multiple rows.
Shown below is the same example with a header row.
Example 6.2.2
<tree>
<treecolgroup>
<treecol flex="1"/>
<treecol flex="1"/>
</treecolgroup>
<treehead>
<treerow>
<treecell value="Sender"/>
<treecell value="Subject"/>
</treerow>
</treehead>
<treechildren flex="1">
<treerow>
<treecell value="joe@somewhere.com"/>
<treecell value="Top secret plans"/>
</treerow>
<treerow>
<treecell value="mel@whereever.com"/>
<treecell value="Let's do lunch"/>
</treerow>
</treechildren>
</tree>
|
The code above shows how similar the data rows are to the header row. We
can add additional rows to the table by adding more
treerow elements after the others. We could add an
additional column by adding a third treecell to
each row, including the header row.
If you are familiar with HTML, you should notice some similarities between trees and HTML tables in syntax. You could use an HTML table to create such a structure but XUL trees have additional features that make them more powerful.
The message list in the previous example appeared fine but we want to add some additional features. First, we want the rows to be selectable. When the user clicks on a row, we want the entire row to be selected. This can be easily done using a new element.
By placing a row inside a treeitem element, the entire row becomes selectable. The example below demonstrates this.
<treeitem>
<treerow>
<treecell value="joe@somewhere.com"/>
<treecell value="Top secret plans"/>
</treerow>
<treeitem>
|
By placing treeitems around each row, the entire row becomes selectable. Actually, it makes whatever is inside the treeitem selectable. You could put two treerows inside a single treeitem making both rows selectable at once. You probably wouldn't do this however.
Of course, we wouldn't put a treeitem inside the header row as we wouldn't want it to be selectable.
The user can select the treeitems by clicking on them with the mouse, or by highlighting them with the keyboard. By default, only one item can be selected at a time. However, there is a way to allow multiple items to be selected at a time. The user can select multiple items by holding down the Shift or Control keys and clicking additional rows. To allow multiple selections, add the multiple attribute as in the example below:
Example 6.2.3
<tree multiple="true">
<treecolgroup>
<treecol flex="1"/>
</treecolgroup>
<treehead>
<treerow>
<treecell value="Elements"/>
</treerow>
</treehead>
<treechildren flex="1">
<treeitem>
<treerow>
<treecell value="hydrogen"/>
</treerow>
</treeitem>
<treeitem>
<treerow>
<treecell value="nitrogen"/>
</treerow>
</treeitem>
<treeitem>
<treerow>
<treecell value="carbon"/>
</treerow>
</treeitem>
<treeitem>
<treerow>
<treecell value="lead"/>
</treerow>
</treeitem>
</treechildren>
</tree>
|
If you click each row while holding down the Control key, each row will be added to the selection. To unselect rows, click again on the row.
Let's add a tree to the find files window where the results of the search would be displayed. The following code should be added in place of the iframe.
<tree>
<treecolgroup>
<treecol flex="1"/>
<treecol flex="2"/>
<treecol flex="1"/>
</treecolgroup>
<treehead>
<treerow>
<treecell value="Filename"/>
<treecell value="Location"/>
<treecell value="Size"/>
</treerow>
</treehead>
<treechildren flex="1">
<treeitem>
<treerow>
<treecell value="mozilla"/>
<treecell value="/usr/local"/>
<treecell value="2520 bytes"/>
</treerow>
</treeitem>
</treechildren>
</tree>
<splitter collapse="before" resizeafter="grow"/>
|
We've added a tree with three columns for the filename, the location and the file size. The second column will appear twice as wide due to the larger flexibility. A single row has been added to demonstrate what the table would look like with a row. In a real implementation, the rows would be added by a script as the search was performed.
(Next) Next, we'll learn how to create more advanced trees.