Friday, July 06, 2012

JSF 2.1 Custom PrimeFaces 3.3 Tree Example

Custom PrimeFaces Tree
I was looking at the default implementation of PrimeFaces <p:tree /> and <p:treeNode />. The default looks nice, but I wanted a different look with different icons.

The icons I picked look more like "nodes" and "documents. The icons are by Yusuke Kamiyamane in his Fugue Icon set. These icons are released under a Creative Commons 3.0 Attribution License.

I also wanted a more flexible tree model with a custom TreeNode implementation that uses node types (node, leaf), and a data component which is represented by an Object.

The result is a nice looking tree that changes icons subtly on selection, or deselection of a node, and leaf nodes are displayed as document icons.


The Apache Maven project was developed using NetBeans 7, GlassFish 3.1.2, and PrimeFaces 3.3.1


The source code can be downloaded here: primefaces-custom-tree.zip

index.xhtml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Custom PrimeFaces Tree</title>
        <h:outputStylesheet name="custom-tree.css" library="css"/>
    </h:head>
    <h:body>
        <h:form id="form1">
            <p:panel id="panel1" header="Custom PrimeFaces Tree">
                <p:growl id="growl1" showSummary="true" showDetail="true" autoUpdate="true"/>
 
                <p:tree id="tree1" value="#{treeBean.model}"
                        var="node"
                        selectionMode="single"
                        selection="#{treeBean.selectedNode}"
                        >
                    <p:ajax event="select"  listener="#{treeBean.onNodeSelect}" />
                    <p:ajax event="expand" listener="#{treeBean.onNodeExpand}" />
                    <p:ajax event="collapse" listener="#{treeBean.onNodeCollapse}" />
                    <p:treeNode type="node"
                                expandedIcon="folder-open"
                                collapsedIcon="folder-collapsed">
                        <h:outputText value="#{node}"/>
                    </p:treeNode>
                    <p:treeNode type="leaf" icon="document-node">
                        <h:outputText value="#{node}" />
                    </p:treeNode>
                </p:tree>
            </p:panel>
        </h:form>
    </h:body>
</html>

TreeNodeImpl.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.bluelotussoftware.example.jsf;
 
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
 
/**
 * Extension of the {@link org.primefaces.model.DefaultTreeNode} class that
 * overrides the node type, and includes a data component.
 *
 * @see org.primefaces.model.DefaultTreeNode
 * @author John Yeary
 * @version 1.0
 */
public class TreeNodeImpl extends DefaultTreeNode {
 
    private static final long serialVersionUID = 5333810777428638968L;
 
    /**
     * Constructor which sets the {@link com.bluelotussoftware.example.jsf.TreeNodeType}, {@code Object}
     * data, and parent node.
     *
     * @param type The type of node this represents.
     * @param data {@code Object} value stored in the node.
     * @param parent the {@link org.primefaces.model.TreeNode} which is the
     * parent to this object, or {@code null} if this is the "root"
     * node.
     */
    public TreeNodeImpl(TreeNodeType type, Object data, TreeNode parent) {
        super(type.getType(), data, parent);
    }
 
    /**
     * Constructor which sets {@code Object} data, and parent node.
     *
     * @param data {@code Object} value stored in the node.
     * @param parent parent the {@link org.primefaces.model.TreeNode} which is
     * the parent to this object, or {@code null} if this is the
     * "root" node.
     */
    public TreeNodeImpl(Object data, TreeNode parent) {
        super(data, parent);
    }
 
    /**
     * This method returns {@link com.bluelotussoftware.example.jsf.TreeNodeType#getType()}
     * depending on whether the node is a "leaf" node which contains
     * no children, or a "node" if it contains children.
     *
     * @return {@link com.bluelotussoftware.example.jsf.TreeNodeType#getType()}
     * based on whether this node has child objects.
     */
    @Override
    public String getType() {
        if (isLeaf()) {
            return TreeNodeType.LEAF.getType();
        } else {
            return TreeNodeType.NODE.getType();
        }
    }
}

