001: package org.wingx.treetable;
002:
003: import java.util.*;
004:
005: import javax.swing.table.DefaultTableModel;
006: import javax.swing.tree.TreeModel;
007:
008: import org.apache.commons.logging.*;
009: import org.wingx.tree.LazyNode;
010:
011: /**
012: * the table model for an OTableTree
013: *
014: */
015: public class XTreeTableModel extends DefaultTableModel {
016:
017: private static final long serialVersionUID = 4071940504892898468L;
018:
019: private final static Log logger = LogFactory
020: .getLog(XTreeTableModel.class);
021:
022: private final TreeModel treeModel;
023:
024: private final List nodeModel = new ArrayList();
025:
026: /**
027: * construct a table model
028: */
029: public XTreeTableModel(TreeModel treeModel) {
030: super ();
031: this .treeModel = treeModel;
032: expandNode(getRoot(), -1);
033: }
034:
035: /**
036: * @inheritDoc
037: */
038: public boolean isCellEditable(int row, int column) {
039: return (column > 0);
040: }
041:
042: /**
043: * toggle the expanded state for the node at the given row
044: */
045: public void toggleExpanded(int row) {
046: if (row < 0 || row >= getNodeModel().size()) {
047: logger.warn("bad row: " + row + " size is "
048: + getNodeModel().size());
049: return;
050: }
051: XTreeTableNode node = (XTreeTableNode) getNodeModel().get(row);
052: logger.info("toggle expanded row=" + row + " expanded="
053: + node.isExpanded() + " model-size="
054: + getNodeModel().size());
055: if (!node.isExpanded()) {
056: int insertPos = expandNode(node, row);
057: fireTableRowsInserted(row + 1, row + insertPos);
058: } else {
059: int delcount = collapseNode(node, row);
060: fireTableRowsDeleted(row + 1, row + delcount);
061: }
062: }
063:
064: /**
065: * expand the given node.
066: * if child nodes already have their expanded flag set to true,
067: * then expand them as well
068: *
069: * @return the insert position
070: */
071: private int expandNode(XTreeTableNode node, int row) {
072: if (node instanceof LazyNode)
073: ((LazyNode) node).initialize();
074:
075: int count = node.getChildCount();
076: int insertPosition = row;
077: for (int i = 0; i < count; i++) {
078: XTreeTableNode child = (XTreeTableNode) node.getChildAt(i);
079: insertPosition++;
080: getNodeModel().add(insertPosition, child);
081: if (child.isExpanded()) {
082: insertPosition = expandNode(child, insertPosition);
083: }
084: }
085: node.setExpanded(true);
086: return insertPosition;
087: }
088:
089: /**
090: * collapse the given node,
091: * remove all descendants which follow the node
092: */
093: private int collapseNode(XTreeTableNode node, int row) {
094: int delcount = 0;
095: while (row + 1 < getNodeModel().size()) {
096: XTreeTableNode candidate = (XTreeTableNode) getNodeModel()
097: .get(row + 1);
098: /*
099: * remove the candidate if the depth is greater than the depth
100: * of the parent to be collapsed
101: */
102: if (candidate.getDepth() > node.getDepth()) {
103: getNodeModel().remove(row + 1);
104: delcount++;
105: } else {
106: break;
107: }
108: }
109: node.setExpanded(false);
110: return delcount;
111: }
112:
113: /**
114: * @inheritDoc
115: */
116: public int getRowCount() {
117: return (getNodeModel() != null) ? getNodeModel().size() : 0;
118: }
119:
120: /**
121: * @param row
122: * @return the value of the first column
123: */
124: public String getFirstColumnValue(int row) {
125: return getNodeModel().get(row).toString();
126: }
127:
128: /**
129: * @inheritDoc
130: */
131: public final Object getValueAt(int row, int column) {
132: if (row >= 0 && row < getNodeModel().size()) {
133: if (column == 0) {
134: return getFirstColumnValue(row);
135: }
136: return ((XTreeTableNode) (getNodeModel().get(row)))
137: .getValueAt(column);
138: }
139: return null;
140: }
141:
142: /**
143: * @inheritDoc
144: */
145: public final void setValueAt(Object aValue, int row, int column) {
146: if (row >= 0 && row < getNodeModel().size()) {
147: ((XTreeTableNode) getNodeModel().get(row)).setValueAt(
148: aValue, column);
149: }
150: fireTableCellUpdated(row, column);
151: }
152:
153: /**
154: * @return Returns the treeModel.
155: */
156: public TreeModel getTreeModel() {
157: return this .treeModel;
158: }
159:
160: /**
161: * @return Returns the parentNode.
162: */
163: public XTreeTableNode getRoot() {
164: return (XTreeTableNode) getTreeModel().getRoot();
165: }
166:
167: /**
168: * @return Returns the nodeModel.
169: */
170: public List getNodeModel() {
171: return this.nodeModel;
172: }
173: }
|