Package org.ribax.ui

Source Code of org.ribax.ui.RootFolder$FolderIconRenderer

/*
* RIBAX, Making Web Applications Easy
* Copyright (C) 2006 Damian Hamill and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.ribax.ui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.jdom.Element;

import org.ribax.utils.log.LOG;
import org.ribax.utils.xml.XMLutils;

import org.ribax.RIBAXApplet;
import org.ribax.parameters.ParameterSet;

/**
* RootFolders are used to break an application into distinct segments
* which are displayed simultaneously in a JSplitPane.  Each RootFolder can contain all
* the elements of a RIBAX GUI including the expandable folder tree.
*
* @version <tt>$Revision: $</tt>
* @author  <a href="mailto:damian@ribax.org">Damian Hamill</a>
*/

public class RootFolder extends JPanel implements  TabButtonListener {
   
    /** An expandable JTree which maybe displayed in the left side of the JSplitPane */
    protected JTree tree;
   
    /** The root node in the tree which contains a handle to the root Folder
     *
     * @see org.ribax.ui.Folder
     * */
    protected DefaultMutableTreeNode rootNode = null;

    /** The right side of a JSplitPane where the selected Folder is displayed */
    protected JPanel mainPanel = new JPanel();

    /** Each RootFolder can have a set of global parameters */
  private ParameterSet globalParams = null;
   
    /** */
    private ButtonPanel buttonPanel = null;

    /** Each RootFolder can have a button panel */
    private RIBAXApplet applet = null;
   
    /** Flags whether the root node in the tree is visible */
    private boolean rootIsVisible = true;
   
    /** Flags whether to display handles in the expandable JTree */
    private boolean showHandles = true;
   
    /** The Folder that is currently displayed */
    private Object nodeInfo = null;
   
    /** The name of the root folder  */
    protected String name = ""; //$NON-NLS-1$
   
    /** The displayable title  */
    protected String title = ""; //$NON-NLS-1$
   
    /** A short text description  */
    protected String description = null;

    /** Tooltip text for the root folder panel */
    protected String tooltip = null;
   
    /**
     * Constructor that creates a RootFolder using the given Element tree as a description
     * of the contents.
     *
     * @param applet the parent applet
     * @param root the Element tree containing the description of the contents of
     * this RootFolder
     */
    public RootFolder(RIBAXApplet applet,Element root) {
      this.applet = applet;
     
        // use BorderLayout for this and the mainPanel
        // Borderlayout.CENTRE ensures the components expand to fit the available space
      mainPanel.setLayout(new BorderLayout());
      setLayout(new BorderLayout());
       
    // read the description of this RootFolder
    rootNode = readDescription(root);
   
        // layout the RootFolder GUI components
    layoutComponents();
    }
 
    /**
     * Read the description of this RootFolder into a Folder and create the GUI
     * components of the Folder.
     *
     * @param node  the element tree containing the Folder description
     * @return a node that is the root node in an expandable JTree
     */
    private DefaultMutableTreeNode readDescription(Element node) {
    Element e;

        // create a new Folder that contains the contents of this RootFolder
    Folder f = new Folder(null);
       
        // get some basic attributes
       name = XMLutils.getElementString("name",node); //$NON-NLS-1$
       title = XMLutils.getElementString("title",node); //$NON-NLS-1$
       description = XMLutils.getElementString("description",node); //$NON-NLS-1$
      tooltip = XMLutils.getElementString("tooltip",node); //$NON-NLS-1$
     
    // read any global parameters
    if ((e = node.getChild("parameters")) != null) { //$NON-NLS-1$
        globalParams = ParameterSet.readParameters(e);
        ParameterSet.globalParameterSet = globalParams;
    }
   
        // read a button panel
    if ((e = node.getChild("buttons")) != null) { //$NON-NLS-1$
        buttonPanel = new ButtonPanel(this);
        buttonPanel.readButtons(e);
    }

        // is the root node visible
    Boolean bval = XMLutils.getElementBoolean("visible",node); //$NON-NLS-1$
    if (bval != null)
      rootIsVisible = bval.booleanValue();
   
        // are the tree handles visible
    bval = XMLutils.getElementBoolean("showHandles",node); //$NON-NLS-1$
    if (bval != null)
      showHandles = bval.booleanValue();
 
   
        // create a new JTree node with the Folder as the data object
    DefaultMutableTreeNode newnode = new DefaultMutableTreeNode(f);
   
        // read the Folder from the element tree
    f.readFolder(newnode, node);     
   
    return newnode; 
    }


