/* * Created on 20.06.2005 * */ package org.jdesktop.swingx.test; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import javax.swing.tree.TreePath; import org.jdesktop.swingx.JXFrame; import org.jdesktop.swingx.treetable.AbstractTreeTableModel; /** * A static snapshot of a container hierarchy. * * NOTE: does not listen to any property changes of * contained components - cell updates are arbitrary on * repaint only! * * @author Jeanette Winzenburg */ public class ComponentTreeTableModel extends AbstractTreeTableModel { public ComponentTreeTableModel(Container root) { super(root); setRoot(root); } public void setRoot(Container root) { if (root == null) { root = new JXFrame(); } this.root = root; modelSupport.fireNewRoot(); } // ------------------TreeModel @Override public Container getRoot() { // TODO Auto-generated method stub return (Container) super.getRoot(); } public Object getChild(Object parent, int index) { return ((Container) parent).getComponent(index); } public int getChildCount(Object parent) { return parent instanceof Container ? ((Container) parent).getComponentCount() : 0; } public int getIndexOfChild(Object parent, Object child) { Component[] children = ((Container) parent).getComponents(); for (int i = 0; i < children.length; i++) { if (children[i].equals(child)) { return i; } } return -1; } @Override public boolean isLeaf(Object node) { return getChildCount(node) == 0; } /** * This method is called by the "tree" part to render the hierarchical * column. <p> * * PENDING: currently need to comment to let the treetable show the * correct value. Need to dig why ... * * @param node * the node to convert * @return the {@code node} as a string */ // public String convertValueToText(Object node) { // return String.valueOf(getValueAt(node, getHierarchicalColumn())); // } @Override public void valueForPathChanged(TreePath path, Object newValue) { Object node = path.getLastPathComponent(); setValueAt(newValue, node, getHierarchicalColumn()); } //------------------ TreeTableModel @Override public Class<?> getColumnClass(int column) { switch (column) { case 0: return Object.class; case 1: return Class.class; case 2: return Dimension.class; case 3: return Integer.class; default: return Object.class; } } public int getColumnCount() { return 4; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Name"; case 1: return "Type"; case 2: return "Size"; case 3: return "Width"; default: return "Column " + column; } } public Object getValueAt(Object node, int column) { Component comp = (Component) node; switch (column) { case 0: return comp.getName(); case 1: return comp.getClass(); case 2: return comp.getSize(); case 3: return comp.getWidth(); default: return null; } } @Override public boolean isCellEditable(Object node, int column) { // fake accessing the node: TreeModel can expect to // be messaged with nodes that belong to the // hierarchical structure // introduced for testing #270-swingx: // NPE for invisible rows (if parent is collapsed. ((Component) node).getName(); return column == 0 || column == 3; } @Override public void setValueAt(Object value, Object node, int column) { if (!isCellEditable(node, column)) return; Component comp = (Component) node; if (column == 0) { comp.setName(String.valueOf(value)); } else if (column == 3) { comp.setSize(new Integer((Integer) value), comp.getHeight()); } nodeChanged(comp); } private void nodeChanged(Component comp) { TreePath path = getPathToRoot(comp); modelSupport.firePathChanged(path); } /** * exposed for test convenience. * * @param node * @return a {@code TreePath} representation from {@code root} to * {@code node} */ public TreePath getPathToRoot(Component node) { return new TreePath(getPathToRoot(node, 0)); } private Component[] getPathToRoot(Component node, int depth) { Component[] retNodes; // This method recurses, traversing towards the root in order // size the array. On the way back, it fills in the nodes, // starting from the root and working back to the original node. /* Check for null, in case someone passed in a null node, or they passed in an element that isn't rooted at root. */ if(node == null) { if(depth == 0) return null; else retNodes = new Component[depth]; } else { depth++; if(node == root) retNodes = new Component[depth]; else retNodes = getPathToRoot(node.getParent(), depth); retNodes[retNodes.length - depth] = node; } return retNodes; } }