package cern.gp.explorer; import java.awt.BorderLayout; import java.beans.IntrospectionException; import javax.swing.JTable; import javax.swing.JTree; import org.openide.explorer.view.NodeTableModel; import org.openide.explorer.view.TreeTableView; import org.openide.explorer.view.TreeView; import org.openide.nodes.Node; import cern.gp.nodes.GPNode; import cern.gp.nodes.impl.NodeUtils; /** * A GUI component that combines a List with a Table, with the List on the left side and the Table on the right. * Each node of the list corresponds to a row in the table. It can be used to explore JavaBeans in the * Tree and show ther properties in the Table. * This class shall simplify the task of creating and parametrizing this type of explorer. * As the other Explorers provided by the GP project, it is strongly based on JavaBeans: * The nodes in the List contain JavaBeans-compliant objects ("domain beans"), and the rows in the Table display * the properties of these domain beans.<p> * The implementation enables the developer to create a Explorer that s/he can easily place into * a NetBeans Mode. It has methods to easily configure the colums of the Table. * It is recommended that the developer uses the NodeFactory to create the Node hierarchy to be explored. * * @version $Revision: 1.2 $ $Date: 2006/09/25 08:52:36 $ * @author Vito Baggiolini */ public class ListTableExplorer extends GPListExplorerPanel implements TableHolder, TablePropertyHolder { private static final String ATTR_COMPARABLE_COLUMN = "ComparableColumnTTV"; // NOI18N private static final String ATTR_SORTING_COLUMN = "SortingColumnTTV"; // NOI18N private static final String ATTR_DESCENDING_ORDER = "DescendingOrderTTV"; // NOI18N private final TableHolder tableHolder; private GPNode beanNode; private String[] tableColumnNames; private final TreeTableViewTableAccess treeTableViewTableAccess; /** * create a ListTableExplorer with the default view and model. */ public ListTableExplorer() { this(new GPTreeTableView()); } /** * create a ListTableExplorer and set the nodes to display * @param nodes the nodes to display */ public ListTableExplorer(GPNode[] nodes) { this(); this.setListNodes(nodes); } protected ListTableExplorer(TreeTableViewTableAccess view) { super(); this.treeTableViewTableAccess = view; setLayout(new BorderLayout()); add(view.getTreeTableView(), BorderLayout.CENTER); tableHolder = new TableHolderImpl(this); } /** * create a TreeTableExplorer and specify the class of the bean from which the Table rows * shall be inferred. This constructor works if you want to display the properties of only * one Bean in the Table. Otherwise use another constructor. * * @param viewableBeanClass the bean class whose properties shall be displayed in the Table * @deprecated this method is only used for a real SortableTreeTableExplorer */ public ListTableExplorer(Class viewableBeanClass) { this(new Class[] { viewableBeanClass }); } /** * create a TreeTableExplorer and specify which beans shall be visible in the Table part of the * TreeTable. Only Bean classes that equal or inherit from one of the classes passed to this constructor * will have their properties displayed in the Table. The others table cells will be empty. * * @param viewableBeanClass the bean classes whose properties shall be displayed in the Table * @deprecated this method is only used for a real SortableTreeTableExplorer */ public ListTableExplorer(Class[] viewableBeanClasses) { this(new GPTreeTableView(new TableHolderImpl.SelectiveTableModel(viewableBeanClasses))); } /** * Getter Method * @return the TreeTableView of this TreeTableExplorer */ public TreeTableViewTableAccess getTreeTableAccess() { return treeTableViewTableAccess; } /** * set the nodes to be displayed in the table. * @param nodes an array of nodes each associated with a Bean. */ public final void setListNodes(final GPNode[] nodes) { // this method is final because it is called from the constructor. // You can override and un-final it, but you have to make sure that your overridden method // is ready when it is called from the constructor of this class! // Beware: Calling an instance method in a derived class from the constructor of the // super class is dangerous, e.g. because the method might use unitialized variables in // the (not yet initialized) derived class. if (nodes.length <=0) { return; } beanNode = nodes[0]; // if any of the nodes has children of their own which would be displayed in the tree, // we create an array of new GPNodes // TODO this should be based on FilterNode, // TODO and then it should be merged with the ListExplorer.setListNodes boolean copyNodes = !areAllNodesLeaves(nodes); try { GPNode[] nodesToSet = copyNodes ? NodeUtils.copyToNewGPNodeArray(nodes) : nodes; Object rootBean = new NamedBean(""); setRootBean(rootBean); this.setRootNode(createRootNode(rootBean, nodesToSet)); } catch(IntrospectionException ex) { ex.printStackTrace(); return; } try { setTableColumns(beanNode); } catch (IntrospectionException ex) { ex.printStackTrace(); return; } } /** * set the parent node of the list of nodes to be explored. The parent node is not * displayed, only its children nodes. * Use this method * <ul> * <li>if you already have a root node whose children you want to display</li> * <li>if you want to control the nodes with your own ChildrenManager as shown below</li> * </ul> * Otherwise, you should use {@link #setListNodes(GPNode[])} * * @param parentNode the parent of the nodes to be displayed in the List */ public void setRootNode(GPNode node){ super.setRootNode(node); // refactored into superclass: getExplorerManager().setRootContext(node.getPeerNode()); getTreeTableAccess().getTreeTableView().setRootVisible(false); this.setTableColumns(node, null); //??? } /** * set the preferred size of the TableExplorer */ public void setPreferredSize(java.awt.Dimension dim) { getTreeTableAccess().getTreeTableView().setPreferredSize(dim); } /** * set the preferred width of the whole TableExplorer */ public void setTreePreferredWidth(int width) { getTreeTableAccess().getTreeTableView().setTreePreferredWidth(width); } /** * set the preferred width of the specified column */ public void setTableColumnPreferredWidth(int index, int width) { getTreeTableAccess().getTreeTableView().setTableColumnPreferredWidth(index, width); } /** * set the columns to be displayed. Note that before this method is called * you must have called {@link #setListNodes(GPNode[])} */ public void setTableColumns(String[] propNames) throws IntrospectionException { if (beanNode == null) { throw new IntrospectionException("explored beans not yet known, use setTableNodes() first!"); } tableHolder.setTableColumns(beanNode, propNames); tableColumnNames = propNames; } /** * Accessor method, the counterpart to {@link #setTableColumns(String[])} * * @return the names of the currently accessed table colums */ public String[] getTableColumnNames() { // TODO this should be implemented in a method TableHolderImpl.getTableColumns return tableColumnNames; } // //---- implements TableHolder ---------------------------------------------- // // public void setTableColumns(GPNode node, String[] propNames) { tableHolder.setTableColumns(node, propNames); } public void setTableColumns(Object bean) throws IntrospectionException { tableHolder.setTableColumns(bean); } public void setTableColumns(Object bean, String[] propNames) throws IntrospectionException { tableHolder.setTableColumns(bean, propNames); } /* (non-Javadoc) * @see cern.gp.explorer.TableHolder#setTableColumns(java.lang.Class[], java.lang.String[]) */ public void setTableColumns(Class[] propTypes, String[] propNames) { tableHolder.setTableColumns(propTypes, propNames); } /** * @since 2.0.6 */ public void setTableColumns(Class[] propTypes, String[] propNames, boolean[] sortable) { tableHolder.setTableColumns(propTypes, propNames, sortable); } /** * @since 2.0.6 */ public void setTableColumns(GPNode node, String[] propNames, boolean[] sortable) { tableHolder.setTableColumns(node, propNames, sortable); } /** * @since 2.0.6 */ public void setTableColumns(Object bean, String[] propNames, boolean[] sortable) throws IntrospectionException { tableHolder.setTableColumns(bean, propNames, sortable); } /** @deprecated use setTableColumns(Object) or setTableColumns(GPBean, String[]) instead */ public void setTableColumns(Class beanClass) throws IntrospectionException { tableHolder.setTableColumns(beanClass); } /** @deprecated use setTableColumns(Object, String[]) or setTableColumns(GPBean, String[]) instead */ public void setTableColumns(Class beanClass, String[] propNames) throws IntrospectionException { tableHolder.setTableColumns(beanClass, propNames); } // //---- implements TablePropertyHolder -------------------------------------- // // public void setProperties(Node.Property[] props, boolean[] sortable) { if (sortable != null) { for (int ix = 0; ix < props.length; ix++) { if (sortable[ix]) { props[ix].setValue(ATTR_COMPARABLE_COLUMN, Boolean.TRUE); } } } else { for (int ix = 0; ix < props.length; ix++) { props[ix].setValue(ATTR_COMPARABLE_COLUMN, Boolean.TRUE); } } if (isVisible()) { setVisible(false); treeTableViewTableAccess.getTreeTableView().setProperties(props); setVisible(true); } else { treeTableViewTableAccess.getTreeTableView().setProperties(props); } } /** * helper method, finds out if all nodes are Leaves or if any of the * nodes has children * @param nodes an array of nodes * @return true if all are leaves, false if at least one node has children */ private boolean areAllNodesLeaves(GPNode[] nodes) { for (int ix=0; ix<nodes.length; ix++) { if (nodes[ix].getNodeCollection() != null) return false; } return true; } // // -- INNER CLASS ---------------------------------------------- // /** * This class is a regular table view that gives access to the underlying table and tree from Swing. * * @version $Id: ListTableExplorer.java,v 1.2 2006/09/25 08:52:36 acaproni Exp $ * @author Lionel Mestre */ private static class GPTreeTableView extends TreeTableView implements TreeTableViewTableAccess { /** * @param arg0 */ public GPTreeTableView(NodeTableModel model) { super(model); } public GPTreeTableView() { super(); } public JTree getTree() { return super.tree; } public JTable getTable() { return super.treeTable; } /* (non-Javadoc) * @see cern.gp.explorer.TreeTableViewTableAccess#getTreeTableView() */ public TreeTableView getTreeTableView() { return this; } /* (non-Javadoc) * @see cern.gp.explorer.TreeViewTreeAccess#getTreeView() */ public TreeView getTreeView() { return this; } } }