You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ecs-dev@jakarta.apache.org by rd...@apache.org on 2001/11/07 00:09:49 UTC

cvs commit: jakarta-ecs/src/java/org/apache/ecs/examples HtmlTree.java

rdonkin     01/11/06 15:09:49

  Added:       src/java/org/apache/ecs/examples HtmlTree.java
  Log:
  Added ecs HtmlTree example by Christian Brensing <ho...@gmx.de>
  
  Revision  Changes    Path
  1.1                  jakarta-ecs/src/java/org/apache/ecs/examples/HtmlTree.java
  
  Index: HtmlTree.java
  ===================================================================
  /*
   * Copyright (c) 1999 The Java Apache Project.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project. <http://java.apache.org/>"
   *
   * 4. The names "Java Apache Element Construction Set", "Java Apache ECS" and 
   *    "Java Apache Project" must not be used to endorse or promote products 
   *    derived from this software without prior written permission.
   *
   * 5. Products derived from this software may not be called 
   *    "Java Apache Element Construction Set" nor "Java Apache ECS" appear 
   *    in their names without prior written permission of the 
   *    Java Apache Project.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project. <http://java.apache.org/>"
   *    
   * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Java Apache Project. For more information
   * on the Java Apache Project please see <http://java.apache.org/>.
   *
   */
  
  package org.apache.ecs.examples;
  
  import java.io.*;
  import java.util.*;
  import javax.swing.tree.*;
  import org.apache.ecs.xml.*;
  import org.apache.ecs.html.*;
  
  /**
   * This JavaBean returns the hierarchical structure described in a
   * javax.swing.tree.DefaultMutableTreeNode as valid XHTML. This class
   * is a very simple counterpart of the javax.swing.JTree with the
   * exception that the external Controller is integrated into this View.
   * If you want your tree elements (nodes and leafs) to be marked with an
   * anchor, you'll have to make sure that the name of your node contains
   * such an anchor.
   *
   * <p>You can use this class in a JavaServerPage like this:</p>
   *
   * <p><blockquote>
   *    <p>...template text...</p>
   *    <p><code>
   *      &lt;%-- Get the bean from the request scope or
   *      create a new one if none exits --%&gt;<br />
   *      &lt;jsp:useBean id="tree" scope="request"
   *      class="org.apache.ecs.examples.HtmlTree"&gt;
   *      <blockquote>
   *        <p>&lt;%-- Read the path from the request --%&gt;<br />
   *        &lt;jsp:setProperty name="tree"
   *        property="path" param="path" /&gt;</p>
   *        <p>&lt;%-- Set bean properties --%&gt;<br />
   *        &lt;jsp:setProperty name="tree"
   *        property="rootVisible" value="true" /&gt;<br />
   *        &lt;jsp:setProperty name="tree"
   *        property="indentation" value="2" /&gt;<br />
   *        &lt;jsp:setProperty name="tree"
   *        property="openIcon" value="open.gif" /&gt;<br />
   *        &lt;jsp:setProperty name="tree"
   *        property="closedIcon" value="closed.gif" /&gt;<br />
   *        &lt;jsp:setProperty name="tree"
   *        property="leafIcon" value="leaf.gif" /&gt;</p>
   *        <p>&lt;%-- Workaround for Netscape
   *        and Opera browsers --%&gt;<br />
   *        &lt;jsp:setProperty name="tree"
   *        property="action" value="tree.jsp" /&gt;</p>
   *      </blockquote>
   *      &lt;/jsp:useBean&gt;
   *    </code></p>
   *    <p>...template text...</p>
   *    <p><code>
   *      &lt;%-- Get the XHTML output from the bean --%&gt;<br />
   *      &lt;jsp:getProperty name="tree" property="html" /&gt;
   *    </code></p>
   * </blockquote></p>
   *
   * Although this class is just an example of using parts of the Element
   * Construction Set, you can use it quite well in real web applications.
   *
   * @version 1.0, 2001/10/30
   * @author <a href="mailto:horombo@gmx.de">Christian Brensing</a>
   */
  public class HtmlTree implements Serializable {
  
    /**
     * Number of blank spaces around each hierarchical level
     * will be indented in relation to its parent node.
     * Default is 2.
     */
    protected int indentation = 2;
  
    /**
     * Path to the requested node to be displayed,
     * described as colon separated integer values.
     * Default is an empty String.
     */
    protected String path = new String();
  
    /**
     * Parameter name used to build the query string for the
     * anchor that acts as the Controller for opening and
     * closing nodes. Default is &quot;path&quot;.
     */
    protected String parameterName = new String("path");
  
    /**
     * Array that stores the index of each node
     * read from the path property.
     */
    private int[] pathArray = new int[0];
  
    /**
     * Icon for displaying leafs.
     * Default is an empty String.
     */
    protected String leafIcon = new String();
  
    /**
     * Icon for displaying open nodes.
     * Default is an empty String.
     */
    protected String openIcon = new String();
  
    /**
     * Icon for displaying closed nodes.
     * Default is an empty String.
     */
    protected String closedIcon = new String();
  
    /**
     * Context path of a web resource for the workaround
     * of a strange behaviour of Netscape and Opera
     * browsers. Default is an empty String.
     */
    protected String action = new String();
  
    /**
     * True if the root node is displayed, false if
     * its children are the highest visible nodes.
     * Default is true.
     */
    protected boolean rootVisible = true;
  
    /**
     * The node that defines the tree displayed by this object.
     * Default is a sample model.
     */
    protected DefaultMutableTreeNode root = getDemoModel();
  
    /**
     * Stores the requested node to be displayed.
     * Default is the root node.
     */
    private DefaultMutableTreeNode displayNode = root;
  
    /**
     * Returns a HtmlTree with a sample model.
     */
    public HtmlTree() {
    } // Constructor
  
    /**
     * Returns a HtmlTree with the specified DefaultMutableTreeNode
     * as its root. If the DefaultMutableTreeNode is <tt>null</tt>,
     * a sample model is set automatically.
     *
     * @param root a DefaultMutableTreeNode object
     */
    public HtmlTree(DefaultMutableTreeNode root) {
  
      setRoot(root);
  
    } // Constructor
  
    /**
     * Sets the root node that will provide the data. If the
     * specified DefaultMutableTreeNode is <tt>null</tt>,
     * a sample model is set automatically.
     *
     * @param root a DefaultMutableTreeNode object
     */
    public void setRoot(DefaultMutableTreeNode root) {
  
      // Check property
      if (root == null) { root = getDemoModel(); }
  
      // Set property
      this.root = root;
  
    } // setRoot
  
    /**
     * Sets the path - described as colon separated integer values -
     * to the requested node to be displayed.
     *
     * @param path the path to the requested node to be displayed
     */
    public void setPath(String path) {
  
      // Check property
      if (path == null) { path = new String(); }
  
      // Set property
      this.path = path;
  
      // Tokenize the path
      StringTokenizer st = new StringTokenizer(path,":");
  
      // Reset path array
      pathArray = new int[st.countTokens()];
  
      // Save value of each token in the array
      if (st.countTokens() > 0) {
        for (int i = 0; i <= st.countTokens(); i++) {
          pathArray[i] = Integer.
          parseInt(st.nextToken().trim());
        } // next i
      } // end if
  
    } // setPath
  
    /**
     * Returns a path constructed from the path array for the
     * specified level.
     *
     * @param level the distance from the node to the root node.
     * @return the path for the specified level
     */
    private String getPath(int level) {
  
      // New StringBuffer for the path generation
      StringBuffer autoPath = new StringBuffer();
  
      // For each node
      for (int i = 0; i < level; i++) {
  
        // Add node index (read from the path array)
        autoPath.append(pathArray[i]);
  
        // Add path separator (colon)
        if (i < (level - 1)) { autoPath.append(":"); }
  
      } // next i
  
      // Return generated path
      return autoPath.toString();
  
    } // getPath
  
    /**
     * Sets the name of the parameter used to build the query
     * string for the anchor that acts as the Controller for
     * opening and closing nodes. You only have to set this
     * name when the default name &quot;path&quot; is already
     * used by your web application.
     *
     * @param parameterName the name of the parameter used to
     * build the query string
     */
    public void setParameterName(String parameterName) {
  
      // Check property
      if (parameterName == null ||
      parameterName.equals("")) {
      parameterName = new String("path"); }
  
      // Set property
      this.parameterName = parameterName;
  
    } // setParameterName
  
    /**
     * Returns the name of the parameter used to build the
     * query string for the anchor that acts as the Controller
     * for opening and closing nodes.
     *
     * @return the name of the parameter
     */
    public String getParameterName() {
  
      return parameterName;
  
    } // getParameterName
  
    /**
     * Determines whether or not the root node is visible.
     *
     * @param rootVisible true if the root node of the tree
     * is to be displayed
     */
    public void setRootVisible(boolean rootVisible) {
  
      this.rootVisible = rootVisible;
  
    } // setRootVisible
  
    /**
     * Returns true if the root node of the tree is displayed.
     *
     * @return true if the root node of the tree is displayed
     */
    public boolean isRootVisible() {
  
      return rootVisible;
  
    } // isRootVisible
  
    /**
     * Sets the number of blank spaces around each hierarchical
     * level will be indented in relation to its parent node.
     *
     * @param indentation the number of blank spaces
     */
    public void setIndentation(int indentation) {
  
      this.indentation = indentation;
  
    } // setIndentation
  
    /**
     * Sets the icon for displaying open nodes.
     *
     * @param openIcon the URI of an image file
     */
    public void setOpenIcon(String openIcon) {
  
      this.openIcon = openIcon;
  
    } // setOpenIcon
  
    /**
     * Sets the icon for displaying closed nodes.
     *
     * @param closedIcon the URI of an image file
     */
    public void setClosedIcon(String closedIcon) {
  
      this.closedIcon = closedIcon;
  
    } // setClosedIcon
  
    /**
     * Sets the icon for displaying leafs.
     *
     * @param leafIcon the URI of an image file
     */
    public void setLeafIcon(String leafIcon) {
  
      this.leafIcon = leafIcon;
  
    } // setLeafIcon
  
    /**
     * Workaround of a strange behaviour of Netscape and Opera browsers.
     * In these browsers the relative URL containg only the query string
     * with the path information (e.g. &quot;?path=0:1&quot;) are not
     * translated correctly into an absoulte URL. By setting a context
     * path, on which to append the query string, this behaviour should
     * be fixed.
     *
     * @param action the context path of a web resource (e.g. a JSP-File)
     */
    public void setAction(String action) {
  
      this.action = action;
  
    } // setAction
  
    /**
     * Returns the name of the currently expanded node to
     * be displayed.
     *
     * @return the name of the node to be displayed
     */
    public String getNodeName() {
  
      return expand().toString();
  
    } // getNodeName
  
    /**
     * Constructs a valid XHTML &lt;img&gt;-tag from the specified icon.
     * Although this method uses the xml-package to generate a valid tag,
     * the xhtml-package would provide the same functionality.
     *
     * @param icon the URI of an image file
     * @return a valid XHTML &lt;img&gt;-tag
     */
    private String getImg(String icon) {
  
      // New <img>
      XML img = new XML("img",false);
  
      // Check specified icon property
      if (icon == null) { icon = new String(); }
  
      // Set src attribute
      img.addAttribute("src",icon);
  
      // return <img>
      return img.toString();
  
    } // getImg
  
    /**
     * Expands the tree by following the specified path
     * and returns the requested node to be displayed
     *
     * @return the requested node to be displayed
     */
    private DefaultMutableTreeNode expand() {
  
      // Reset node to be displayed
      displayNode = root;
  
      // Iterate trough the path array
      for (int i = 0; i < pathArray.length; i++) {
        displayNode = (DefaultMutableTreeNode)
        displayNode.getChildAt(pathArray[i]);
      } // next i
  
      // Return node to be displayed
      return displayNode;
  
    } // expand
  
    /**
     * Returns the hierarchical structure described in the specified root
     * node as valid XHTML. For perfomance reasons all parent nodes of the
     * requested node are collapsed. The source code does not contain any
     * formatting tags or attributes. I recommend that you use Cascading
     * Style Sheets instead. For this purpose, the tree elements are marked
     * with the class attribute values &quot;tree&quot;, &quot;parent&quot;
     * and &quot;child&quot;.
     *
     * @return the hierarchical structure within a &lt;table&gt;-tag
     */
    public String getHtml() {
  
      // Expand the tree
      displayNode = expand();
  
      // New <table>
      Table table = new Table();
      table.setClass("tree");
  
      // Reset auto indentation
      int autoIndentation = 0;
  
      // Initialize ancestor node with the first
      // child of the node to be displayed
      TreeNode ancestor = displayNode.getFirstChild();
  
      // Read all ancestors into an array
      ArrayList list = new ArrayList();
      while ((ancestor = ancestor.getParent())
      != null) { list.add(ancestor); }
  
      // For each ancestor (ordered desc beginning at the root)
      for (int index = list.size(); index > 0; index--) {
  
        // Get current ancestor
        DefaultMutableTreeNode parent =
        (DefaultMutableTreeNode)list.
        get(index-1);
  
        // Displays the ancestor if it's not the root
        // or the isRootVisible property is set to true
        if (!parent.isRoot() || rootVisible) {
  
          // New <td>
          TD td = new TD();
          td.setClass("parent");
  
          // Generate href for this ancestor (the
          // level is decreased by one to provide
          // an anchor to its parent node)
          String href = action.concat("?").
          concat(parameterName).concat("=").
          concat(getPath(parent.getLevel()-1));
  
          // Add indentation to <td>
          for (int i = 0; i < autoIndentation; i++)
          { td.addElement("&nbsp;"); }
  
          // Add icon with <a> to <td>
          td.addElement(new A(href,getImg(openIcon)));
  
          // Add ancestor with <nobr> to <td>
          td.addElement(new NOBR(parent.toString()));
  
          // Add <td> to <tr> to <table>
          table.addElement(new TR(td));
  
          // Increment auto indentation
          autoIndentation = autoIndentation + indentation;
  
        } // end if rootVisible
  
      } // next index
  
      // For each child
      for (int index = 0; index < displayNode.getChildCount(); index++) {
  
        // New <td>
        TD td = new TD();
        td.setClass("child");
  
        // Get current child
        DefaultMutableTreeNode child =
        (DefaultMutableTreeNode)displayNode.
        getChildAt(index);
  
        // Generate path == path + child index
        String autoPath = getPath(child.getLevel()-1).
        concat(":").concat(String.valueOf(index));
  
        // Generate href for this child
        String href = action.concat("?").
        concat(parameterName).concat("=").
        concat(autoPath);
  
        // Add indentation to <td>
        for (int i = 0; i < autoIndentation; i++)
        { td.addElement("&nbsp;"); }
  
        // New <img> with default leaf icon
        String img = getImg(leafIcon);
  
        // Set closed node icon, if child is not a leaf
        if (!child.isLeaf()) { img = getImg(closedIcon); }
  
        // Add icon with <a> (not for leafs) to <td>
        if (!child.isLeaf()) {td.addElement(new A(href,img)); }
  
        // Add icon without <a> (leafs only) to <td>
        if (child.isLeaf()) { td.addElement(img); }
  
        // Add child with <nobr> to <td>
        td.addElement(new NOBR(child.toString()));
  
        // Add <td> to <tr> to <table>
        table.addElement(new TR(td));
  
      } // next index
  
      // Return <table>
      return table.toString();
  
    } // getHtml
  
    /**
     * Returns a sample tree model.
     *
     * @return a DefaultMutableTreeNode with a sample tree model
     */
    private DefaultMutableTreeNode getDemoModel() {
  
      // New root node
      DefaultMutableTreeNode root =
      new DefaultMutableTreeNode("Root");
  
      // First level
      for (int i = 1; i <= 5; i++) {
  
        // New node
        DefaultMutableTreeNode child =
        new DefaultMutableTreeNode("Folder-" + i);
  
        // Add node to root
        root.add(child);
  
        // Second level
        for (int j = 1; j <= 3; j++) {
  
          // New node
          DefaultMutableTreeNode subchild =
          new DefaultMutableTreeNode("Subfolder-" + j);
  
          // Add node to parent node
          child.add(subchild);
  
          // Third level
          for (int k = 1; k <= 3; k++) {
  
            // New anchor
            A a = new A("http://jakarta.apache.org");
            a.setTarget("target").addElement("Document-" + k);
  
            // New node (leaf)
            DefaultMutableTreeNode document =
            new DefaultMutableTreeNode(a.toString());
  
            // Add node to parent node
            subchild.add(document);
  
          } // next k
  
        } // next j
  
      } // next i
  
      // Return root node
      return root;
  
    } // getDemoModel
  
  } // HtmlTree
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>