Click
Click Examples

Source Viewer : WEB-INF/classes/org/apache/click/examples/page/tree/CheckboxTreePage.java

package org.apache.click.examples.page.tree;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.click.Context;
import org.apache.click.control.Checkbox;
import org.apache.click.control.FieldSet;
import org.apache.click.control.Form;
import org.apache.click.control.Reset;
import org.apache.click.control.Submit;
import org.apache.click.examples.page.BorderPage;
import org.apache.click.examples.util.ExampleUtils;
import org.apache.click.extras.tree.CheckboxTree;
import org.apache.click.extras.tree.Tree;
import org.apache.click.extras.tree.TreeListener;
import org.apache.click.extras.tree.TreeNode;

/**
 * Example usage of the {@link CheckboxTree} control.
 */
public class CheckboxTreePage extends BorderPage implements TreeListener {

    private static final long serialVersionUID = 1L;

    public static final String TREE_NODES_SESSION_KEY = "checkboxTreeNodes";

    private CheckboxTree tree;
    private Form form;
    private Submit okSubmit;
    private Reset resetBtn;

    //  Event Handlers --------------------------------------------------------

    /**
     * @see org.apache.click.Page#onInit()
     */
    @Override
    public void onInit() {
        super.onInit();

        // The checkbox tree needs to be placed inside a form so all the
        // checkbox values can be submitted to the server when we submit
        // the form.
        form = new Form("form");

        // Create the tree and tree model and add it to the page
        tree = buildTree();
        tree.addListener(this);

        // Add the tree to the form.
        form.add(tree);

        okSubmit = new Submit("select", "Select");
        resetBtn = new Reset("reset", "Reset");

        form.add(okSubmit);
        form.add(resetBtn);

        addControl(form);

        // Build the options user interface for users to interactively
        // change the tree values.
        buildOptionsUI();
    }

    // Public Methods ---------------------------------------------------------

    /**
     * Creates and return a new tree instance.
     *
     * @return a new CheckboxTree instance
     */
    public CheckboxTree createTree() {
        return new CheckboxTree("checkboxTree");
    }

    /**
     * Build the tree model and stores it in the session.
     *
     * @return a new CheckboxTree instance
     */
    public CheckboxTree buildTree() {
        tree = createTree();

        // Try and load the already stored nodes from the session.
        // If this is the first time we access the page, this method
        // will return null, indicating no nodes is stored.
        TreeNode existingRootNode = loadNodesFromSession();

        if(existingRootNode != null) {
            // OK we had already nodes stored in the session, so no need
            // to rebuild them. We attach the root node and return.
            tree.setRootNode(existingRootNode);

            return tree;
        }

        // Create a node representing the root directory with the specified
        // parameter as the value. Because an id is not specified, a random
        // one will be generated by the node. By default the root node is
        // not rendered by the tree. This can be changed by calling
        // tree.setRootNodeDisplayed(true).
        TreeNode root = new TreeNode("c:");

        // Create a new directory, setting the root directory as its parent. Here
        // we do specify a id as the 2nd argument, so no id is generated.
        TreeNode dev = new TreeNode("dev","1");
        root.add(dev);

        // The following 3 nodes represent files in the directory as children of
        // the dev node. Note the false argument to the constructor.
        // This means that the specific node does not support child nodes, and
        // it will be rendered as a leaf icon. If children are supported (the
        // default value) then even  if the node is a leaf, it will still be rendered
        // as a collapsed icon. In the example a default leaf node will be
        // rendered as a directory, and a node that does not support children is
        // rendered as a file.
        // Also note the node with the long text, will cause the tree to overflow
        // and add scrollbars
        dev.add(new TreeNode("java.pdf", "1.1", false));
        dev.add(new TreeNode("JEE 6 - the new fantastic approach to write better software (apparently)", "1.2", false));
        dev.add(new TreeNode("ruby.pdf", "1.3", false));

        //We continue constructing the rest of the tree
        TreeNode programFiles = new TreeNode("program files", "2");
        root.add(programFiles);
        programFiles.add(new TreeNode("Adobe", "2.1"));

        TreeNode download = new TreeNode("downloads","3");
        root.add(download);

        TreeNode web = new TreeNode("web", "3.1");
        download.add(web);
        web.add(new TreeNode("html.pdf", "3.1.1", false));
        web.add(new TreeNode("css.html", "3.1.2", false));

        TreeNode databases = new TreeNode("databases", "3.2");
        download.add(databases);
        TreeNode relationalDb = new TreeNode("relational", "3.2.1");
        databases.add(relationalDb);

        relationalDb.add(new TreeNode("mysql.html", "3.2.1.1",false));
        relationalDb.add(new TreeNode("oracle.pdf", "3.2.1.2", false));
        relationalDb.add(new TreeNode("postgres", "3.2.1.3", false));

        TreeNode objectDb = new TreeNode("object", "3.2.2");
        databases.add(objectDb);
        objectDb.add(new TreeNode("db4o.html", "3.2.2.1", false));

        // Attach the root node containing all the other nodes to the tree
        tree.setRootNode(root);

        // By default root node is not displayed in browser. Here we expand it,
        // so that the root's children are visible.
        expandRoot();

        // Store the tree nodes in the session so on the next request we do not
        // have to rebuild it. Also because we keep the tree nodes in the session
        // the nodes will keep their state between requests.
        storeNodesInSession(root);

        return tree;
    }

    // TreeListener Support ---------------------------------------------------

    /**
     * This method, which implements TreeListener, is called when a node is selected
     */
    public void nodeSelected(Tree tree, TreeNode node, Context context, boolean oldValue) {
        List list = getModelValue("selected");
        list.add(node);
    }