TreeNodeType.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.bluelotussoftware.example.jsf;
 
/**
 * {@code enum} which represents the types of tree objects as either
 * "leaf", or "node".
 *
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public enum TreeNodeType {
 
    LEAF("leaf"), NODE("node");
    private String type;
 
    private TreeNodeType(final String type) {
        this.type = type;
    }
 
    @Override
    public String toString() {
        return type;
    }
 
    public String getType() {
        return type;
    }
}

TreeBean.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.bluelotussoftware.example.jsf;
 
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.primefaces.event.NodeCollapseEvent;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.TreeNode;
 
/**
 * Page backing bean which manages page data and events.
 *
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
@ManagedBean
@ViewScoped
public class TreeBean implements Serializable {
 
    private static final long serialVersionUID = 2417620239014385855L;
    private TreeNode root;
    private TreeNode selectedNode;
 
    /**
     * Default constructor
     */
    public TreeBean() {
        root = new TreeNodeImpl("Root", null);
        TreeNode node0 = new TreeNodeImpl("Segment 0", root);
        TreeNode node1 = new TreeNodeImpl("Segment 1", root);
        TreeNode node2 = new TreeNodeImpl("Segment 2", root);
        TreeNode node00 = new TreeNodeImpl("Segment 0.0", node0);
        TreeNode node01 = new TreeNodeImpl("Segment 0.1", node0);
        TreeNode node10 = new TreeNodeImpl("Segment 1.0", node1);
        TreeNode node11 = new TreeNodeImpl("Segment 1.1", node1);
        TreeNode node000 = new TreeNodeImpl("Segment 0.0.0", node00);
        TreeNode node001 = new TreeNodeImpl("Segment 0.0.1", node00);
        TreeNode node010 = new TreeNodeImpl("Segment 0.1.0", node01);
        TreeNode node100 = new TreeNodeImpl("Segment 1.0.0", node10);
 
    }
 
    /**
     * This method returns the tree model based on the root node.
     *
     * @return root node.
     */
    public TreeNode getModel() {
        return root;
    }
 
    /**
     * Gets the selected node in the tree.
     *
     * @return selected node in tree.
     */
    public TreeNode getSelectedNode() {
        return selectedNode;
    }
 
    /**
     * Sets the selected node in the tree.
     *
     * @param selectedNode node to be set as selected.
     */
    public void setSelectedNode(TreeNode selectedNode) {
        this.selectedNode = selectedNode;
    }
 
    /**
     * {@inheritDoc }
     *
     * Adds a {@link javax.faces.application.FacesMessage} with event data to
     * the {@link javax.faces.context.FacesContext}.
     */
    public void onNodeSelect(NodeSelectEvent event) {
        System.out.println("NodeSelectEvent Fired");
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected", event.getTreeNode().getData().toString());
        FacesContext.getCurrentInstance().addMessage(event.getComponent().getId(), msg);
    }
 
    /**
     * {@inheritDoc}
     *
     * Adds a {@link javax.faces.application.FacesMessage} with event data to
     * the {@link javax.faces.context.FacesContext}.
     */
    public void onNodeExpand(NodeExpandEvent event) {
 
        System.out.println("NodeExpandEvent Fired");
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Expanded", event.getTreeNode().getData().toString());
        FacesContext.getCurrentInstance().addMessage(event.getComponent().getId(), msg);
    }
 
    /**
     * {@inheritDoc}
     *
     * Adds a {@link javax.faces.application.FacesMessage} with event data to
     * the {@link javax.faces.context.FacesContext}.
     */
    public void onNodeCollapse(NodeCollapseEvent event) {
        System.out.println("NodeCollapseEvent Fired");
        FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Collapsed", event.getTreeNode().getData().toString());
        FacesContext.getCurrentInstance().addMessage(event.getComponent().getId(), msg);
    }
}

0 comments :

Popular Posts