    /**
     * Layout the GUI components for this RootFolder.  If the tree has more than 1 node then
     * we need to display the tree as well as the main panel.  However if the tree has only 1
     * node then there is no point displaying the tree as only 1 node can be selected so just
     * display the main panel as the contents of this RootFolder and dispense with the
     * JTree.
     *
     */
    private void layoutComponents() {
        if (rootNode == null) {
          return;
        }
        if (rootNode.getChildCount() > 0)
          layoutWithFolderTree();
        else
          layoutSingleFolder();
    }
   
    /**
     * Layout the GUI components for this RootFolder with an expandable JTree on the left
     * of a SplitPane and the main panel on the right.
     */
    private void layoutWithFolderTree() {
       
        // get the JTree Component
        tree = getFolderTree();
       
        if (rootIsVisible == false)
          // hide the root node
          tree.setRootVisible(false);
       
        // Enable tool tips.
        ToolTipManager.sharedInstance().registerComponent(tree);
       
        // embed the JTree in a scrollpane
      JScrollPane treeScrollPane = new JScrollPane(tree);

        // the left and right sides of the JSplitPane
        JComponent leftside, rightside = mainPanel;
           
      if (globalParams == null && buttonPanel == null) {
          //Create a split pane with the treePane on the left and the main panel on the right
        leftside = treeScrollPane;
      } else {
            /* the left side has global parameters and/or buttons so we need to create a
             * vertical split pane for the tree and the parameters/buttons           
            */
          JComponent globalParamsBox = globalParams;
         
          // globalparams could be null but buttonpanel could not be
          if (buttonPanel != null) {
                 // add buttonPanel to a vertical box with globalParams
            Box box = Box.createVerticalBox();
             
              if (globalParams != null) {
                box.add(globalParams);
                box.add(Box.createVerticalGlue());
              }
              box.add(buttonPanel);
             
              globalParamsBox = box;
          }

            // create the vertical split pane
          leftside = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
              treeScrollPane, new JScrollPane(globalParamsBox));      
      }

