/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.explorer.view; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.tree.TreePath; import javax.swing.event.*; import org.openide.nodes.*; /* NodeTableModel synchronizing tree and table model. Used by TreeTable. * * @author Jan Rojcek */ class TreeTableModelAdapter extends NodeTableModel { private JTree tree; private NodeTableModel nodeTableModel; public TreeTableModelAdapter(JTree t, NodeTableModel ntm) { this.tree = t; this.nodeTableModel = ntm; Listener listener = new Listener(); tree.addTreeExpansionListener(listener); tree.getModel().addTreeModelListener(listener); nodeTableModel.addTableModelListener(listener); } // NodeTableModel methods public void setNodes(Node[] nodes) { nodeTableModel.setNodes(nodes); } public void setProperties(Node.Property[] props) { nodeTableModel.setProperties(props); } protected Node.Property getPropertyFor(Node node, Node.Property prop) { return nodeTableModel.getPropertyFor(node, prop); } Node nodeForRow(int row) { return Visualizer.findNode(tree.getPathForRow(row).getLastPathComponent()); } Node.Property propertyForColumn(int column) { return nodeTableModel.propertyForColumn(column - 1); } // Wrappers, implementing TableModel interface. public int getColumnCount() { return nodeTableModel.getColumnCount() + 1; } public String getColumnName(int column) { return column == 0 ? Visualizer.findNode(tree.getModel().getRoot()).getDisplayName() : nodeTableModel.getColumnName(column - 1); } public Class getColumnClass(int column) { return column == 0 ? TreeTableModelAdapter.class : nodeTableModel.getColumnClass(column - 1); } public int getRowCount() { return tree.getRowCount(); } public Object getValueAt(int row, int column) { return column == 0 ? tree.getPathForRow(row).getLastPathComponent() : nodeTableModel.getPropertyFor( nodeForRow(row), propertyForColumn(column)); } public boolean isCellEditable(int row, int column) { return column == 0 ? true : getValueAt(row, column) != null; } public void setValueAt(Object value, int row, int column) { } /* Listener for synchronizing tree and table model. */ class Listener implements TreeExpansionListener, TreeModelListener, TableModelListener, Runnable { // selection paths stored for restore after update TreePath[] tps = null; ///////// TreeExpansionListener public void treeExpanded(TreeExpansionEvent event) { updateNodes(); } public void treeCollapsed(TreeExpansionEvent event) { updateNodes(); } ///////////// TreeModelListener // Install a TreeModelListener that can update the table when // tree changes. We use delayedUpdateNodes as we can // not be guaranteed the tree will have finished processing // the event before us. public void treeNodesChanged(TreeModelEvent e) { delayedUpdateNodes(e); } public void treeNodesInserted(TreeModelEvent e) { delayedUpdateNodes(e); } public void treeNodesRemoved(TreeModelEvent e) { delayedUpdateNodes(e); } public void treeStructureChanged(TreeModelEvent e) { // bugfix #23757, store selection paths tps = tree.getSelectionPaths (); // bugfix #30355, don't restore selection when the tree root changed // (see javadoc TreeModelListener.treeStructureChanged) if (e.getPath ().length == 1 && !e.getTreePath ().equals (e.getPath ()[0])) { tps = null; } delayedUpdateNodes(e); } ///////// TableModelListener public void tableChanged(TableModelEvent e) { int c = e.getColumn(); int column = c == TableModelEvent.ALL_COLUMNS ? TableModelEvent.ALL_COLUMNS : c + 1; fireTableChanged(new TableModelEvent(TreeTableModelAdapter.this, e.getFirstRow(), e.getLastRow(), column, e.getType())); } /** * Invokes fireTableDataChanged after all the pending events have been processed. */ protected void delayedUpdateNodes(TreeModelEvent e) { // Something like this can be used for updating tree column name ?! //if (tree.getModel().getRoot().equals(e.getTreePath().getLastPathComponent())) { // fireTableStructureChanged(); //} SwingUtilities.invokeLater(this); } public void run() { updateNodes(); } private void updateNodes() { Node[] nodes = new Node[tree.getRowCount()]; for (int i = 0; i < tree.getRowCount(); i++) { nodes[i] = Visualizer.findNode(tree.getPathForRow(i).getLastPathComponent()); } setNodes(nodes); // retore selection paths if (tps != null) { tree.setSelectionPaths (tps); tps = null; } } } }