001/*
002  The Broad Institute
003  SOFTWARE COPYRIGHT NOTICE AGREEMENT
004  This software and its documentation are copyright (2003-2008) by the
005  Broad Institute/Massachusetts Institute of Technology. All rights are
006  reserved.
007
008  This software is supplied without any warranty or guaranteed support
009  whatsoever. Neither the Broad Institute nor MIT can be responsible for its
010  use, misuse, or functionality.
011*/
012
013package ca.bc.webarts.widgets.treetable;
014// package org.genomespace.gsui.ui.treetable;
015
016/*
017    @(#)TreeTableModelAdapter.java      1.2 98/10/27
018    Copyright 1997, 1998 by Sun Microsystems, Inc.,
019    901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
020    All rights reserved.
021    This software is the confidential and proprietary information
022    of Sun Microsystems, Inc. ("Confidential Information").  You
023    shall not disclose such Confidential Information and shall use
024    it only in accordance with the terms of the license agreement
025    you entered into with Sun.
026*/
027import javax.swing.JTree;
028import javax.swing.SwingUtilities;
029import javax.swing.event.TreeExpansionEvent;
030import javax.swing.event.TreeExpansionListener;
031import javax.swing.event.TreeModelEvent;
032import javax.swing.event.TreeModelListener;
033import javax.swing.table.AbstractTableModel;
034import javax.swing.tree.TreePath;
035import org.jdesktop.swingx.*;
036import org.jdesktop.swingx.treetable.*;
037
038/**
039 *  This is a wrapper class takes a TreeTableModel and implements the table
040 *  model interface. The implementation is trivial, with all of the event
041 *  dispatching support provided by the superclass: the AbstractTableModel.
042 *
043 * @author     Philip Milne
044 * @author     Scott Violet
045 * @version    1.2 10/27/98
046 */
047public class TreeTableModelAdapter extends AbstractTableModel
048{
049  JTree tree;
050  TreeTableModel treeTableModel;
051
052  public TreeTableModelAdapter( TreeTableModel treeTableModel, JTree tree )
053  {
054    this.tree = tree;
055    this.treeTableModel = treeTableModel;
056
057    tree.addTreeExpansionListener ( new TreeExpansionListener()
058    {
059      // Don't use fireTableRowsInserted() here; the selection model
060      // would get updated twice.
061      public void treeExpanded( TreeExpansionEvent event )
062      {
063        fireTableDataChanged();
064      }
065
066      public void treeCollapsed( TreeExpansionEvent event )
067      {
068        fireTableDataChanged();
069      }
070    } );
071
072    // Install a TreeModelListener that can update the table when
073    // tree changes. We use delayedFireTableDataChanged as we can
074    // not be guaranteed the tree will have finished processing
075    // the event before us.
076    treeTableModel.addTreeModelListener ( new TreeModelListener()
077    {
078      public void treeNodesChanged( TreeModelEvent e )
079      {
080        delayedFireTableDataChanged();
081      }
082
083      public void treeNodesInserted( TreeModelEvent e )
084      {
085        delayedFireTableDataChanged();
086      }
087
088      public void treeNodesRemoved( TreeModelEvent e )
089      {
090        delayedFireTableDataChanged();
091      }
092
093      public void treeStructureChanged( TreeModelEvent e )
094      {
095        delayedFireTableDataChanged();
096      }
097    } );
098  }
099
100
101  protected Object nodeForRow( int row )
102  {
103    TreePath treePath = tree.getPathForRow( row );
104    return treePath.getLastPathComponent();
105  }
106
107
108  /**
109   *  Invokes fireTableDataChanged after all the pending events have been
110   *  processed. SwingUtilities.invokeLater is used to handle this.
111   */
112  protected void delayedFireTableDataChanged()
113  {
114    SwingUtilities.invokeLater ( new Runnable()
115    {
116      public void run()
117      {
118        TreePath selectionPath = tree.getSelectionPath();
119        fireTableDataChanged();
120        tree.updateUI();
121        if ( selectionPath != null )
122        {
123          tree.setSelectionPath( selectionPath );
124        }
125      }
126    } );
127  }
128
129
130  public void setValueAt( Object value, int row, int column )
131  {
132    treeTableModel.setValueAt( value, nodeForRow( row ), column );
133  }
134
135
136  // Wrappers, implementing TableModel interface.
137
138  public int getColumnCount()
139  {
140    return treeTableModel.getColumnCount();
141  }
142
143
144  public String getColumnName( int column )
145  {
146    return treeTableModel.getColumnName( column );
147  }
148
149
150  public Class getColumnClass( int column )
151  {
152    return treeTableModel.getColumnClass( column );
153  }
154
155
156  public int getRowCount()
157  {
158    return tree.getRowCount();
159  }
160
161
162  public Object getValueAt( int row, int column )
163  {
164    return treeTableModel.getValueAt( nodeForRow( row ), column );
165  }
166
167
168  public boolean isCellEditable( int row, int column )
169  {
170    return treeTableModel.isCellEditable( nodeForRow( row ), column );
171  }
172}
173
174