        // create the horizontal split pane with the left and right sides
      JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
              leftside, rightside);
      splitPane.setOneTouchExpandable(true);
       
        // set the divider location to be 150 pixels from the left
      splitPane.setDividerLocation(150);
       
        // add the split pane to this component
      add(splitPane, BorderLayout.CENTER);
     
    }
   
    /**
     *  Layout the GUI components for this RootFolder with the main panel containing the
     *  folder occupying all of the availabe space.  However if global parameters
     *   have been defined then we use a split pane anyway.
     */
    private void layoutSingleFolder() {
          
      // if there are global parameters then add them to the left side
      // and create a split pane anyway
      if (globalParams == null) {
            // no parameters have been defined so use all available space for the main panel
        add(mainPanel, BorderLayout.CENTER);
           
            // if a set of buttons have been defined then add them to the panel
            if (buttonPanel != null) {
                add(buttonPanel,buttonPanel.getLayoutLocation());
            }
      } else {
          // create a split pane with the global parameters on the left side
            // and the main panel on the right
          JComponent globalParamsBox = globalParams;
         
            // if a set of buttons have been defined then add them to the left side
          if (buttonPanel != null) {
              Box box = Box.createVerticalBox();
             
                // add buttonPanel to a vertical box with globalParams
              box.add(globalParams);
              box.add(Box.createVerticalGlue());
              box.add(buttonPanel);           
 
              globalParamsBox = box;
          }
          JScrollPane leftside = new JScrollPane(globalParamsBox);
        
          JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                  leftside, mainPanel);
          splitPane.setOneTouchExpandable(true);
           
            // set the divider location to be 150 pixels from the left
          splitPane.setDividerLocation(150);
         
            // add the split pane to this panel
          add(splitPane, BorderLayout.CENTER);         
      }
    }
   
    /**
     * Create a new JTree using the root node as the root of the tree
     * @return the newly created JTree
     */
    private JTree getFolderTree(){

      if(rootNode == null){
          throw new RuntimeException(Messages.getString("RootFolder.10")); //$NON-NLS-1$
      }
     
      final JTree tree = new JTree(rootNode);

        // this tree is not editable
      tree.setEditable(false);

        // setup some default properties
      tree.putClientProperty("JTree.lineStyle", "Angled"); //$NON-NLS-1$ //$NON-NLS-2$
      tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
      tree.setShowsRootHandles(showHandles);

        // set the cell renderer to display text and/or images
      tree.setCellRenderer(new FolderIconRenderer());
     
        /* when the user clicks on a tree node then load the Folder for the node
         * that is clicked
         */
      tree.addTreeSelectionListener(new TreeSelectionListener() {
          public void valueChanged(TreeSelectionEvent e) {
              @SuppressWarnings("unused")
                TreePath treePath = e.getNewLeadSelectionPath();
              DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
             
              if (node == null)
                  return;
                    
              Object nodeInfo = node.getUserObject();
          loadNodeObject(nodeInfo);
             
          }
        });
     
        // the maximum hieght of each row in the JTree
      int maxRowHeight = -1;
     
        /* determine the maximum height of the nodes in the JTree by getting the
         * maximum hieght of each Folder node in the tree.  It is helpful if using images
         * for Folder nodes that all images are the same height.
         */
      Enumeration<TreeNode> e = rootNode.breadthFirstEnumeration();
      DefaultMutableTreeNode node;
           
      Folder f = getFolderForNode(rootNode);
     
        // determine the maximum height of the root Folder node
      if (f != null) {
        ImageIcon icon;
        if ((icon = f.getFolderIcon()) != null) {
          maxRowHeight = Math.max(maxRowHeight,icon.getIconHeight());
        }
      }
     
        // determine the maximum height of all child nodes
      for ( ; e.hasMoreElements() ;) {
        node = (DefaultMutableTreeNode)e.nextElement();
        f = getFolderForNode(node);
       
        if (f != null) {
          ImageIcon icon;
          if ((icon = f.getFolderIcon()) != null) {
            maxRowHeight = Math.max(maxRowHeight,icon.getIconHeight());
          }
        }
      }
       
        // set the rowheight of the JTree to the maximum of the current height and the
        // maximum Folder node height
      int rowHeight = tree.getRowHeight();
      if (maxRowHeight > rowHeight)
        tree.setRowHeight(maxRowHeight);
     
      return tree;
    }  

    /**
     * Load the top level Folder for this RootFolder into the main panel
     */
    public void loadRootFolder() {
        // get the Folder for the root node
        Object nodeInfo = rootNode.getUserObject();  

        // load it into the main panel
      loadNodeObject(nodeInfo);
     
      // kick off garbage collection
      System.gc();
    }
   
   
    /**
     * Load the given Folder into the main panel.
     *
     * @param node the user object from the JTree node that should be a Folder/DataItem
     *
     * @see org.ribax.ui.Folder
     * @see org.ribax.ui.DataItem
     */
    private void loadNodeObject(Object node) {
       
        if (node == null)
            return;
       
        try {
          setCursor(new Cursor(Cursor.WAIT_CURSOR));
          
            this.nodeInfo = node;
      
          if (LOG.isDebugEnabled())
            LOG.debug(name+Messages.getString("RootFolder.13")+nodeInfo.toString()); //$NON-NLS-1$
           
            // the node object must be a DataItem
            if (nodeInfo instanceof DataItem) {
               
                // get the name or title of the Folder/DataItem
              String nodeName = ((DataItem)nodeInfo).getDataItemName();
              if (nodeName == null)
                nodeName = ((DataItem)nodeInfo).getTitle();
             
              applet.reportStatus(name+Messages.getString("RootFolder.14")+nodeName+Messages.getString("RootFolder.15")); //$NON-NLS-1$ //$NON-NLS-2$
             
                // tell the Folder to load it's data if it hasn't already done so
              if (globalParams == null)
                ((DataItem)nodeInfo).loadData(null,Messages.getString("RootFolder.16")); //$NON-NLS-1$
              else
                ((DataItem)nodeInfo).loadData(globalParams.getNameValuePairs(),"LoadData"); //$NON-NLS-1$
             
              applet.reportStatus(name+Messages.getString("RootFolder.18")+nodeName); //$NON-NLS-1$
            } else {
              LOG.info(name+Messages.getString("RootFolder.19")+nodeInfo.getClass().getName()); //$NON-NLS-1$
            }
           
          if (LOG.isDebugEnabled())
            LOG.debug(name+Messages.getString("RootFolder.20")+nodeInfo.toString()); //$NON-NLS-1$
        } finally {
          setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
       
        // update the UI so the selected Folder appears in the main panel
        mainPanel.removeAll();
        mainPanel.add((JComponent)nodeInfo,BorderLayout.CENTER);

        mainPanel.validate();
        mainPanel.repaint();
    }
   
   
    /**
     * Tell every item in the tree that it's data is out of date
     */
    private void invalidateItemTree() {
        Enumeration<TreeNode> e = rootNode.breadthFirstEnumeration();
        DefaultMutableTreeNode node;
       
        // invalidate the root object
        Object nodeInfo = rootNode.getUserObject();
        ((DataItem)nodeInfo).invalidateData();
       
        // invalidate all of the root object's descendents
        for ( ; e.hasMoreElements() ;) {
            node = (DefaultMutableTreeNode)e.nextElement();
            nodeInfo = node.getUserObject();
            ((DataItem)nodeInfo).invalidateData();
        }
    }
   

    /**
     * Tell every DataItem to stop whatever they are doing (like streaming).
     */
    public void stop() {
        Enumeration<TreeNode> e = rootNode.breadthFirstEnumeration();
        DefaultMutableTreeNode node;
       
        // tell the root Folder to stop
        Object nodeInfo = rootNode.getUserObject();
        ((DataItem)nodeInfo).close();
       
        // tell all of the root Folder's descendents to stop
        for ( ; e.hasMoreElements() ;) {
            node = (DefaultMutableTreeNode)e.nextElement();
            nodeInfo = node.getUserObject();
            ((DataItem)nodeInfo).close();
        }
    }

    /**
     * Handle a user button click from one of the buttons on the ButtonPanel in this
     * RootFolder.
     *
     * @see org.ribax.ui.TabButtonListener#doAction(int, java.lang.String)
     */
    public void doAction(int buttonType, String action) {

        if (nodeInfo == null)
            return;
       
        ArrayList params = null;
       
        if (globalParams != null)
            params = globalParams.getNameValuePairs();
       
        // pass the action to the current selected Folder
        if (buttonType == TabButton.REFRESH) {
          ((DataItem)nodeInfo).invalidateData();
            ((DataItem)nodeInfo).refresh(params,action);
        } else if (buttonType == TabButton.UPDATE)
            ((DataItem)nodeInfo).updateData(params,action);
        else if (buttonType == TabButton.RELOAD) {
            invalidateItemTree();
            ((DataItem)nodeInfo).refresh(params,action);
        }
    }
   
    /**
     * A class to display an image or text string to represent a Folder in an expandable
     * Folder JTree.
     *
     * @author damian
     *
     */
    private class FolderIconRenderer extends DefaultTreeCellRenderer {

      public FolderIconRenderer() {
      }
     
      /* (non-Javadoc)
       * @see javax.swing.tree.DefaultTreeCellRenderer#getTreeCellRendererComponent(javax.swing.JTree, java.lang.Object, boolean, boolean, boolean, int, boolean)
       */
      public Component getTreeCellRendererComponent(
                JTree tree,
                Object value,
                boolean sel,
                boolean expanded,
                boolean leaf,
                int row,
                boolean hasFocus) {

        super.getTreeCellRendererComponent(
                tree, value, sel,
                expanded, leaf, row,
                hasFocus);
       
        Folder f = getFolderForNode(value);
       
        if (f != null) {
          String folderName = f.getTitle();
         
          if (folderName == null || folderName.length() == 0)
            folderName = f.getDataItemName();
         
          if (f.getFolderIcon() != null) {
            setIcon(f.getFolderIcon());
          } else
            setText(folderName);
          setToolTipText(f.getTooltip());
        } else {
          setToolTipText(null); //no tool tip
        }

        return this;
      }
     
    }
   
  /**
     * Get the Folder for the given tree node.
     *
   * @param value the node containing the Folder
   * @return the Folder user object or null if it is not a Folder
   */
  protected static Folder getFolderForNode(Object value) {
        DefaultMutableTreeNode node =
                (DefaultMutableTreeNode)value;
        Object nodeInfo =
                (Object)(node.getUserObject());
       
        if (nodeInfo instanceof Folder)
          return (Folder)nodeInfo;

        return null;
    }
}
TOP

Related Classes of org.ribax.ui.RootFolder$FolderIconRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.