commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Eric Galluzzo <egallu...@einnovation.com>
Subject Re: BasicDynaBean and overriding the toString()
Date Tue, 02 Dec 2003 19:56:16 GMT
dumdum 420 wrote:

> I know this is not the place but can u share you custom TreeModel and 
> how are u doing your job with that using the DynaBean. (it will be fun 
> to know :))

Well, there's nothing magic about it.  I just implement the TreeModel 
interface with my own class (TreeModel is pretty small and easy to 
implement).  The particular implementation depends on what I want to 
display in the tree.  I don't think I've ever actually displayed 
DynaBeans in a JTree, but there's nothing that would prevent that.  You 
would just have to know what the property that contained the list of 
children was.  Here is a working example TreeModel I just coded up. 

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import org.apache.commons.beanutils.DynaBean;

/**
 * A tree model that introspects a {@link DynaBean} property to discover a
 * node's children.
 *
 * @author Eric Galluzzo, egalluzzo@einnovation.com
 */
public class DynaBeanTreeModel implements TreeModel
{
    protected List fListeners;
    protected DynaBean fRoot;
    protected String fChildProperty;
   
    /**
     * Creates a new tree model with the given root, that will traverse 
children
     * that are given by the given property on the {@link DynaBean}.
     *
     * @param inRoot           The root of the tree
     * @param inChildProperty  The JavaBeans property that will 
determine the
     *                         children of each node
     */
    public DynaBeanTreeModel( DynaBean inRoot, String inChildProperty )
    {
        fRoot = inRoot;
        fChildProperty = inChildProperty;
    }
   
    /**
     * Returns the bean property that will determine the children of 
each node
     * in this model.
     *
     * @return  The child property
     */
    public String getChildProperty()
    {
        return fChildProperty;
    }
   
    /**
     * Sets the bean property that will determine the children of each 
node in
     * this model.
     *
     * @param inChildProperty  The new child property
     */
    public void setChildProperty( String inChildProperty )
    {
        if ( !inChildProperty.equals( fChildProperty ) )
        {
            fChildProperty = inChildProperty;
            fireTreeStructureChanged();
        }
    }
   
    /* (non-Javadoc)
     * @see javax.swing.tree.TreeModel#getRoot()
     */
    public Object getRoot()
    {
        return fRoot;
    }

    /* (non-Javadoc)
     * @see javax.swing.tree.TreeModel#getChild(java.lang.Object, int)
     */
    public Object getChild(Object parent, int index)
    {
        return getChildren( parent ).get( index );
    }

    /* (non-Javadoc)
     * @see javax.swing.tree.TreeModel#getChildCount(java.lang.Object)
     */
    public int getChildCount(Object parent)
    {
        return getChildren( parent ).size();
    }

    /* (non-Javadoc)
     * @see javax.swing.tree.TreeModel#isLeaf(java.lang.Object)
     */
    public boolean isLeaf(Object node)
    {
        return ( (DynaBean) node ).getDynaClass().getDynaProperty( 
getChildProperty() ) == null;
    }

    /* (non-Javadoc)
     * @see 
javax.swing.tree.TreeModel#valueForPathChanged(javax.swing.tree.TreePath, 
java.lang.Object)
     */
    public void valueForPathChanged(TreePath path, Object newValue)
    {
        // If you want to support mutable trees, you should do something 
here,
        // and fire off an event to the listeners.
    }

    /* (non-Javadoc)
     * @see javax.swing.tree.TreeModel#getIndexOfChild(java.lang.Object, 
java.lang.Object)
     */
    public int getIndexOfChild(Object parent, Object child)
    {
        return getChildren( parent ).indexOf( child );
    }

    /* (non-Javadoc)
     * @see 
javax.swing.tree.TreeModel#addTreeModelListener(javax.swing.event.TreeModelListener)
     */
    public void addTreeModelListener(TreeModelListener l)
    {
        getListeners().add( l );
    }

    /* (non-Javadoc)
     * @see 
javax.swing.tree.TreeModel#removeTreeModelListener(javax.swing.event.TreeModelListener)
     */
    public void removeTreeModelListener(TreeModelListener l)
    {
        getListeners().remove( l );
    }
   
    /**
     * Returns the collection given by the child property of the given bean.
     * This could be extended to handle arrays (via
     * {@link Arrays#asList(java.lang.Object[])).
     *
     * @param inObj  The object for which to retrieve children
     *
     * @return  The children, as a collection
     */
    protected List getChildren( Object inObj )
    {
        List children = (List) ( (DynaBean) inObj ).get( 
getChildProperty() );
        if ( children == null )
        {
            children = Collections.EMPTY_LIST;
        }
        return children;
    }
   
    /**
     * Returns the list of listeners to this bean.
     *
     * @return  The list of listeners
     */
    protected List getListeners()
    {
        if ( fListeners == null )
        {
            fListeners = new ArrayList( 3 );
        }
        return fListeners;
    }

    /**
     * Fire off a tree structure changed event to all the listeners.
     */
    protected void fireTreeStructureChanged()
    {
        TreeModelEvent event =
            new TreeModelEvent( this, new Object[] { getRoot() } );
        for ( Iterator iter = getListeners().iterator(); iter.hasNext(); )
        {
            TreeModelListener listener = (TreeModelListener) iter.next();
            listener.treeStructureChanged( event );
        }
    }
}

Doing things this way means that you can, at some point, hook up 
listeners to your business objects that fire off events in your 
TreeModel when your business object structure changes.  Then you don't 
have to do any kind of manual resynchronization between model and view 
(e.g. the dreaded "Refresh" button).  Test cases are left as an exercise 
for the reader. :)

For example usage, consider the case where one has a "group" DynaClass.  
The "group" DynaClass has a "subgroups" property that holds a List of 
child group DynaBeans.  Then, one could do this:

TreeModel model = new DynaBeanTreeModel( rootGroup, "subgroups" );
JTree tree = new JTree( model );
...

This would show a tree whose root is rootGroup, and whose parent-child 
relationship is governed by the "subgroups" property.  OK, this is a 
poor example, but my imagination is at low tide at the moment. :)

> BTW: Thanx a lot for help.

Sure, no problem!

    - Eric



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Mime
View raw message