001: package com.xoetrope.swing.treetable;
002:
003: import javax.swing.JTree;
004: import javax.swing.SwingUtilities;
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: * A tree node wrapper for an XModel node
014: *
015: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
016: * the GNU Public License (GPL), please see license.txt for more details. If
017: * you make commercial use of this software you must purchase a commercial
018: * license from Xoetrope.</p>
019: * <p> $Revision: 1.4 $</p>
020: */
021: public class TreeTableModelAdapter extends AbstractTableModel {
022: JTree tree;
023: TreeTableModel treeTableModel;
024:
025: public TreeTableModelAdapter(TreeTableModel treeTableModel,
026: JTree tree) {
027: this .tree = tree;
028: this .treeTableModel = treeTableModel;
029:
030: tree.addTreeExpansionListener(new TreeExpansionListener() {
031: // Don't use fireTableRowsInserted() here; the selection model
032: // would get updated twice.
033: public void treeExpanded(TreeExpansionEvent event) {
034: fireTableDataChanged();
035: }
036:
037: public void treeCollapsed(TreeExpansionEvent event) {
038: fireTableDataChanged();
039: }
040: });
041:
042: // Install a TreeModelListener that can update the table when
043: // tree changes. We use delayedFireTableDataChanged as we can
044: // not be guaranteed the tree will have finished processing
045: // the event before us.
046: treeTableModel.addTreeModelListener(new TreeModelListener() {
047: public void treeNodesChanged(TreeModelEvent e) {
048: delayedFireTableDataChanged();
049: }
050:
051: public void treeNodesInserted(TreeModelEvent e) {
052: delayedFireTableDataChanged();
053: }
054:
055: public void treeNodesRemoved(TreeModelEvent e) {
056: delayedFireTableDataChanged();
057: }
058:
059: public void treeStructureChanged(TreeModelEvent e) {
060: delayedFireTableDataChanged();
061: }
062: });
063: }
064:
065: // Wrappers, implementing TableModel interface.
066:
067: public int getColumnCount() {
068: return treeTableModel.getColumnCount();
069: }
070:
071: public String getColumnName(int column) {
072: return treeTableModel.getColumnName(column);
073: }
074:
075: public Class getColumnClass(int column) {
076: return treeTableModel.getColumnClass(column);
077: }
078:
079: public boolean isCellEditable(int row, int column) {
080: return treeTableModel.isCellEditable(nodeForRow(row), column);
081: }
082:
083: public int getRowCount() {
084: return tree.getRowCount();
085: }
086:
087: protected Object nodeForRow(int row) {
088: TreePath treePath = tree.getPathForRow(row);
089: return treePath.getLastPathComponent();
090: }
091:
092: public Object getValueAt(int row, int column) {
093: try {
094: return treeTableModel.getValueAt(nodeForRow(row), column);
095: } catch (Exception e) {
096: if (column > 0)
097: return "";
098: }
099: return null;
100: }
101:
102: public void setValueAt(Object value, int row, int column) {
103: treeTableModel.setValueAt(value, nodeForRow(row), column);
104: }
105:
106: /**
107: * Invokes fireTableDataChanged after all the pending events have been
108: * processed. SwingUtilities.invokeLater is used to handle this.
109: */
110: protected void delayedFireTableDataChanged() {
111: SwingUtilities.invokeLater(new Runnable() {
112: public void run() {
113: fireTableDataChanged();
114: }
115: });
116: }
117: }
|