/** Reëexpand descendants of a newly expanded path which were * expanded the last time their parent was expanded */ private void updateExpandedDescendants(TreePath path) { getLayout().setExpandedState(path, true); TreePath[] descendants = getTreePathSupport().getExpandedDescendants(path); if(descendants.length > 0) { for (int i=0; i < descendants.length; i++) { getLayout().setExpandedState(descendants[i], true); } } }
/** Create a change TableModelEvent for the passed TreeModelEvent and the * contiguous subrange of the TreeModelEvent's getChildIndices() value */ private TableModelEvent createTableChangeEvent (TreeModelEvent e, int[] indices) { TableModelEvent result = null; TreePath path = e.getTreePath(); int row = getLayout().getRowForPath(path); int first = null == indices ? row : indices[0]; int last = null == indices ? row : indices[indices.length-1]; //TODO - does not need to be ALL_COLUMNS, but we need a way to determine //which column index is the tree result = new TableModelEvent (getModel(), first, last, TableModelEvent.ALL_COLUMNS, TableModelEvent.UPDATE); return result; }
/** Process a node removal event from the user-supplied tree model * Order of operations: * <ol><li>Refire the same tree event with the OutlineModel we're * proxying as the source</li> * <li>Create one or more table model events (more than one if the * incoming event affects discontiguous rows) reflecting the effect * of the tree change</li> * <li>Call the method with the same signature as this one on the * layout cache, so it will update its state appropriately</li> * <li>Fire the generated TableModelEvent(s)</li></ol> */ public void treeNodesRemoved(TreeModelEvent e) { assert SwingUtilities.isEventDispatchThread(); fireTreeChange (translateEvent(e), NODES_REMOVED); TableModelEvent[] events = translateEvent(e, NODES_REMOVED); getLayout().treeNodesRemoved(e); fireTableChange(events); }
/** Process a change event from the user-supplied tree model. * Order of operations: * <ol><li>Refire the same tree event with the OutlineModel we're * proxying as the source</li> * <li>Create one or more table model events (more than one if the * incoming event affects discontiguous rows) reflecting the effect * of the tree change</li> * <li>Call the method with the same signature as this one on the * layout cache, so it will update its state appropriately</li> * <li>Fire the generated TableModelEvent(s)</li></ol> */ public void treeNodesChanged(TreeModelEvent e) { assert SwingUtilities.isEventDispatchThread(); fireTreeChange (translateEvent(e), NODES_CHANGED); TableModelEvent[] events = translateEvent(e, NODES_CHANGED); getLayout().treeNodesChanged(e); fireTableChange(events); }
/** Process a node insertion event from the user-supplied tree model * Order of operations: * <ol><li>Refire the same tree event with the OutlineModel we're * proxying as the source</li> * <li>Create one or more table model events (more than one if the * incoming event affects discontiguous rows) reflecting the effect * of the tree change</li> * <li>Call the method with the same signature as this one on the * layout cache, so it will update its state appropriately</li> * <li>Fire the generated TableModelEvent(s)</li></ol> */ public void treeNodesInserted(TreeModelEvent e) { assert SwingUtilities.isEventDispatchThread(); fireTreeChange (translateEvent(e), NODES_INSERTED); TableModelEvent[] events = translateEvent(e, NODES_INSERTED); getLayout().treeNodesInserted(e); fireTableChange(events); }
public void treeCollapsed(TreeExpansionEvent event) { assert SwingUtilities.isEventDispatchThread(); log ("treeExpanded", event); //FixedHeightLayoutCache tests if the event is null. //Don't know how it could be, but there's probably a reason... if(event != null) { TreePath path = event.getPath(); //Tell the layout about the change if(path != null && getTreePathSupport().isVisible(path)) { getLayout().setExpandedState(path, false); } } log ("about to fire", pendingExpansionEvent); //Now fire a change on the owning row so its display is updated (it //may have just become an expandable node) TreePath path = event.getPath(); int row = getLayout().getRowForPath(path); TableModelEvent evt = new TableModelEvent (getModel(), row, row, 0, TableModelEvent.UPDATE); fireTableChange(new TableModelEvent[] {evt, pendingExpansionEvent}); pendingExpansionEvent = null; inProgressEvent = null; }
/** Process a structural change event from the user-supplied tree model. * This will result in a generic "something changed" * TableModelEvent being fired. */ public void treeStructureChanged(TreeModelEvent e) { assert SwingUtilities.isEventDispatchThread(); getLayout().treeStructureChanged(e); fireTreeChange (translateEvent(e), STRUCTURE_CHANGED); //If it's a structural change, we need to dump all our info about the //existing tree structure - it can be bogus now. Similar to JTree, //this will have the effect of collapsing all expanded paths. The //TreePathSupport takes care of dumping the layout cache's copy of //such data getTreePathSupport().clear(); //We will just fire a "Something happened. Go figure out what." event. fireTableChange (new TableModelEvent (getModel())); }
int firstRow = getLayout().getRowForPath(path) + 1; if (firstRow == -1) {
/** Updates the layout to mark the descendants of the events path as also * expanded if they were the last it was expanded, then fires a table change. */ public void treeExpanded(TreeExpansionEvent event) { assert SwingUtilities.isEventDispatchThread(); log ("treeExpanded", event); //Mysterious how the event could be null, but JTree tests it //so we will too. if(event != null) { updateExpandedDescendants(event.getPath()); } log ("about to fire", pendingExpansionEvent); //Now fire a change on the owning row so its display is updated (it //may have just become an expandable node) TreePath path = event.getPath(); int row = getLayout().getRowForPath(path); TableModelEvent evt = new TableModelEvent (getModel(), row, row, 0, TableModelEvent.UPDATE); if (row == -1) { evt = new TableModelEvent(getModel()); } fireTableChange(new TableModelEvent[] {evt, pendingExpansionEvent}); pendingExpansionEvent = null; inProgressEvent = null; }