001 package ui.model;
002
003 import javax.swing.JTree;
004 import java.awt.EventQueue;
005 import javax.swing.table.AbstractTableModel;
006 import javax.swing.tree.TreePath;
007 import javax.swing.event.TreeExpansionEvent;
008 import javax.swing.event.TreeExpansionListener;
009 import javax.swing.event.TreeModelEvent;
010 import javax.swing.event.TreeModelListener;
011
012 /**
013 * This is a wrapper class takes a TreeTableModel and implements
014 * the table model interface. The implementation is trivial, with
015 * all of the event dispatching support provided by the superclass:
016 * the AbstractTableModel.
017 *
018 * @version 1.2 10/27/98
019 *
020 * @author Philip Milne
021 * @author Scott Violet
022 */
023 public class TreeTableModelAdapter extends AbstractTableModel
024 {
025 JTree tree;
026 TreeTableModel treeTableModel;
027
028 public TreeTableModelAdapter(TreeTableModel treeTableModel, JTree tree) {
029 this.tree = tree;
030 this.treeTableModel = treeTableModel;
031
032 tree.addTreeExpansionListener(new TreeExpansionListener() {
033 // Don't use fireTableRowsInserted() here; the selection model
034 // would get updated twice.
035 public void treeExpanded(TreeExpansionEvent event) {
036 fireTableDataChanged();
037 }
038 public void treeCollapsed(TreeExpansionEvent event) {
039 fireTableDataChanged();
040 }
041 });
042
043 // Install a TreeModelListener that can update the table when
044 // tree changes. We use delayedFireTableDataChanged as we can
045 // not be guaranteed the tree will have finished processing
046 // the event before us.
047 treeTableModel.addTreeModelListener(new TreeModelListener() {
048 public void treeNodesChanged(TreeModelEvent e) {
049 delayedFireTableDataChanged();
050 }
051
052 public void treeNodesInserted(TreeModelEvent e) {
053 delayedFireTableDataChanged();
054 }
055
056 public void treeNodesRemoved(TreeModelEvent e) {
057 delayedFireTableDataChanged();
058 }
059
060 public void treeStructureChanged(TreeModelEvent e) {
061 delayedFireTableDataChanged();
062 }
063 });
064 }
065
066 // Wrappers, implementing TableModel interface.
067
068 public int getColumnCount() {
069 return treeTableModel.getColumnCount();
070 }
071
072 public String getColumnName(int column) {
073 return treeTableModel.getColumnName(column);
074 }
075
076 public Class getColumnClass(int column) {
077 return treeTableModel.getColumnClass(column);
078 }
079
080 public int getRowCount() {
081 return tree.getRowCount();
082 }
083
084 public Object getValueAt(int row, int column) {
085 return treeTableModel.getValueAt(nodeForRow(row), column);
086 }
087
088 public boolean isCellEditable(int row, int column) {
089 return treeTableModel.isCellEditable(nodeForRow(row), column);
090 }
091
092 public void setValueAt(Object value, int row, int column) {
093 treeTableModel.setValueAt(value, nodeForRow(row), column);
094 }
095
096
097 // row to node mapping used only in the last three methods
098 protected Object nodeForRow(int row) {
099 TreePath treePath = tree.getPathForRow(row);
100 return treePath.getLastPathComponent();
101 }
102
103 /**
104 * Invokes fireTableDataChanged after all the pending events have been processed.
105 * The static method : java.awt.EventQueue.invokeLater()
106 * is used to handle this.
107 */
108 protected void delayedFireTableDataChanged() {
109 EventQueue.invokeLater(new Runnable() {
110 public void run() {
111 fireTableDataChanged();
112 }
113 });
114 }
115 }
116