All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.odell.glazedlists.swing.EventTreeModel Maven / Gradle / Ivy

There is a newer version: 1.9.1
Show newest version
/* Glazed Lists                                                 (c) 2003-2006 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.swing;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.TransformedList;
import ca.odell.glazedlists.TreeList;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;

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

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

/**
 * Adapt a {@link TreeList} for use in a {@link JTree}.
 *
 * 

Ongoing problem: TreeList cannot cache all tree data on * the swing thread proxy due to the extra data in a tree. * *

Developer Preview this class is still under heavy development * and subject to API changes. It's also really slow at the moment and won't scale * to lists of size larger than a hundred or so efficiently. * * @author jessewilson */ public class EventTreeModel implements TreeModel, ListEventListener { /** the proxy moves events to the Swing Event Dispatch thread */ protected TransformedList swingThreadSource; /** true indicates that disposing this TreeModel should dispose of the swingThreadSource as well */ private final boolean disposeSwingThreadSource; private TreeList treeList; /** swing trees all have only a single root */ private final Object treeRoot = new Object(); /** Listeners. */ protected List listenerList = new ArrayList(); /** * Creates a new tree model that extracts the tree data from the given * source. * * @param source a {@link TreeList} that provides the tree data */ public EventTreeModel(TreeList source) { // lock the source list for reading since we want to prevent writes // from occurring until we fully initialize this EventTableModel source.getReadWriteLock().readLock().lock(); try { disposeSwingThreadSource = !GlazedListsSwing.isSwingThreadProxyList(source); swingThreadSource = disposeSwingThreadSource ? GlazedListsSwing.swingThreadProxyList(source) : (TransformedList) source; // prepare listeners swingThreadSource.addListEventListener(this); } finally { source.getReadWriteLock().readLock().unlock(); } this.treeList = source; } /** {@inheritDoc} */ public Object getRoot() { return treeRoot; } /** {@inheritDoc} */ public Object getChild(Object parent, int index) { if(parent == treeRoot) { return treeList.getRoots().get(index); } else { TreeList.Node node = (TreeList.Node)parent; return node.getChildren().get(index); } } /** {@inheritDoc} */ public int getChildCount(Object parent) { if(parent == treeRoot) { return treeList.getRoots().size(); } else { TreeList.Node node = (TreeList.Node)parent; return node.getChildren().size(); } } /** {@inheritDoc} */ public boolean isLeaf(Object node) { if(node == treeRoot) { return treeList.isEmpty(); } else { TreeList.Node treeNode = (TreeList.Node)node; return treeNode.isLeaf(); } } /** {@inheritDoc} */ public void valueForPathChanged(TreePath path, Object newValue) { // todo } /** {@inheritDoc} */ public int getIndexOfChild(Object parent, Object child) { if(parent == treeRoot) { return treeList.getRoots().indexOf(child); } else { TreeList.Node treeNode = (TreeList.Node)parent; return treeNode.getChildren().indexOf(child); } } /** {@inheritDoc} */ public void addTreeModelListener(TreeModelListener listener) { listenerList.add(listener); } /** {@inheritDoc} */ public void removeTreeModelListener(TreeModelListener listener) { listenerList.remove(listener); } /** {@inheritDoc} */ public void listChanged(ListEvent listChanges) { // todo: fire a more general event for(Iterator i = listenerList.iterator(); i.hasNext(); ) { TreeModelListener listener = i.next(); listener.treeStructureChanged(new TreeModelEvent(this, new Object[] { treeRoot })); } } /** * Releases the resources consumed by this {@link EventTreeModel} so that it * may eventually be garbage collected. * *

An {@link EventTreeModel} will be garbage collected without a call to * {@link #dispose()}, but not before its source {@link EventList} is garbage * collected. By calling {@link #dispose()}, you allow the {@link EventTreeModel} * to be garbage collected before its source {@link EventList}. This is * necessary for situations where an {@link EventTreeModel} is short-lived but * its source {@link EventList} is long-lived. * *

Warning: It is an error * to call any method on an {@link EventTreeModel} after it has been disposed. */ public void dispose() { swingThreadSource.removeListEventListener(this); // if we created the swingThreadSource then we must also dispose it if(disposeSwingThreadSource) { swingThreadSource.dispose(); } // this encourages exceptions to be thrown if this model is incorrectly accessed again swingThreadSource = null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy