apache > cocoon
 

Tree widget

Concept

The tree widget is for displaying trees of "things". The tree widget supports expanding and collapsing of nodes, single or multiple selections, and a flexible TreeModel interface to provide its data.

Definition

<fd:tree id="..." state="..." root-visible="true" selection="multiple|single">
  <fd:tree-model type="..."/>
  <fd:on-selection-changed>
   ...
  </fd:on-selection-changed>
  <fd:on-create>
    ...
  </fd:on-create>
  <fd:validation>
    ...
  </fd:validation>
  <fd:attributes>
    ...
  </fd:attributes>
</fd:tree>

All elements and attributes, except for id, are optional.

See the field widget for information on common attributes and elements.

The tree model

See the interface TreeModel. Essentially, can be a tree of any sort of objects (there is no interface for the nodes in the tree). Each parent node should be able to identify its children uniquely by means of a key (some string).

CForms ships with two implementations of TreeModel: one generic implementation (DefaultTreeModel), and one for browsing over Cocoon/Avalon sources (= filesystem-like structures).

You can set the form model in the form definition, or set it at runtime using the setModel method on the tree widget.

Source tree model

Syntax:

<fd:tree-model type="source" src="...">
  <fd:fileset>
    <fd:include pattern="..."/>
    <fd:exclude pattern="..."/>
  </fd:fileset>
  <fd:dirset>
    <fd:include pattern="..."/>
    <fd:exclude pattern="..."/>
  </fd:dirset>
</fd:tree-model>

The src attribute defines the root of the content to be browsed. For example, to browse the content of the webapp directory, specify src="context://". Of course, you can also use "file://" or other traversable sources [todo: link to some page with info about sources].

The fd:fileset and fd:dirset elements are optional. The fileset patterns are used to filter files based on their name, and the dirset patterns are used to filter directories based on their names.

There can be multiple (or none at all) fd:include and fd:exclude elements inside fd:fileset or fd:dirset. The include patterns will be evaluated first, the exclude patterns next, so the exclude patterns have higher precendence.

The patterns are wildcard patterns. They are the same as for the wildcard matcher in the sitemap, thus simply use a * as wildcard (the ** syntax makes no sense here, as the pattern is evaluated on individual names, not on full paths).

Custom models

Syntax:

<fd:tree-model type="java" class="..."/>

whereby the class attribute specifies a class implementing TreeModel. The class can implement Avalon interfaces to get the Logger, ServiceManager and Context.

Programmatically assigning a model

Here's an example of how to build a tree model programatically using the provided DefaultTreeModel in flowscript:

importClass(Packages.org.apache.cocoon.forms.formmodel.tree.DefaultTreeModel);

[...]

var node1 = new DefaultTreeModel.DefaultTreeNode("node 1")
var node2 = new DefaultTreeModel.DefaultTreeNode("node 2")
var root = new DefaultTreeModel.DefaultTreeNode("root")
root.add("node1", node1);
node1.add("node2", node2);
var treeModel = new DefaultTreeModel(root);

var treeWidget = form.getChild("mytree");
treeWidget.setModel(treeModel);

Template

For the display of a tree widget, three special template elements are available:

  • ft:tree: global element to insert a tree widget in the template. This also inserts two hidden fields, ":path" and ":action" to communicate a node action to the server, see below.
  • ft:tree-nodes: the template to be executed for each tree node.
  • ft:tree-children: used inside ft:tree-nodes to recursively apply the ft:tree-nodes template to the child nodes.

A very rough example is:

<ft:tree id="mytree">
  <div>
    <ft:tree-nodes>
      <div>
        ${treeNode.node.data}
      </div>
      <ft:tree-children/>
    </ft:tree-nodes>
  </div>
</ft:tree>

This example just shows the typical structural rendering, but doesn't contain any styling and javascript actions to trigger expansion and collapsion of nodes.

Inside ft:tree you have access to two variables:

  • treeWidget, just a synonym for the normal "widget" variable that is available in the template of each widget.
  • treeNode, provides access to the current tree node being rendered. More specifically it is a TreeWalker instance. Its node property gives access to the actual tree node.
Note
The ${treeNode.node.data} expression in the template example above is specific to the form model you are using, since the node can be any object. The data property exists in the DefaultTreeModel nodes, however in the source tree model the nodes are Source objects, so you would use name instead of data.

Tree node actions

An action can be executed on a certain node in the tree. The available actions are:

  • expand
  • collapse
  • toggle-collapse
  • select
  • unselect
  • toggle-select

To execute an action, set the hidden field named tree-widget-full-name + ":action" to one of the actions listed above. The node on which the action is applied is specified in the hidden field named tree-widget-full-name + ":path". The node is specified as a slash-separated path of node keys. In the template you can access this easily with treeNode.path.

A more functional template

For a complete example of a tree template, see e.g. the file_explorer_template.xml file in the CForms samples. From there, you can "steal" the styling and the javascript to perform tree node actions.

API notes

See the API docs of the tree widgets for more information on how to access e.g. the selected nodes.