    /**
     * This method, which implements TreeListener, is called when a node is deselected
     */
    public void nodeDeselected(Tree tree, TreeNode node, Context context, boolean oldValue) {
        List list = getModelValue("deselected");
        list.add(node);
    }

    /**
     * This method, which implements TreeListener, is called when a node is expanded
     */
    public void nodeExpanded(Tree tree, TreeNode node, Context context, boolean oldValue) {
        List list = getModelValue("expanded");
        list.add(node);
    }

    /**
     * This method, which implements TreeListener, is called when a node is collapsed
     */
    public void nodeCollapsed(Tree tree, TreeNode node, Context context, boolean oldValue) {
        List list = getModelValue("collapsed");
        list.add(node);
    }

    /**
     * Returns the value for the specified name from the page's model.
     * If a value is not found, a new ArrayList is created and added to the model.
     */
    private List getModelValue(String name) {
        List list = (List) getModel().get(name);
        if(list == null) {
            list = new ArrayList();
            addModel(name, list);
        }
        return list;
    }

    // NOTE -------------------------------------------------------------------
    //The code below is not specific to tree control usage.

    private Form optionsForm;
    private Checkbox jsEnabled = new Checkbox("jsEnabled", "JavaScript Enabled");
    private Checkbox rootNodeDisplayed = new Checkbox("rootNodeDisplayed", "Display root node");
    private Checkbox selectChildNodes = new Checkbox("selectChildNodes", "Select child nodes");
    private Submit applyOptions = new Submit("apply", "Apply Options", this, "onApplyOptionsClick");

    /**
     * Called when user submits the options form.
     */
    public boolean onApplyOptionsClick() {
        //Reset the tree and nodes to default values
        resetTree();

        //Store the users options in the session
        CheckboxTreeOptions options = new CheckboxTreeOptions();
        options.javascriptEnabled = jsEnabled.isChecked();
        options.rootNodeDisplayed = rootNodeDisplayed.isChecked();
        options.selectChildNodes = selectChildNodes.isChecked();
        ExampleUtils.setSessionObject(options);

        //Apply users new options
        applyOptions();

        return true;
    }

    /**
     * Builds the user interface for users to change the tree options interactively.
     */
    public void buildOptionsUI() {
        //Form to handle user selected options
        optionsForm = new Form("optionForm");
        FieldSet fieldSet = new FieldSet("options", "Form Options");
        fieldSet.add(jsEnabled);
        fieldSet.add(rootNodeDisplayed);
        fieldSet.add(selectChildNodes);
        optionsForm.add(fieldSet);

        addControl(optionsForm);
        optionsForm.add(applyOptions);

        //Apply users existing options
        applyOptions();
    }

    /** Form options holder. */
    public static class CheckboxTreeOptions implements Serializable {
        private static final long serialVersionUID = 1L;
        boolean javascriptEnabled= false;
        boolean rootNodeDisplayed = false;
        boolean selectChildNodes = false;
    }

    /**
     * Reset the tree to initial state
     */
    private void resetTree() {
        // Remove any Session entries made by Tree
        tree.cleanupSession();

        //Temporarily disable notification to any tree listeners while we reset the tree
        tree.setNotifyListeners(false);

        //Clear all current selections so the tree can start afresh with new options enabled
        tree.deselectAll();
        tree.collapseAll();

        //Enable notification to any tree listeners again
        tree.setNotifyListeners(true);

        if(!rootNodeDisplayed.isChecked()) {
            //If rootNodeDisplayed is false, the root node is not displayed in browser. Here we
            //expand it,  so that the root's children are visible.
            expandRoot();
        }
    }

    /**
     * Store the tree nodes in the session
     */
    private void storeNodesInSession(TreeNode rootNode) {
        if (tree.getRootNode() == null) {
            return;
        }

        getContext().getSession().setAttribute(TREE_NODES_SESSION_KEY, rootNode);
    }

    /**
     * Retrieve the tree nodes from the session if available. Otherwise we return
     * null.
     */
    private TreeNode loadNodesFromSession() {
        return (TreeNode) getContext().getSession().getAttribute(TREE_NODES_SESSION_KEY);
    }

    /**
     * Enable javascript so that there are no round trips to server
     * when expand and collapsing nodes.
     */
    private void enableJavascript(boolean enable) {
        //This call enables the client side javascript functionality
        tree.setJavascriptEnabled(enable);
    }

    /**
     * Applies the user selected options to the tree like enabling javascript,
     * displaying the root node etc.
     */
    private void applyOptions() {

        //We retrieve our stored options from the session and set the controls state
        CheckboxTreeOptions options = (CheckboxTreeOptions)
            ExampleUtils.getSessionObject(CheckboxTreeOptions.class);

        jsEnabled.setChecked(options.javascriptEnabled);
        rootNodeDisplayed.setChecked(options.rootNodeDisplayed);
        selectChildNodes.setChecked(options.selectChildNodes);

        //Enable or disable javascript functionality based on users current option
        enableJavascript(options.javascriptEnabled);

        //Indicates if we want to display the root node or not.
        tree.setRootNodeDisplayed(options.rootNodeDisplayed);

        //Indicates if the tree should recursively select child nodes.
        tree.setSelectChildNodes(options.selectChildNodes);
    }

    /**
     * Expand the root but do not notify any tree listeners of the change.
     */
    private void expandRoot() {
        //Temporarily disable notification to any tree listeners while we expand the root node
        tree.setNotifyListeners(false);

        tree.expand(tree.getRootNode());

        //Enable notification to any tree listeners again
        tree.setNotifyListeners(true);
    }
}