| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package javax.swing.plaf.basic;  | 
 | 
 | 
 | 
import javax.swing.*;  | 
 | 
import javax.swing.event.*;  | 
 | 
import java.awt.*;  | 
 | 
import java.awt.event.*;  | 
 | 
import java.awt.datatransfer.*;  | 
 | 
import java.beans.*;  | 
 | 
import java.util.Enumeration;  | 
 | 
import java.util.Hashtable;  | 
 | 
import java.util.ArrayList;  | 
 | 
import java.util.Collections;  | 
 | 
import java.util.Comparator;  | 
 | 
import javax.swing.plaf.ComponentUI;  | 
 | 
import javax.swing.plaf.UIResource;  | 
 | 
import javax.swing.plaf.TreeUI;  | 
 | 
import javax.swing.tree.*;  | 
 | 
import javax.swing.text.Position;  | 
 | 
import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag;  | 
 | 
import sun.awt.AWTAccessor;  | 
 | 
import sun.swing.SwingUtilities2;  | 
 | 
 | 
 | 
import sun.swing.DefaultLookup;  | 
 | 
import sun.swing.UIAction;  | 
 | 
 | 
 | 
/**  | 
 | 
 * The basic L&F for a hierarchical data structure.  | 
 | 
 * <p>  | 
 | 
 *  | 
 | 
 * @author Scott Violet  | 
 | 
 * @author Shannon Hickey (drag and drop)  | 
 | 
 */  | 
 | 
 | 
 | 
public class BasicTreeUI extends TreeUI  | 
 | 
{ | 
 | 
    private static final StringBuilder BASELINE_COMPONENT_KEY =  | 
 | 
        new StringBuilder("Tree.baselineComponent"); | 
 | 
 | 
 | 
      | 
 | 
    static private final Actions SHARED_ACTION = new Actions();  | 
 | 
 | 
 | 
    transient protected Icon        collapsedIcon;  | 
 | 
    transient protected Icon        expandedIcon;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    private Color hashColor;  | 
 | 
 | 
 | 
      | 
 | 
      * drawn. */  | 
 | 
    protected int               leftChildIndent;  | 
 | 
      | 
 | 
      * contents will be drawn. */  | 
 | 
    protected int               rightChildIndent;  | 
 | 
      | 
 | 
      * and rightChildIndent. */  | 
 | 
    protected int               totalChildIndent;  | 
 | 
 | 
 | 
      | 
 | 
    protected Dimension         preferredMinSize;  | 
 | 
 | 
 | 
      | 
 | 
    protected int               lastSelectedRow;  | 
 | 
 | 
 | 
      | 
 | 
    protected JTree             tree;  | 
 | 
 | 
 | 
      | 
 | 
    transient protected TreeCellRenderer   currentCellRenderer;  | 
 | 
 | 
 | 
      | 
 | 
     * created by this instance. */  | 
 | 
    protected boolean           createdRenderer;  | 
 | 
 | 
 | 
      | 
 | 
    transient protected TreeCellEditor     cellEditor;  | 
 | 
 | 
 | 
      | 
 | 
     * created by this instance. */  | 
 | 
    protected boolean           createdCellEditor;  | 
 | 
 | 
 | 
      | 
 | 
      * the node should be selected before editing, used in completeEditing. */  | 
 | 
    protected boolean           stopEditingInCompleteEditing;  | 
 | 
 | 
 | 
      | 
 | 
    protected CellRendererPane  rendererPane;  | 
 | 
 | 
 | 
      | 
 | 
    protected Dimension         preferredSize;  | 
 | 
 | 
 | 
      | 
 | 
    protected boolean           validCachedPreferredSize;  | 
 | 
 | 
 | 
    /** Object responsible for handling sizing and expanded issues. */  | 
 | 
    // WARNING: Be careful with the bounds held by treeState. They are  | 
 | 
    // always in terms of left-to-right. They get mapped to right-to-left  | 
 | 
      | 
 | 
    protected AbstractLayoutCache  treeState;  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
    protected Hashtable<TreePath,Boolean> drawingCache;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     * return a FixedHeightLayoutCache instance. */  | 
 | 
    protected boolean           largeModel;  | 
 | 
 | 
 | 
      | 
 | 
    protected AbstractLayoutCache.NodeDimensions     nodeDimensions;  | 
 | 
 | 
 | 
      | 
 | 
    protected TreeModel         treeModel;  | 
 | 
 | 
 | 
      | 
 | 
    protected TreeSelectionModel treeSelectionModel;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     * and if the root handles are visible. */  | 
 | 
    protected int               depthOffset;  | 
 | 
 | 
 | 
    // Following 4 ivars are only valid when editing.  | 
 | 
 | 
 | 
      | 
 | 
      * editing. */  | 
 | 
    protected Component         editingComponent;  | 
 | 
 | 
 | 
      | 
 | 
    protected TreePath          editingPath;  | 
 | 
 | 
 | 
      | 
 | 
     * editingComponent is not null. */  | 
 | 
    protected int               editingRow;  | 
 | 
 | 
 | 
      | 
 | 
    protected boolean           editorHasDifferentSize;  | 
 | 
 | 
 | 
      | 
 | 
    private int                 leadRow;  | 
 | 
      | 
 | 
     * or ANCHOR_SELECTION_PATH_PROPERTY will not generate a repaint. */  | 
 | 
    private boolean             ignoreLAChange;  | 
 | 
 | 
 | 
      | 
 | 
    private boolean             leftToRight;  | 
 | 
 | 
 | 
      | 
 | 
    private PropertyChangeListener propertyChangeListener;  | 
 | 
    private PropertyChangeListener selectionModelPropertyChangeListener;  | 
 | 
    private MouseListener mouseListener;  | 
 | 
    private FocusListener focusListener;  | 
 | 
    private KeyListener keyListener;  | 
 | 
      | 
 | 
     * updates the validCachedPreferredSize bit accordingly. */  | 
 | 
    private ComponentListener   componentListener;  | 
 | 
      | 
 | 
    private CellEditorListener  cellEditorListener;  | 
 | 
      | 
 | 
    private TreeSelectionListener treeSelectionListener;  | 
 | 
      | 
 | 
    private TreeModelListener treeModelListener;  | 
 | 
      | 
 | 
    private TreeExpansionListener treeExpansionListener;  | 
 | 
 | 
 | 
      | 
 | 
    private boolean paintLines = true;  | 
 | 
 | 
 | 
      | 
 | 
    private boolean lineTypeDashed;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private long timeFactor = 1000L;  | 
 | 
 | 
 | 
    private Handler handler;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private MouseEvent releaseEvent;  | 
 | 
 | 
 | 
    public static ComponentUI createUI(JComponent x) { | 
 | 
        return new BasicTreeUI();  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    static void loadActionMap(LazyActionMap map) { | 
 | 
        map.put(new Actions(Actions.SELECT_PREVIOUS));  | 
 | 
        map.put(new Actions(Actions.SELECT_PREVIOUS_CHANGE_LEAD));  | 
 | 
        map.put(new Actions(Actions.SELECT_PREVIOUS_EXTEND_SELECTION));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SELECT_NEXT));  | 
 | 
        map.put(new Actions(Actions.SELECT_NEXT_CHANGE_LEAD));  | 
 | 
        map.put(new Actions(Actions.SELECT_NEXT_EXTEND_SELECTION));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SELECT_CHILD));  | 
 | 
        map.put(new Actions(Actions.SELECT_CHILD_CHANGE_LEAD));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SELECT_PARENT));  | 
 | 
        map.put(new Actions(Actions.SELECT_PARENT_CHANGE_LEAD));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SCROLL_UP_CHANGE_SELECTION));  | 
 | 
        map.put(new Actions(Actions.SCROLL_UP_CHANGE_LEAD));  | 
 | 
        map.put(new Actions(Actions.SCROLL_UP_EXTEND_SELECTION));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SCROLL_DOWN_CHANGE_SELECTION));  | 
 | 
        map.put(new Actions(Actions.SCROLL_DOWN_EXTEND_SELECTION));  | 
 | 
        map.put(new Actions(Actions.SCROLL_DOWN_CHANGE_LEAD));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SELECT_FIRST));  | 
 | 
        map.put(new Actions(Actions.SELECT_FIRST_CHANGE_LEAD));  | 
 | 
        map.put(new Actions(Actions.SELECT_FIRST_EXTEND_SELECTION));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SELECT_LAST));  | 
 | 
        map.put(new Actions(Actions.SELECT_LAST_CHANGE_LEAD));  | 
 | 
        map.put(new Actions(Actions.SELECT_LAST_EXTEND_SELECTION));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.TOGGLE));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.CANCEL_EDITING));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.START_EDITING));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SELECT_ALL));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.CLEAR_SELECTION));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SCROLL_LEFT));  | 
 | 
        map.put(new Actions(Actions.SCROLL_RIGHT));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SCROLL_LEFT_EXTEND_SELECTION));  | 
 | 
        map.put(new Actions(Actions.SCROLL_RIGHT_EXTEND_SELECTION));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.SCROLL_RIGHT_CHANGE_LEAD));  | 
 | 
        map.put(new Actions(Actions.SCROLL_LEFT_CHANGE_LEAD));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.EXPAND));  | 
 | 
        map.put(new Actions(Actions.COLLAPSE));  | 
 | 
        map.put(new Actions(Actions.MOVE_SELECTION_TO_PARENT));  | 
 | 
 | 
 | 
        map.put(new Actions(Actions.ADD_TO_SELECTION));  | 
 | 
        map.put(new Actions(Actions.TOGGLE_AND_ANCHOR));  | 
 | 
        map.put(new Actions(Actions.EXTEND_TO));  | 
 | 
        map.put(new Actions(Actions.MOVE_SELECTION_TO));  | 
 | 
 | 
 | 
        map.put(TransferHandler.getCutAction());  | 
 | 
        map.put(TransferHandler.getCopyAction());  | 
 | 
        map.put(TransferHandler.getPasteAction());  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    public BasicTreeUI() { | 
 | 
        super();  | 
 | 
    }  | 
 | 
 | 
 | 
    protected Color getHashColor() { | 
 | 
        return hashColor;  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void setHashColor(Color color) { | 
 | 
        hashColor = color;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void setLeftChildIndent(int newAmount) { | 
 | 
        leftChildIndent = newAmount;  | 
 | 
        totalChildIndent = leftChildIndent + rightChildIndent;  | 
 | 
        if(treeState != null)  | 
 | 
            treeState.invalidateSizes();  | 
 | 
        updateSize();  | 
 | 
    }  | 
 | 
 | 
 | 
    public int getLeftChildIndent() { | 
 | 
        return leftChildIndent;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void setRightChildIndent(int newAmount) { | 
 | 
        rightChildIndent = newAmount;  | 
 | 
        totalChildIndent = leftChildIndent + rightChildIndent;  | 
 | 
        if(treeState != null)  | 
 | 
            treeState.invalidateSizes();  | 
 | 
        updateSize();  | 
 | 
    }  | 
 | 
 | 
 | 
    public int getRightChildIndent() { | 
 | 
        return rightChildIndent;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void setExpandedIcon(Icon newG) { | 
 | 
        expandedIcon = newG;  | 
 | 
    }  | 
 | 
 | 
 | 
    public Icon getExpandedIcon() { | 
 | 
        return expandedIcon;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void setCollapsedIcon(Icon newG) { | 
 | 
        collapsedIcon = newG;  | 
 | 
    }  | 
 | 
 | 
 | 
    public Icon getCollapsedIcon() { | 
 | 
        return collapsedIcon;  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Methods for configuring the behavior of the tree. None of them  | 
 | 
    // push the value to the JTree instance. You should really only  | 
 | 
    // call these methods on the JTree.  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setLargeModel(boolean largeModel) { | 
 | 
        if(getRowHeight() < 1)  | 
 | 
            largeModel = false;  | 
 | 
        if(this.largeModel != largeModel) { | 
 | 
            completeEditing();  | 
 | 
            this.largeModel = largeModel;  | 
 | 
            treeState = createLayoutCache();  | 
 | 
            configureLayoutCache();  | 
 | 
            updateLayoutCacheExpandedNodesIfNecessary();  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    protected boolean isLargeModel() { | 
 | 
        return largeModel;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setRowHeight(int rowHeight) { | 
 | 
        completeEditing();  | 
 | 
        if(treeState != null) { | 
 | 
            setLargeModel(tree.isLargeModel());  | 
 | 
            treeState.setRowHeight(rowHeight);  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    protected int getRowHeight() { | 
 | 
        return (tree == null) ? -1 : tree.getRowHeight();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setCellRenderer(TreeCellRenderer tcr) { | 
 | 
        completeEditing();  | 
 | 
        updateRenderer();  | 
 | 
        if(treeState != null) { | 
 | 
            treeState.invalidateSizes();  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected TreeCellRenderer getCellRenderer() { | 
 | 
        return currentCellRenderer;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setModel(TreeModel model) { | 
 | 
        completeEditing();  | 
 | 
        if(treeModel != null && treeModelListener != null)  | 
 | 
            treeModel.removeTreeModelListener(treeModelListener);  | 
 | 
        treeModel = model;  | 
 | 
        if(treeModel != null) { | 
 | 
            if(treeModelListener != null)  | 
 | 
                treeModel.addTreeModelListener(treeModelListener);  | 
 | 
        }  | 
 | 
        if(treeState != null) { | 
 | 
            treeState.setModel(model);  | 
 | 
            updateLayoutCacheExpandedNodesIfNecessary();  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    protected TreeModel getModel() { | 
 | 
        return treeModel;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setRootVisible(boolean newValue) { | 
 | 
        completeEditing();  | 
 | 
        updateDepthOffset();  | 
 | 
        if(treeState != null) { | 
 | 
            treeState.setRootVisible(newValue);  | 
 | 
            treeState.invalidateSizes();  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    protected boolean isRootVisible() { | 
 | 
        return (tree != null) ? tree.isRootVisible() : false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setShowsRootHandles(boolean newValue) { | 
 | 
        completeEditing();  | 
 | 
        updateDepthOffset();  | 
 | 
        if(treeState != null) { | 
 | 
            treeState.invalidateSizes();  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    protected boolean getShowsRootHandles() { | 
 | 
        return (tree != null) ? tree.getShowsRootHandles() : false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setCellEditor(TreeCellEditor editor) { | 
 | 
        updateCellEditor();  | 
 | 
    }  | 
 | 
 | 
 | 
    protected TreeCellEditor getCellEditor() { | 
 | 
        return (tree != null) ? tree.getCellEditor() : null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setEditable(boolean newValue) { | 
 | 
        updateCellEditor();  | 
 | 
    }  | 
 | 
 | 
 | 
    protected boolean isEditable() { | 
 | 
        return (tree != null) ? tree.isEditable() : false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void setSelectionModel(TreeSelectionModel newLSM) { | 
 | 
        completeEditing();  | 
 | 
        if(selectionModelPropertyChangeListener != null &&  | 
 | 
           treeSelectionModel != null)  | 
 | 
            treeSelectionModel.removePropertyChangeListener  | 
 | 
                              (selectionModelPropertyChangeListener);  | 
 | 
        if(treeSelectionListener != null && treeSelectionModel != null)  | 
 | 
            treeSelectionModel.removeTreeSelectionListener  | 
 | 
                               (treeSelectionListener);  | 
 | 
        treeSelectionModel = newLSM;  | 
 | 
        if(treeSelectionModel != null) { | 
 | 
            if(selectionModelPropertyChangeListener != null)  | 
 | 
                treeSelectionModel.addPropertyChangeListener  | 
 | 
                              (selectionModelPropertyChangeListener);  | 
 | 
            if(treeSelectionListener != null)  | 
 | 
                treeSelectionModel.addTreeSelectionListener  | 
 | 
                                   (treeSelectionListener);  | 
 | 
            if(treeState != null)  | 
 | 
                treeState.setSelectionModel(treeSelectionModel);  | 
 | 
        }  | 
 | 
        else if(treeState != null)  | 
 | 
            treeState.setSelectionModel(null);  | 
 | 
        if(tree != null)  | 
 | 
            tree.repaint();  | 
 | 
    }  | 
 | 
 | 
 | 
    protected TreeSelectionModel getSelectionModel() { | 
 | 
        return treeSelectionModel;  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // TreeUI methods  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public Rectangle getPathBounds(JTree tree, TreePath path) { | 
 | 
        if(tree != null && treeState != null) { | 
 | 
            return getPathBounds(path, tree.getInsets(), new Rectangle());  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
    private Rectangle getPathBounds(TreePath path, Insets insets,  | 
 | 
                                    Rectangle bounds) { | 
 | 
        bounds = treeState.getBounds(path, bounds);  | 
 | 
        if (bounds != null) { | 
 | 
            if (leftToRight) { | 
 | 
                bounds.x += insets.left;  | 
 | 
            } else { | 
 | 
                bounds.x = tree.getWidth() - (bounds.x + bounds.width) -  | 
 | 
                        insets.right;  | 
 | 
            }  | 
 | 
            bounds.y += insets.top;  | 
 | 
        }  | 
 | 
        return bounds;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public TreePath getPathForRow(JTree tree, int row) { | 
 | 
        return (treeState != null) ? treeState.getPathForRow(row) : null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public int getRowForPath(JTree tree, TreePath path) { | 
 | 
        return (treeState != null) ? treeState.getRowForPath(path) : -1;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    public int getRowCount(JTree tree) { | 
 | 
        return (treeState != null) ? treeState.getRowCount() : 0;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public TreePath getClosestPathForLocation(JTree tree, int x, int y) { | 
 | 
        if(tree != null && treeState != null) { | 
 | 
            // TreeState doesn't care about the x location, hence it isn't  | 
 | 
              | 
 | 
            y -= tree.getInsets().top;  | 
 | 
            return treeState.getPathClosestTo(x, y);  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public boolean isEditing(JTree tree) { | 
 | 
        return (editingComponent != null);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public boolean stopEditing(JTree tree) { | 
 | 
        if(editingComponent != null && cellEditor.stopCellEditing()) { | 
 | 
            completeEditing(false, false, true);  | 
 | 
            return true;  | 
 | 
        }  | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    public void cancelEditing(JTree tree) { | 
 | 
        if(editingComponent != null) { | 
 | 
            completeEditing(false, true, false);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public void startEditingAtPath(JTree tree, TreePath path) { | 
 | 
        tree.scrollPathToVisible(path);  | 
 | 
        if(path != null && tree.isVisible(path))  | 
 | 
            startEditing(path, null);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public TreePath getEditingPath(JTree tree) { | 
 | 
        return editingPath;  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Install methods  | 
 | 
    //  | 
 | 
 | 
 | 
    public void installUI(JComponent c) { | 
 | 
        if ( c == null ) { | 
 | 
            throw new NullPointerException( "null component passed to BasicTreeUI.installUI()" );  | 
 | 
        }  | 
 | 
 | 
 | 
        tree = (JTree)c;  | 
 | 
 | 
 | 
        prepareForUIInstall();  | 
 | 
 | 
 | 
          | 
 | 
        installDefaults();  | 
 | 
        installKeyboardActions();  | 
 | 
        installComponents();  | 
 | 
        installListeners();  | 
 | 
 | 
 | 
        completeUIInstall();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void prepareForUIInstall() { | 
 | 
        drawingCache = new Hashtable<TreePath,Boolean>(7);  | 
 | 
 | 
 | 
          | 
 | 
        leftToRight = BasicGraphicsUtils.isLeftToRight(tree);  | 
 | 
        stopEditingInCompleteEditing = true;  | 
 | 
        lastSelectedRow = -1;  | 
 | 
        leadRow = -1;  | 
 | 
        preferredSize = new Dimension();  | 
 | 
 | 
 | 
        largeModel = tree.isLargeModel();  | 
 | 
        if(getRowHeight() <= 0)  | 
 | 
            largeModel = false;  | 
 | 
        setModel(tree.getModel());  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void completeUIInstall() { | 
 | 
        // Custom install code  | 
 | 
 | 
 | 
        this.setShowsRootHandles(tree.getShowsRootHandles());  | 
 | 
 | 
 | 
        updateRenderer();  | 
 | 
 | 
 | 
        updateDepthOffset();  | 
 | 
 | 
 | 
        setSelectionModel(tree.getSelectionModel());  | 
 | 
 | 
 | 
          | 
 | 
        treeState = createLayoutCache();  | 
 | 
        configureLayoutCache();  | 
 | 
 | 
 | 
        updateSize();  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void installDefaults() { | 
 | 
        if(tree.getBackground() == null ||  | 
 | 
           tree.getBackground() instanceof UIResource) { | 
 | 
            tree.setBackground(UIManager.getColor("Tree.background")); | 
 | 
        }  | 
 | 
        if(getHashColor() == null || getHashColor() instanceof UIResource) { | 
 | 
            setHashColor(UIManager.getColor("Tree.hash")); | 
 | 
        }  | 
 | 
        if (tree.getFont() == null || tree.getFont() instanceof UIResource)  | 
 | 
            tree.setFont( UIManager.getFont("Tree.font") ); | 
 | 
        // JTree's original row height is 16.  To correctly display the  | 
 | 
        // contents on Linux we should have set it to 18, Windows 19 and  | 
 | 
        // Solaris 20.  As these values vary so much it's too hard to  | 
 | 
        // be backward compatable and try to update the row height, we're  | 
 | 
        // therefor NOT going to adjust the row height based on font.  If the  | 
 | 
        // developer changes the font, it's there responsibility to update  | 
 | 
        // the row height.  | 
 | 
 | 
 | 
        setExpandedIcon( (Icon)UIManager.get( "Tree.expandedIcon" ) );  | 
 | 
        setCollapsedIcon( (Icon)UIManager.get( "Tree.collapsedIcon" ) );  | 
 | 
 | 
 | 
        setLeftChildIndent(((Integer)UIManager.get("Tree.leftChildIndent")). | 
 | 
                           intValue());  | 
 | 
        setRightChildIndent(((Integer)UIManager.get("Tree.rightChildIndent")). | 
 | 
                           intValue());  | 
 | 
 | 
 | 
        LookAndFeel.installProperty(tree, "rowHeight",  | 
 | 
                                    UIManager.get("Tree.rowHeight")); | 
 | 
 | 
 | 
        largeModel = (tree.isLargeModel() && tree.getRowHeight() > 0);  | 
 | 
 | 
 | 
        Object scrollsOnExpand = UIManager.get("Tree.scrollsOnExpand"); | 
 | 
        if (scrollsOnExpand != null) { | 
 | 
            LookAndFeel.installProperty(tree, "scrollsOnExpand", scrollsOnExpand);  | 
 | 
        }  | 
 | 
 | 
 | 
        paintLines = UIManager.getBoolean("Tree.paintLines"); | 
 | 
        lineTypeDashed = UIManager.getBoolean("Tree.lineTypeDashed"); | 
 | 
 | 
 | 
        Long l = (Long)UIManager.get("Tree.timeFactor"); | 
 | 
        timeFactor = (l!=null) ? l.longValue() : 1000L;  | 
 | 
 | 
 | 
        Object showsRootHandles = UIManager.get("Tree.showsRootHandles"); | 
 | 
        if (showsRootHandles != null) { | 
 | 
            LookAndFeel.installProperty(tree,  | 
 | 
                    JTree.SHOWS_ROOT_HANDLES_PROPERTY, showsRootHandles);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void installListeners() { | 
 | 
        if ( (propertyChangeListener = createPropertyChangeListener())  | 
 | 
             != null ) { | 
 | 
            tree.addPropertyChangeListener(propertyChangeListener);  | 
 | 
        }  | 
 | 
        if ( (mouseListener = createMouseListener()) != null ) { | 
 | 
            tree.addMouseListener(mouseListener);  | 
 | 
            if (mouseListener instanceof MouseMotionListener) { | 
 | 
                tree.addMouseMotionListener((MouseMotionListener)mouseListener);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if ((focusListener = createFocusListener()) != null ) { | 
 | 
            tree.addFocusListener(focusListener);  | 
 | 
        }  | 
 | 
        if ((keyListener = createKeyListener()) != null) { | 
 | 
            tree.addKeyListener(keyListener);  | 
 | 
        }  | 
 | 
        if((treeExpansionListener = createTreeExpansionListener()) != null) { | 
 | 
            tree.addTreeExpansionListener(treeExpansionListener);  | 
 | 
        }  | 
 | 
        if((treeModelListener = createTreeModelListener()) != null &&  | 
 | 
           treeModel != null) { | 
 | 
            treeModel.addTreeModelListener(treeModelListener);  | 
 | 
        }  | 
 | 
        if((selectionModelPropertyChangeListener =  | 
 | 
            createSelectionModelPropertyChangeListener()) != null &&  | 
 | 
           treeSelectionModel != null) { | 
 | 
            treeSelectionModel.addPropertyChangeListener  | 
 | 
                (selectionModelPropertyChangeListener);  | 
 | 
        }  | 
 | 
        if((treeSelectionListener = createTreeSelectionListener()) != null &&  | 
 | 
           treeSelectionModel != null) { | 
 | 
            treeSelectionModel.addTreeSelectionListener(treeSelectionListener);  | 
 | 
        }  | 
 | 
 | 
 | 
        TransferHandler th = tree.getTransferHandler();  | 
 | 
        if (th == null || th instanceof UIResource) { | 
 | 
            tree.setTransferHandler(defaultTransferHandler);  | 
 | 
            // default TransferHandler doesn't support drop  | 
 | 
              | 
 | 
            if (tree.getDropTarget() instanceof UIResource) { | 
 | 
                tree.setDropTarget(null);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        LookAndFeel.installProperty(tree, "opaque", Boolean.TRUE);  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void installKeyboardActions() { | 
 | 
        InputMap km = getInputMap(JComponent.  | 
 | 
                                  WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);  | 
 | 
 | 
 | 
        SwingUtilities.replaceUIInputMap(tree, JComponent.  | 
 | 
                                         WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,  | 
 | 
                                         km);  | 
 | 
        km = getInputMap(JComponent.WHEN_FOCUSED);  | 
 | 
        SwingUtilities.replaceUIInputMap(tree, JComponent.WHEN_FOCUSED, km);  | 
 | 
 | 
 | 
        LazyActionMap.installLazyActionMap(tree, BasicTreeUI.class,  | 
 | 
                                           "Tree.actionMap");  | 
 | 
    }  | 
 | 
 | 
 | 
    InputMap getInputMap(int condition) { | 
 | 
        if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { | 
 | 
            return (InputMap)DefaultLookup.get(tree, this,  | 
 | 
                                               "Tree.ancestorInputMap");  | 
 | 
        }  | 
 | 
        else if (condition == JComponent.WHEN_FOCUSED) { | 
 | 
            InputMap keyMap = (InputMap)DefaultLookup.get(tree, this,  | 
 | 
                                                      "Tree.focusInputMap");  | 
 | 
            InputMap rtlKeyMap;  | 
 | 
 | 
 | 
            if (tree.getComponentOrientation().isLeftToRight() ||  | 
 | 
                  ((rtlKeyMap = (InputMap)DefaultLookup.get(tree, this,  | 
 | 
                  "Tree.focusInputMap.RightToLeft")) == null)) { | 
 | 
                return keyMap;  | 
 | 
            } else { | 
 | 
                rtlKeyMap.setParent(keyMap);  | 
 | 
                return rtlKeyMap;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void installComponents() { | 
 | 
        if ((rendererPane = createCellRendererPane()) != null) { | 
 | 
            tree.add( rendererPane );  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Create methods.  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected AbstractLayoutCache.NodeDimensions createNodeDimensions() { | 
 | 
        return new NodeDimensionsHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected PropertyChangeListener createPropertyChangeListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
    private Handler getHandler() { | 
 | 
        if (handler == null) { | 
 | 
            handler = new Handler();  | 
 | 
        }  | 
 | 
        return handler;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected MouseListener createMouseListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected FocusListener createFocusListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected KeyListener createKeyListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected PropertyChangeListener createSelectionModelPropertyChangeListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected TreeSelectionListener createTreeSelectionListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected CellEditorListener createCellEditorListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected ComponentListener createComponentListener() { | 
 | 
        return new ComponentHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected TreeExpansionListener createTreeExpansionListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected AbstractLayoutCache createLayoutCache() { | 
 | 
        if(isLargeModel() && getRowHeight() > 0) { | 
 | 
            return new FixedHeightLayoutCache();  | 
 | 
        }  | 
 | 
        return new VariableHeightLayoutCache();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected CellRendererPane createCellRendererPane() { | 
 | 
        return new CellRendererPane();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    protected TreeCellEditor createDefaultCellEditor() { | 
 | 
        if(currentCellRenderer != null &&  | 
 | 
           (currentCellRenderer instanceof DefaultTreeCellRenderer)) { | 
 | 
            DefaultTreeCellEditor editor = new DefaultTreeCellEditor  | 
 | 
                        (tree, (DefaultTreeCellRenderer)currentCellRenderer);  | 
 | 
 | 
 | 
            return editor;  | 
 | 
        }  | 
 | 
        return new DefaultTreeCellEditor(tree, null);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    protected TreeCellRenderer createDefaultCellRenderer() { | 
 | 
        return new DefaultTreeCellRenderer();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected TreeModelListener createTreeModelListener() { | 
 | 
        return getHandler();  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Uninstall methods  | 
 | 
    //  | 
 | 
 | 
 | 
    public void uninstallUI(JComponent c) { | 
 | 
        completeEditing();  | 
 | 
 | 
 | 
        prepareForUIUninstall();  | 
 | 
 | 
 | 
        uninstallDefaults();  | 
 | 
        uninstallListeners();  | 
 | 
        uninstallKeyboardActions();  | 
 | 
        uninstallComponents();  | 
 | 
 | 
 | 
        completeUIUninstall();  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void prepareForUIUninstall() { | 
 | 
    }  | 
 | 
 | 
 | 
    protected void completeUIUninstall() { | 
 | 
        if(createdRenderer) { | 
 | 
            tree.setCellRenderer(null);  | 
 | 
        }  | 
 | 
        if(createdCellEditor) { | 
 | 
            tree.setCellEditor(null);  | 
 | 
        }  | 
 | 
        cellEditor = null;  | 
 | 
        currentCellRenderer = null;  | 
 | 
        rendererPane = null;  | 
 | 
        componentListener = null;  | 
 | 
        propertyChangeListener = null;  | 
 | 
        mouseListener = null;  | 
 | 
        focusListener = null;  | 
 | 
        keyListener = null;  | 
 | 
        setSelectionModel(null);  | 
 | 
        treeState = null;  | 
 | 
        drawingCache = null;  | 
 | 
        selectionModelPropertyChangeListener = null;  | 
 | 
        tree = null;  | 
 | 
        treeModel = null;  | 
 | 
        treeSelectionModel = null;  | 
 | 
        treeSelectionListener = null;  | 
 | 
        treeExpansionListener = null;  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void uninstallDefaults() { | 
 | 
        if (tree.getTransferHandler() instanceof UIResource) { | 
 | 
            tree.setTransferHandler(null);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void uninstallListeners() { | 
 | 
        if(componentListener != null) { | 
 | 
            tree.removeComponentListener(componentListener);  | 
 | 
        }  | 
 | 
        if (propertyChangeListener != null) { | 
 | 
            tree.removePropertyChangeListener(propertyChangeListener);  | 
 | 
        }  | 
 | 
        if (mouseListener != null) { | 
 | 
            tree.removeMouseListener(mouseListener);  | 
 | 
            if (mouseListener instanceof MouseMotionListener) { | 
 | 
                tree.removeMouseMotionListener((MouseMotionListener)mouseListener);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (focusListener != null) { | 
 | 
            tree.removeFocusListener(focusListener);  | 
 | 
        }  | 
 | 
        if (keyListener != null) { | 
 | 
            tree.removeKeyListener(keyListener);  | 
 | 
        }  | 
 | 
        if(treeExpansionListener != null) { | 
 | 
            tree.removeTreeExpansionListener(treeExpansionListener);  | 
 | 
        }  | 
 | 
        if(treeModel != null && treeModelListener != null) { | 
 | 
            treeModel.removeTreeModelListener(treeModelListener);  | 
 | 
        }  | 
 | 
        if(selectionModelPropertyChangeListener != null &&  | 
 | 
           treeSelectionModel != null) { | 
 | 
            treeSelectionModel.removePropertyChangeListener  | 
 | 
                (selectionModelPropertyChangeListener);  | 
 | 
        }  | 
 | 
        if(treeSelectionListener != null && treeSelectionModel != null) { | 
 | 
            treeSelectionModel.removeTreeSelectionListener  | 
 | 
                               (treeSelectionListener);  | 
 | 
        }  | 
 | 
        handler = null;  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void uninstallKeyboardActions() { | 
 | 
        SwingUtilities.replaceUIActionMap(tree, null);  | 
 | 
        SwingUtilities.replaceUIInputMap(tree, JComponent.  | 
 | 
                                         WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,  | 
 | 
                                         null);  | 
 | 
        SwingUtilities.replaceUIInputMap(tree, JComponent.WHEN_FOCUSED, null);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void uninstallComponents() { | 
 | 
        if(rendererPane != null) { | 
 | 
            tree.remove(rendererPane);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private void redoTheLayout() { | 
 | 
        if (treeState != null) { | 
 | 
            treeState.invalidateSizes();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public int getBaseline(JComponent c, int width, int height) { | 
 | 
        super.getBaseline(c, width, height);  | 
 | 
        UIDefaults lafDefaults = UIManager.getLookAndFeelDefaults();  | 
 | 
        Component renderer = (Component)lafDefaults.get(  | 
 | 
                BASELINE_COMPONENT_KEY);  | 
 | 
        if (renderer == null) { | 
 | 
            TreeCellRenderer tcr = createDefaultCellRenderer();  | 
 | 
            renderer = tcr.getTreeCellRendererComponent(  | 
 | 
                    tree, "a", false, false, false, -1, false);  | 
 | 
            lafDefaults.put(BASELINE_COMPONENT_KEY, renderer);  | 
 | 
        }  | 
 | 
        int rowHeight = tree.getRowHeight();  | 
 | 
        int baseline;  | 
 | 
        if (rowHeight > 0) { | 
 | 
            baseline = renderer.getBaseline(Integer.MAX_VALUE, rowHeight);  | 
 | 
        }  | 
 | 
        else { | 
 | 
            Dimension pref = renderer.getPreferredSize();  | 
 | 
            baseline = renderer.getBaseline(pref.width, pref.height);  | 
 | 
        }  | 
 | 
        return baseline + tree.getInsets().top;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Component.BaselineResizeBehavior getBaselineResizeBehavior(  | 
 | 
            JComponent c) { | 
 | 
        super.getBaselineResizeBehavior(c);  | 
 | 
        return Component.BaselineResizeBehavior.CONSTANT_ASCENT;  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Painting routines.  | 
 | 
    //  | 
 | 
 | 
 | 
    public void paint(Graphics g, JComponent c) { | 
 | 
        if (tree != c) { | 
 | 
            throw new InternalError("incorrect component"); | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        if(treeState == null) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        Rectangle        paintBounds = g.getClipBounds();  | 
 | 
        Insets           insets = tree.getInsets();  | 
 | 
        TreePath         initialPath = getClosestPathForLocation  | 
 | 
                                       (tree, 0, paintBounds.y);  | 
 | 
        Enumeration      paintingEnumerator = treeState.getVisiblePathsFrom  | 
 | 
                                              (initialPath);  | 
 | 
        int              row = treeState.getRowForPath(initialPath);  | 
 | 
        int              endY = paintBounds.y + paintBounds.height;  | 
 | 
 | 
 | 
        drawingCache.clear();  | 
 | 
 | 
 | 
        if(initialPath != null && paintingEnumerator != null) { | 
 | 
            TreePath   parentPath = initialPath;  | 
 | 
 | 
 | 
            // Draw the lines, knobs, and rows  | 
 | 
 | 
 | 
              | 
 | 
            parentPath = parentPath.getParentPath();  | 
 | 
            while(parentPath != null) { | 
 | 
                paintVerticalPartOfLeg(g, paintBounds, insets, parentPath);  | 
 | 
                drawingCache.put(parentPath, Boolean.TRUE);  | 
 | 
                parentPath = parentPath.getParentPath();  | 
 | 
            }  | 
 | 
 | 
 | 
            boolean         done = false;  | 
 | 
              | 
 | 
            boolean         isExpanded;  | 
 | 
            boolean         hasBeenExpanded;  | 
 | 
            boolean         isLeaf;  | 
 | 
            Rectangle       boundsBuffer = new Rectangle();  | 
 | 
            Rectangle       bounds;  | 
 | 
            TreePath        path;  | 
 | 
            boolean         rootVisible = isRootVisible();  | 
 | 
 | 
 | 
            while(!done && paintingEnumerator.hasMoreElements()) { | 
 | 
                path = (TreePath)paintingEnumerator.nextElement();  | 
 | 
                if(path != null) { | 
 | 
                    isLeaf = treeModel.isLeaf(path.getLastPathComponent());  | 
 | 
                    if(isLeaf)  | 
 | 
                        isExpanded = hasBeenExpanded = false;  | 
 | 
                    else { | 
 | 
                        isExpanded = treeState.getExpandedState(path);  | 
 | 
                        hasBeenExpanded = tree.hasBeenExpanded(path);  | 
 | 
                    }  | 
 | 
                    bounds = getPathBounds(path, insets, boundsBuffer);  | 
 | 
                    if(bounds == null)  | 
 | 
                        // This will only happen if the model changes out  | 
 | 
                        // from under us (usually in another thread).  | 
 | 
                        // Swing isn't multithreaded, but I'll put this  | 
 | 
                          | 
 | 
                        return;  | 
 | 
                      | 
 | 
                    parentPath = path.getParentPath();  | 
 | 
                    if(parentPath != null) { | 
 | 
                        if(drawingCache.get(parentPath) == null) { | 
 | 
                            paintVerticalPartOfLeg(g, paintBounds,  | 
 | 
                                                   insets, parentPath);  | 
 | 
                            drawingCache.put(parentPath, Boolean.TRUE);  | 
 | 
                        }  | 
 | 
                        paintHorizontalPartOfLeg(g, paintBounds, insets,  | 
 | 
                                                 bounds, path, row,  | 
 | 
                                                 isExpanded,  | 
 | 
                                                 hasBeenExpanded, isLeaf);  | 
 | 
                    }  | 
 | 
                    else if(rootVisible && row == 0) { | 
 | 
                        paintHorizontalPartOfLeg(g, paintBounds, insets,  | 
 | 
                                                 bounds, path, row,  | 
 | 
                                                 isExpanded,  | 
 | 
                                                 hasBeenExpanded, isLeaf);  | 
 | 
                    }  | 
 | 
                    if(shouldPaintExpandControl(path, row, isExpanded,  | 
 | 
                                                hasBeenExpanded, isLeaf)) { | 
 | 
                        paintExpandControl(g, paintBounds, insets, bounds,  | 
 | 
                                           path, row, isExpanded,  | 
 | 
                                           hasBeenExpanded, isLeaf);  | 
 | 
                    }  | 
 | 
                    paintRow(g, paintBounds, insets, bounds, path,  | 
 | 
                                 row, isExpanded, hasBeenExpanded, isLeaf);  | 
 | 
                    if((bounds.y + bounds.height) >= endY)  | 
 | 
                        done = true;  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    done = true;  | 
 | 
                }  | 
 | 
                row++;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        paintDropLine(g);  | 
 | 
 | 
 | 
          | 
 | 
        rendererPane.removeAll();  | 
 | 
 | 
 | 
        drawingCache.clear();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean isDropLine(JTree.DropLocation loc) { | 
 | 
        return loc != null && loc.getPath() != null && loc.getChildIndex() != -1;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void paintDropLine(Graphics g) { | 
 | 
        JTree.DropLocation loc = tree.getDropLocation();  | 
 | 
        if (!isDropLine(loc)) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        Color c = UIManager.getColor("Tree.dropLineColor"); | 
 | 
        if (c != null) { | 
 | 
            g.setColor(c);  | 
 | 
            Rectangle rect = getDropLineRect(loc);  | 
 | 
            g.fillRect(rect.x, rect.y, rect.width, rect.height);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected Rectangle getDropLineRect(JTree.DropLocation loc) { | 
 | 
        Rectangle rect;  | 
 | 
        TreePath path = loc.getPath();  | 
 | 
        int index = loc.getChildIndex();  | 
 | 
        boolean ltr = leftToRight;  | 
 | 
 | 
 | 
        Insets insets = tree.getInsets();  | 
 | 
 | 
 | 
        if (tree.getRowCount() == 0) { | 
 | 
            rect = new Rectangle(insets.left,  | 
 | 
                                 insets.top,  | 
 | 
                                 tree.getWidth() - insets.left - insets.right,  | 
 | 
                                 0);  | 
 | 
        } else { | 
 | 
            TreeModel model = getModel();  | 
 | 
            Object root = model.getRoot();  | 
 | 
 | 
 | 
            if (path.getLastPathComponent() == root  | 
 | 
                    && index >= model.getChildCount(root)) { | 
 | 
 | 
 | 
                rect = tree.getRowBounds(tree.getRowCount() - 1);  | 
 | 
                rect.y = rect.y + rect.height;  | 
 | 
                Rectangle xRect;  | 
 | 
 | 
 | 
                if (!tree.isRootVisible()) { | 
 | 
                    xRect = tree.getRowBounds(0);  | 
 | 
                } else if (model.getChildCount(root) == 0){ | 
 | 
                    xRect = tree.getRowBounds(0);  | 
 | 
                    xRect.x += totalChildIndent;  | 
 | 
                    xRect.width -= totalChildIndent + totalChildIndent;  | 
 | 
                } else { | 
 | 
                    TreePath lastChildPath = path.pathByAddingChild(  | 
 | 
                        model.getChild(root, model.getChildCount(root) - 1));  | 
 | 
                    xRect = tree.getPathBounds(lastChildPath);  | 
 | 
                }  | 
 | 
 | 
 | 
                rect.x = xRect.x;  | 
 | 
                rect.width = xRect.width;  | 
 | 
            } else { | 
 | 
                rect = tree.getPathBounds(path.pathByAddingChild(  | 
 | 
                    model.getChild(path.getLastPathComponent(), index)));  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        if (rect.y != 0) { | 
 | 
            rect.y--;  | 
 | 
        }  | 
 | 
 | 
 | 
        if (!ltr) { | 
 | 
            rect.x = rect.x + rect.width - 100;  | 
 | 
        }  | 
 | 
 | 
 | 
        rect.width = 100;  | 
 | 
        rect.height = 2;  | 
 | 
 | 
 | 
        return rect;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,  | 
 | 
                                            Insets insets, Rectangle bounds,  | 
 | 
                                            TreePath path, int row,  | 
 | 
                                            boolean isExpanded,  | 
 | 
                                            boolean hasBeenExpanded, boolean  | 
 | 
                                            isLeaf) { | 
 | 
        if (!paintLines) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        int depth = path.getPathCount() - 1;  | 
 | 
        if((depth == 0 || (depth == 1 && !isRootVisible())) &&  | 
 | 
           !getShowsRootHandles()) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        int clipLeft = clipBounds.x;  | 
 | 
        int clipRight = clipBounds.x + clipBounds.width;  | 
 | 
        int clipTop = clipBounds.y;  | 
 | 
        int clipBottom = clipBounds.y + clipBounds.height;  | 
 | 
        int lineY = bounds.y + bounds.height / 2;  | 
 | 
 | 
 | 
        if (leftToRight) { | 
 | 
            int leftX = bounds.x - getRightChildIndent();  | 
 | 
            int nodeX = bounds.x - getHorizontalLegBuffer();  | 
 | 
 | 
 | 
            if(lineY >= clipTop  | 
 | 
                    && lineY < clipBottom  | 
 | 
                    && nodeX >= clipLeft  | 
 | 
                    && leftX < clipRight  | 
 | 
                    && leftX < nodeX) { | 
 | 
 | 
 | 
                g.setColor(getHashColor());  | 
 | 
                paintHorizontalLine(g, tree, lineY, leftX, nodeX - 1);  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            int nodeX = bounds.x + bounds.width + getHorizontalLegBuffer();  | 
 | 
            int rightX = bounds.x + bounds.width + getRightChildIndent();  | 
 | 
 | 
 | 
            if(lineY >= clipTop  | 
 | 
                    && lineY < clipBottom  | 
 | 
                    && rightX >= clipLeft  | 
 | 
                    && nodeX < clipRight  | 
 | 
                    && nodeX < rightX) { | 
 | 
 | 
 | 
                g.setColor(getHashColor());  | 
 | 
                paintHorizontalLine(g, tree, lineY, nodeX, rightX - 1);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,  | 
 | 
                                          Insets insets, TreePath path) { | 
 | 
        if (!paintLines) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        int depth = path.getPathCount() - 1;  | 
 | 
        if (depth == 0 && !getShowsRootHandles() && !isRootVisible()) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
        int lineX = getRowX(-1, depth + 1);  | 
 | 
        if (leftToRight) { | 
 | 
            lineX = lineX - getRightChildIndent() + insets.left;  | 
 | 
        }  | 
 | 
        else { | 
 | 
            lineX = tree.getWidth() - lineX - insets.right +  | 
 | 
                    getRightChildIndent() - 1;  | 
 | 
        }  | 
 | 
        int clipLeft = clipBounds.x;  | 
 | 
        int clipRight = clipBounds.x + (clipBounds.width - 1);  | 
 | 
 | 
 | 
        if (lineX >= clipLeft && lineX <= clipRight) { | 
 | 
            int clipTop = clipBounds.y;  | 
 | 
            int clipBottom = clipBounds.y + clipBounds.height;  | 
 | 
            Rectangle parentBounds = getPathBounds(tree, path);  | 
 | 
            Rectangle lastChildBounds = getPathBounds(tree,  | 
 | 
                                                     getLastChildPath(path));  | 
 | 
 | 
 | 
            if(lastChildBounds == null)  | 
 | 
                // This shouldn't happen, but if the model is modified  | 
 | 
                // in another thread it is possible for this to happen.  | 
 | 
                // Swing isn't multithreaded, but I'll add this check in  | 
 | 
                  | 
 | 
                return;  | 
 | 
 | 
 | 
            int       top;  | 
 | 
 | 
 | 
            if(parentBounds == null) { | 
 | 
                top = Math.max(insets.top + getVerticalLegBuffer(),  | 
 | 
                               clipTop);  | 
 | 
            }  | 
 | 
            else  | 
 | 
                top = Math.max(parentBounds.y + parentBounds.height +  | 
 | 
                               getVerticalLegBuffer(), clipTop);  | 
 | 
            if(depth == 0 && !isRootVisible()) { | 
 | 
                TreeModel      model = getModel();  | 
 | 
 | 
 | 
                if(model != null) { | 
 | 
                    Object        root = model.getRoot();  | 
 | 
 | 
 | 
                    if(model.getChildCount(root) > 0) { | 
 | 
                        parentBounds = getPathBounds(tree, path.  | 
 | 
                                  pathByAddingChild(model.getChild(root, 0)));  | 
 | 
                        if(parentBounds != null)  | 
 | 
                            top = Math.max(insets.top + getVerticalLegBuffer(),  | 
 | 
                                           parentBounds.y +  | 
 | 
                                           parentBounds.height / 2);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            int bottom = Math.min(lastChildBounds.y +  | 
 | 
                                  (lastChildBounds.height / 2), clipBottom);  | 
 | 
 | 
 | 
            if (top <= bottom) { | 
 | 
                g.setColor(getHashColor());  | 
 | 
                paintVerticalLine(g, tree, lineX, top, bottom);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void paintExpandControl(Graphics g,  | 
 | 
                                      Rectangle clipBounds, Insets insets,  | 
 | 
                                      Rectangle bounds, TreePath path,  | 
 | 
                                      int row, boolean isExpanded,  | 
 | 
                                      boolean hasBeenExpanded,  | 
 | 
                                      boolean isLeaf) { | 
 | 
        Object       value = path.getLastPathComponent();  | 
 | 
 | 
 | 
        // Draw icons if not a leaf and either hasn't been loaded,  | 
 | 
          | 
 | 
        if (!isLeaf && (!hasBeenExpanded ||  | 
 | 
                        treeModel.getChildCount(value) > 0)) { | 
 | 
            int middleXOfKnob;  | 
 | 
            if (leftToRight) { | 
 | 
                middleXOfKnob = bounds.x - getRightChildIndent() + 1;  | 
 | 
            } else { | 
 | 
                middleXOfKnob = bounds.x + bounds.width + getRightChildIndent() - 1;  | 
 | 
            }  | 
 | 
            int middleYOfKnob = bounds.y + (bounds.height / 2);  | 
 | 
 | 
 | 
            if (isExpanded) { | 
 | 
                Icon expandedIcon = getExpandedIcon();  | 
 | 
                if(expandedIcon != null)  | 
 | 
                  drawCentered(tree, g, expandedIcon, middleXOfKnob,  | 
 | 
                               middleYOfKnob );  | 
 | 
            }  | 
 | 
            else { | 
 | 
                Icon collapsedIcon = getCollapsedIcon();  | 
 | 
                if(collapsedIcon != null)  | 
 | 
                  drawCentered(tree, g, collapsedIcon, middleXOfKnob,  | 
 | 
                               middleYOfKnob);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void paintRow(Graphics g, Rectangle clipBounds,  | 
 | 
                            Insets insets, Rectangle bounds, TreePath path,  | 
 | 
                            int row, boolean isExpanded,  | 
 | 
                            boolean hasBeenExpanded, boolean isLeaf) { | 
 | 
          | 
 | 
        if(editingComponent != null && editingRow == row)  | 
 | 
            return;  | 
 | 
 | 
 | 
        int leadIndex;  | 
 | 
 | 
 | 
        if(tree.hasFocus()) { | 
 | 
            leadIndex = getLeadSelectionRow();  | 
 | 
        }  | 
 | 
        else  | 
 | 
            leadIndex = -1;  | 
 | 
 | 
 | 
        Component component;  | 
 | 
 | 
 | 
        component = currentCellRenderer.getTreeCellRendererComponent  | 
 | 
                      (tree, path.getLastPathComponent(),  | 
 | 
                       tree.isRowSelected(row), isExpanded, isLeaf, row,  | 
 | 
                       (leadIndex == row));  | 
 | 
 | 
 | 
        rendererPane.paintComponent(g, component, tree, bounds.x, bounds.y,  | 
 | 
                                    bounds.width, bounds.height, true);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean shouldPaintExpandControl(TreePath path, int row,  | 
 | 
                                               boolean isExpanded,  | 
 | 
                                               boolean hasBeenExpanded,  | 
 | 
                                               boolean isLeaf) { | 
 | 
        if(isLeaf)  | 
 | 
            return false;  | 
 | 
 | 
 | 
        int              depth = path.getPathCount() - 1;  | 
 | 
 | 
 | 
        if((depth == 0 || (depth == 1 && !isRootVisible())) &&  | 
 | 
           !getShowsRootHandles())  | 
 | 
            return false;  | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,  | 
 | 
                                    int bottom) { | 
 | 
        if (lineTypeDashed) { | 
 | 
            drawDashedVerticalLine(g, x, top, bottom);  | 
 | 
        } else { | 
 | 
            g.drawLine(x, top, x, bottom);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void paintHorizontalLine(Graphics g, JComponent c, int y,  | 
 | 
                                      int left, int right) { | 
 | 
        if (lineTypeDashed) { | 
 | 
            drawDashedHorizontalLine(g, y, left, right);  | 
 | 
        } else { | 
 | 
            g.drawLine(left, y, right, y);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected int getVerticalLegBuffer() { | 
 | 
        return 0;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected int getHorizontalLegBuffer() { | 
 | 
        return 0;  | 
 | 
    }  | 
 | 
 | 
 | 
    private int findCenteredX(int x, int iconWidth) { | 
 | 
        return leftToRight  | 
 | 
               ? x - (int)Math.ceil(iconWidth / 2.0)  | 
 | 
               : x - (int)Math.floor(iconWidth / 2.0);  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Generic painting methods  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
    protected void drawCentered(Component c, Graphics graphics, Icon icon,  | 
 | 
                                int x, int y) { | 
 | 
        icon.paintIcon(c, graphics,  | 
 | 
                      findCenteredX(x, icon.getIconWidth()),  | 
 | 
                      y - icon.getIconHeight() / 2);  | 
 | 
    }  | 
 | 
 | 
 | 
    // This method is slow -- revisit when Java2D is ready.  | 
 | 
      | 
 | 
    protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2){ | 
 | 
        // Drawing only even coordinates helps join line segments so they  | 
 | 
        // appear as one line.  This can be defeated by translating the  | 
 | 
          | 
 | 
        x1 += (x1 % 2);  | 
 | 
 | 
 | 
        for (int x = x1; x <= x2; x+=2) { | 
 | 
            g.drawLine(x, y, x, y);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    // This method is slow -- revisit when Java2D is ready.  | 
 | 
      | 
 | 
    protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2) { | 
 | 
        // Drawing only even coordinates helps join line segments so they  | 
 | 
        // appear as one line.  This can be defeated by translating the  | 
 | 
          | 
 | 
        y1 += (y1 % 2);  | 
 | 
 | 
 | 
        for (int y = y1; y <= y2; y+=2) { | 
 | 
            g.drawLine(x, y, x, y);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Various local methods  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected int getRowX(int row, int depth) { | 
 | 
        return totalChildIndent * (depth + depthOffset);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void updateLayoutCacheExpandedNodes() { | 
 | 
        if(treeModel != null && treeModel.getRoot() != null)  | 
 | 
            updateExpandedDescendants(new TreePath(treeModel.getRoot()));  | 
 | 
    }  | 
 | 
 | 
 | 
    private void updateLayoutCacheExpandedNodesIfNecessary() { | 
 | 
        if (treeModel != null && treeModel.getRoot() != null) { | 
 | 
            TreePath rootPath = new TreePath(treeModel.getRoot());  | 
 | 
            if (tree.isExpanded(rootPath)) { | 
 | 
                updateLayoutCacheExpandedNodes();  | 
 | 
            } else { | 
 | 
                treeState.setExpandedState(rootPath, false);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void updateExpandedDescendants(TreePath path) { | 
 | 
        completeEditing();  | 
 | 
        if(treeState != null) { | 
 | 
            treeState.setExpandedState(path, true);  | 
 | 
 | 
 | 
            Enumeration   descendants = tree.getExpandedDescendants(path);  | 
 | 
 | 
 | 
            if(descendants != null) { | 
 | 
                while(descendants.hasMoreElements()) { | 
 | 
                    path = (TreePath)descendants.nextElement();  | 
 | 
                    treeState.setExpandedState(path, true);  | 
 | 
                }  | 
 | 
            }  | 
 | 
            updateLeadSelectionRow();  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected TreePath getLastChildPath(TreePath parent) { | 
 | 
        if(treeModel != null) { | 
 | 
            int         childCount = treeModel.getChildCount  | 
 | 
                (parent.getLastPathComponent());  | 
 | 
 | 
 | 
            if(childCount > 0)  | 
 | 
                return parent.pathByAddingChild(treeModel.getChild  | 
 | 
                           (parent.getLastPathComponent(), childCount - 1));  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void updateDepthOffset() { | 
 | 
        if(isRootVisible()) { | 
 | 
            if(getShowsRootHandles())  | 
 | 
                depthOffset = 1;  | 
 | 
            else  | 
 | 
                depthOffset = 0;  | 
 | 
        }  | 
 | 
        else if(!getShowsRootHandles())  | 
 | 
            depthOffset = -1;  | 
 | 
        else  | 
 | 
            depthOffset = 0;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    protected void updateCellEditor() { | 
 | 
        TreeCellEditor        newEditor;  | 
 | 
 | 
 | 
        completeEditing();  | 
 | 
        if(tree == null)  | 
 | 
            newEditor = null;  | 
 | 
        else { | 
 | 
            if(tree.isEditable()) { | 
 | 
                newEditor = tree.getCellEditor();  | 
 | 
                if(newEditor == null) { | 
 | 
                    newEditor = createDefaultCellEditor();  | 
 | 
                    if(newEditor != null) { | 
 | 
                        tree.setCellEditor(newEditor);  | 
 | 
                        createdCellEditor = true;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
            else  | 
 | 
                newEditor = null;  | 
 | 
        }  | 
 | 
        if(newEditor != cellEditor) { | 
 | 
            if(cellEditor != null && cellEditorListener != null)  | 
 | 
                cellEditor.removeCellEditorListener(cellEditorListener);  | 
 | 
            cellEditor = newEditor;  | 
 | 
            if(cellEditorListener == null)  | 
 | 
                cellEditorListener = createCellEditorListener();  | 
 | 
            if(newEditor != null && cellEditorListener != null)  | 
 | 
                newEditor.addCellEditorListener(cellEditorListener);  | 
 | 
            createdCellEditor = false;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    protected void updateRenderer() { | 
 | 
        if(tree != null) { | 
 | 
            TreeCellRenderer      newCellRenderer;  | 
 | 
 | 
 | 
            newCellRenderer = tree.getCellRenderer();  | 
 | 
            if(newCellRenderer == null) { | 
 | 
                tree.setCellRenderer(createDefaultCellRenderer());  | 
 | 
                createdRenderer = true;  | 
 | 
            }  | 
 | 
            else { | 
 | 
                createdRenderer = false;  | 
 | 
                currentCellRenderer = newCellRenderer;  | 
 | 
                if(createdCellEditor) { | 
 | 
                    tree.setCellEditor(null);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        else { | 
 | 
            createdRenderer = false;  | 
 | 
            currentCellRenderer = null;  | 
 | 
        }  | 
 | 
        updateCellEditor();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void configureLayoutCache() { | 
 | 
        if(treeState != null && tree != null) { | 
 | 
            if(nodeDimensions == null)  | 
 | 
                nodeDimensions = createNodeDimensions();  | 
 | 
            treeState.setNodeDimensions(nodeDimensions);  | 
 | 
            treeState.setRootVisible(tree.isRootVisible());  | 
 | 
            treeState.setRowHeight(tree.getRowHeight());  | 
 | 
            treeState.setSelectionModel(getSelectionModel());  | 
 | 
            // Only do this if necessary, may loss state if call with  | 
 | 
              | 
 | 
            if(treeState.getModel() != tree.getModel())  | 
 | 
                treeState.setModel(tree.getModel());  | 
 | 
            updateLayoutCacheExpandedNodesIfNecessary();  | 
 | 
            // Create a listener to update preferred size when bounds  | 
 | 
              | 
 | 
            if(isLargeModel()) { | 
 | 
                if(componentListener == null) { | 
 | 
                    componentListener = createComponentListener();  | 
 | 
                    if(componentListener != null)  | 
 | 
                        tree.addComponentListener(componentListener);  | 
 | 
                }  | 
 | 
            }  | 
 | 
            else if(componentListener != null) { | 
 | 
                tree.removeComponentListener(componentListener);  | 
 | 
                componentListener = null;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        else if(componentListener != null) { | 
 | 
            tree.removeComponentListener(componentListener);  | 
 | 
            componentListener = null;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void updateSize() { | 
 | 
        validCachedPreferredSize = false;  | 
 | 
        tree.treeDidChange();  | 
 | 
    }  | 
 | 
 | 
 | 
    private void updateSize0() { | 
 | 
        validCachedPreferredSize = false;  | 
 | 
        tree.revalidate();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void updateCachedPreferredSize() { | 
 | 
        if(treeState != null) { | 
 | 
            Insets               i = tree.getInsets();  | 
 | 
 | 
 | 
            if(isLargeModel()) { | 
 | 
                Rectangle            visRect = tree.getVisibleRect();  | 
 | 
 | 
 | 
                if (visRect.x == 0 && visRect.y == 0 &&  | 
 | 
                        visRect.width == 0 && visRect.height == 0 &&  | 
 | 
                        tree.getVisibleRowCount() > 0) { | 
 | 
                    // The tree doesn't have a valid bounds yet. Calculate  | 
 | 
                      | 
 | 
                    visRect.width = 1;  | 
 | 
                    visRect.height = tree.getRowHeight() *  | 
 | 
                            tree.getVisibleRowCount();  | 
 | 
                } else { | 
 | 
                    visRect.x -= i.left;  | 
 | 
                    visRect.y -= i.top;  | 
 | 
                }  | 
 | 
                  | 
 | 
                Component component = SwingUtilities.getUnwrappedParent(tree);  | 
 | 
                if (component instanceof JViewport) { | 
 | 
                    component = component.getParent();  | 
 | 
                    if (component instanceof JScrollPane) { | 
 | 
                        JScrollPane pane = (JScrollPane) component;  | 
 | 
                        JScrollBar bar = pane.getHorizontalScrollBar();  | 
 | 
                        if ((bar != null) && bar.isVisible()) { | 
 | 
                            int height = bar.getHeight();  | 
 | 
                            visRect.y -= height;  | 
 | 
                            visRect.height += height;  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                preferredSize.width = treeState.getPreferredWidth(visRect);  | 
 | 
            }  | 
 | 
            else { | 
 | 
                preferredSize.width = treeState.getPreferredWidth(null);  | 
 | 
            }  | 
 | 
            preferredSize.height = treeState.getPreferredHeight();  | 
 | 
            preferredSize.width += i.left + i.right;  | 
 | 
            preferredSize.height += i.top + i.bottom;  | 
 | 
        }  | 
 | 
        validCachedPreferredSize = true;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    protected void pathWasExpanded(TreePath path) { | 
 | 
        if(tree != null) { | 
 | 
            tree.fireTreeExpanded(path);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    protected void pathWasCollapsed(TreePath path) { | 
 | 
        if(tree != null) { | 
 | 
            tree.fireTreeCollapsed(path);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    protected void ensureRowsAreVisible(int beginRow, int endRow) { | 
 | 
        if(tree != null && beginRow >= 0 && endRow < getRowCount(tree)) { | 
 | 
            boolean scrollVert = DefaultLookup.getBoolean(tree, this,  | 
 | 
                              "Tree.scrollsHorizontallyAndVertically", false);  | 
 | 
            if(beginRow == endRow) { | 
 | 
                Rectangle     scrollBounds = getPathBounds(tree, getPathForRow  | 
 | 
                                                           (tree, beginRow));  | 
 | 
 | 
 | 
                if(scrollBounds != null) { | 
 | 
                    if (!scrollVert) { | 
 | 
                        scrollBounds.x = tree.getVisibleRect().x;  | 
 | 
                        scrollBounds.width = 1;  | 
 | 
                    }  | 
 | 
                    tree.scrollRectToVisible(scrollBounds);  | 
 | 
                }  | 
 | 
            }  | 
 | 
            else { | 
 | 
                Rectangle   beginRect = getPathBounds(tree, getPathForRow  | 
 | 
                                                      (tree, beginRow));  | 
 | 
                if (beginRect != null) { | 
 | 
                    Rectangle   visRect = tree.getVisibleRect();  | 
 | 
                    Rectangle   testRect = beginRect;  | 
 | 
                    int         beginY = beginRect.y;  | 
 | 
                    int         maxY = beginY + visRect.height;  | 
 | 
 | 
 | 
                    for(int counter = beginRow + 1; counter <= endRow; counter++) { | 
 | 
                            testRect = getPathBounds(tree,  | 
 | 
                                    getPathForRow(tree, counter));  | 
 | 
                        if (testRect == null) { | 
 | 
                            return;  | 
 | 
                        }  | 
 | 
                        if((testRect.y + testRect.height) > maxY)  | 
 | 
                                counter = endRow;  | 
 | 
                            }  | 
 | 
                        tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1,  | 
 | 
                                                      testRect.y + testRect.height-  | 
 | 
                                                      beginY));  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
      */  | 
 | 
    public void setPreferredMinSize(Dimension newSize) { | 
 | 
        preferredMinSize = newSize;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
      */  | 
 | 
    public Dimension getPreferredMinSize() { | 
 | 
        if(preferredMinSize == null)  | 
 | 
            return null;  | 
 | 
        return new Dimension(preferredMinSize);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    public Dimension getPreferredSize(JComponent c) { | 
 | 
        return getPreferredSize(c, true);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public Dimension getPreferredSize(JComponent c,  | 
 | 
                                      boolean checkConsistency) { | 
 | 
        Dimension       pSize = this.getPreferredMinSize();  | 
 | 
 | 
 | 
        if(!validCachedPreferredSize)  | 
 | 
            updateCachedPreferredSize();  | 
 | 
        if(tree != null) { | 
 | 
            if(pSize != null)  | 
 | 
                return new Dimension(Math.max(pSize.width,  | 
 | 
                                              preferredSize.width),  | 
 | 
                              Math.max(pSize.height, preferredSize.height));  | 
 | 
            return new Dimension(preferredSize.width, preferredSize.height);  | 
 | 
        }  | 
 | 
        else if(pSize != null)  | 
 | 
            return pSize;  | 
 | 
        else  | 
 | 
            return new Dimension(0, 0);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public Dimension getMinimumSize(JComponent c) { | 
 | 
        if(this.getPreferredMinSize() != null)  | 
 | 
            return this.getPreferredMinSize();  | 
 | 
        return new Dimension(0, 0);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public Dimension getMaximumSize(JComponent c) { | 
 | 
        if(tree != null)  | 
 | 
            return getPreferredSize(tree);  | 
 | 
        if(this.getPreferredMinSize() != null)  | 
 | 
            return this.getPreferredMinSize();  | 
 | 
        return new Dimension(0, 0);  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void completeEditing() { | 
 | 
          | 
 | 
        if(tree.getInvokesStopCellEditing() &&  | 
 | 
           stopEditingInCompleteEditing && editingComponent != null) { | 
 | 
            cellEditor.stopCellEditing();  | 
 | 
        }  | 
 | 
          | 
 | 
           was successful. */  | 
 | 
        completeEditing(false, true, false);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    protected void completeEditing(boolean messageStop,  | 
 | 
                                   boolean messageCancel,  | 
 | 
                                   boolean messageTree) { | 
 | 
        if(stopEditingInCompleteEditing && editingComponent != null) { | 
 | 
            Component             oldComponent = editingComponent;  | 
 | 
            TreePath              oldPath = editingPath;  | 
 | 
            TreeCellEditor        oldEditor = cellEditor;  | 
 | 
            Object                newValue = oldEditor.getCellEditorValue();  | 
 | 
            Rectangle             editingBounds = getPathBounds(tree,  | 
 | 
                                                                editingPath);  | 
 | 
            boolean               requestFocus = (tree != null &&  | 
 | 
                                   (tree.hasFocus() || SwingUtilities.  | 
 | 
                                    findFocusOwner(editingComponent) != null));  | 
 | 
 | 
 | 
            editingComponent = null;  | 
 | 
            editingPath = null;  | 
 | 
            if(messageStop)  | 
 | 
                oldEditor.stopCellEditing();  | 
 | 
            else if(messageCancel)  | 
 | 
                oldEditor.cancelCellEditing();  | 
 | 
            tree.remove(oldComponent);  | 
 | 
            if(editorHasDifferentSize) { | 
 | 
                treeState.invalidatePathBounds(oldPath);  | 
 | 
                updateSize();  | 
 | 
            }  | 
 | 
            else if (editingBounds != null) { | 
 | 
                editingBounds.x = 0;  | 
 | 
                editingBounds.width = tree.getSize().width;  | 
 | 
                tree.repaint(editingBounds);  | 
 | 
            }  | 
 | 
            if(requestFocus)  | 
 | 
                tree.requestFocus();  | 
 | 
            if(messageTree)  | 
 | 
                treeModel.valueForPathChanged(oldPath, newValue);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    // cover method for startEditing that allows us to pass extra  | 
 | 
      | 
 | 
    private boolean startEditingOnRelease(TreePath path,  | 
 | 
                                          MouseEvent event,  | 
 | 
                                          MouseEvent releaseEvent) { | 
 | 
        this.releaseEvent = releaseEvent;  | 
 | 
        try { | 
 | 
            return startEditing(path, event);  | 
 | 
        } finally { | 
 | 
            this.releaseEvent = null;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    protected boolean startEditing(TreePath path, MouseEvent event) { | 
 | 
        if (isEditing(tree) && tree.getInvokesStopCellEditing() &&  | 
 | 
                               !stopEditing(tree)) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
        completeEditing();  | 
 | 
        if(cellEditor != null && tree.isPathEditable(path)) { | 
 | 
            int           row = getRowForPath(tree, path);  | 
 | 
 | 
 | 
            if(cellEditor.isCellEditable(event)) { | 
 | 
                editingComponent = cellEditor.getTreeCellEditorComponent  | 
 | 
                      (tree, path.getLastPathComponent(),  | 
 | 
                       tree.isPathSelected(path), tree.isExpanded(path),  | 
 | 
                       treeModel.isLeaf(path.getLastPathComponent()), row);  | 
 | 
                Rectangle           nodeBounds = getPathBounds(tree, path);  | 
 | 
                if (nodeBounds == null) { | 
 | 
                    return false;  | 
 | 
                }  | 
 | 
 | 
 | 
                editingRow = row;  | 
 | 
 | 
 | 
                Dimension editorSize = editingComponent.getPreferredSize();  | 
 | 
 | 
 | 
                  | 
 | 
                if(editorSize.height != nodeBounds.height &&  | 
 | 
                   getRowHeight() > 0)  | 
 | 
                    editorSize.height = getRowHeight();  | 
 | 
 | 
 | 
                if(editorSize.width != nodeBounds.width ||  | 
 | 
                   editorSize.height != nodeBounds.height) { | 
 | 
                    // Editor wants different width or height, invalidate  | 
 | 
                      | 
 | 
                    editorHasDifferentSize = true;  | 
 | 
                    treeState.invalidatePathBounds(path);  | 
 | 
                    updateSize();  | 
 | 
                    // To make sure x/y are updated correctly, fetch  | 
 | 
                      | 
 | 
                    nodeBounds = getPathBounds(tree, path);  | 
 | 
                    if (nodeBounds == null) { | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                else  | 
 | 
                    editorHasDifferentSize = false;  | 
 | 
                tree.add(editingComponent);  | 
 | 
                editingComponent.setBounds(nodeBounds.x, nodeBounds.y,  | 
 | 
                                           nodeBounds.width,  | 
 | 
                                           nodeBounds.height);  | 
 | 
                editingPath = path;  | 
 | 
                AWTAccessor.getComponentAccessor().revalidateSynchronously(editingComponent);  | 
 | 
                editingComponent.repaint();  | 
 | 
                if(cellEditor.shouldSelectCell(event)) { | 
 | 
                    stopEditingInCompleteEditing = false;  | 
 | 
                    tree.setSelectionRow(row);  | 
 | 
                    stopEditingInCompleteEditing = true;  | 
 | 
                }  | 
 | 
 | 
 | 
                Component focusedComponent = SwingUtilities2.  | 
 | 
                                 compositeRequestFocus(editingComponent);  | 
 | 
                boolean selectAll = true;  | 
 | 
 | 
 | 
                if(event != null) { | 
 | 
                      | 
 | 
                       mouse events until mouseReleased. */  | 
 | 
                    Point          componentPoint = SwingUtilities.convertPoint  | 
 | 
                        (tree, new Point(event.getX(), event.getY()),  | 
 | 
                         editingComponent);  | 
 | 
 | 
 | 
                    /* Create an instance of BasicTreeMouseListener to handle  | 
 | 
                       passing the mouse/motion events to the necessary  | 
 | 
                       component. */  | 
 | 
                    // We really want similar behavior to getMouseEventTarget,  | 
 | 
                      | 
 | 
                    Component activeComponent = SwingUtilities.  | 
 | 
                                    getDeepestComponentAt(editingComponent,  | 
 | 
                                       componentPoint.x, componentPoint.y);  | 
 | 
                    if (activeComponent != null) { | 
 | 
                        MouseInputHandler handler =  | 
 | 
                            new MouseInputHandler(tree, activeComponent,  | 
 | 
                                                  event, focusedComponent);  | 
 | 
 | 
 | 
                        if (releaseEvent != null) { | 
 | 
                            handler.mouseReleased(releaseEvent);  | 
 | 
                        }  | 
 | 
 | 
 | 
                        selectAll = false;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                if (selectAll && focusedComponent instanceof JTextField) { | 
 | 
                    ((JTextField)focusedComponent).selectAll();  | 
 | 
                }  | 
 | 
                return true;  | 
 | 
            }  | 
 | 
            else  | 
 | 
                editingComponent = null;  | 
 | 
        }  | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // Following are primarily for handling mouse events.  | 
 | 
    //  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void checkForClickInExpandControl(TreePath path,  | 
 | 
                                                int mouseX, int mouseY) { | 
 | 
      if (isLocationInExpandControl(path, mouseX, mouseY)) { | 
 | 
          handleExpandControlClick(path, mouseX, mouseY);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean isLocationInExpandControl(TreePath path,  | 
 | 
                                                int mouseX, int mouseY) { | 
 | 
        if(path != null && !treeModel.isLeaf(path.getLastPathComponent())){ | 
 | 
            int                     boxWidth;  | 
 | 
            Insets                  i = tree.getInsets();  | 
 | 
 | 
 | 
            if(getExpandedIcon() != null)  | 
 | 
                boxWidth = getExpandedIcon().getIconWidth();  | 
 | 
            else  | 
 | 
                boxWidth = 8;  | 
 | 
 | 
 | 
            int boxLeftX = getRowX(tree.getRowForPath(path),  | 
 | 
                                   path.getPathCount() - 1);  | 
 | 
 | 
 | 
            if (leftToRight) { | 
 | 
                boxLeftX = boxLeftX + i.left - getRightChildIndent() + 1;  | 
 | 
            } else { | 
 | 
                boxLeftX = tree.getWidth() - boxLeftX - i.right + getRightChildIndent() - 1;  | 
 | 
            }  | 
 | 
 | 
 | 
            boxLeftX = findCenteredX(boxLeftX, boxWidth);  | 
 | 
 | 
 | 
            return (mouseX >= boxLeftX && mouseX < (boxLeftX + boxWidth));  | 
 | 
        }  | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void handleExpandControlClick(TreePath path, int mouseX,  | 
 | 
                                            int mouseY) { | 
 | 
        toggleExpandState(path);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void toggleExpandState(TreePath path) { | 
 | 
        if(!tree.isExpanded(path)) { | 
 | 
            int       row = getRowForPath(tree, path);  | 
 | 
 | 
 | 
            tree.expandPath(path);  | 
 | 
            updateSize();  | 
 | 
            if(row != -1) { | 
 | 
                if(tree.getScrollsOnExpand())  | 
 | 
                    ensureRowsAreVisible(row, row + treeState.  | 
 | 
                                         getVisibleChildCount(path));  | 
 | 
                else  | 
 | 
                    ensureRowsAreVisible(row, row);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        else { | 
 | 
            tree.collapsePath(path);  | 
 | 
            updateSize();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean isToggleSelectionEvent(MouseEvent event) { | 
 | 
        return (SwingUtilities.isLeftMouseButton(event) &&  | 
 | 
                BasicGraphicsUtils.isMenuShortcutKeyDown(event));  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean isMultiSelectEvent(MouseEvent event) { | 
 | 
        return (SwingUtilities.isLeftMouseButton(event) &&  | 
 | 
                event.isShiftDown());  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean isToggleEvent(MouseEvent event) { | 
 | 
        if(!SwingUtilities.isLeftMouseButton(event)) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
        int           clickCount = tree.getToggleClickCount();  | 
 | 
 | 
 | 
        if(clickCount <= 0) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
        return ((event.getClickCount() % clickCount) == 0);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void selectPathForEvent(TreePath path, MouseEvent event) { | 
 | 
          | 
 | 
        if(isMultiSelectEvent(event)) { | 
 | 
            TreePath    anchor = getAnchorSelectionPath();  | 
 | 
            int         anchorRow = (anchor == null) ? -1 :  | 
 | 
                                    getRowForPath(tree, anchor);  | 
 | 
 | 
 | 
            if(anchorRow == -1 || tree.getSelectionModel().  | 
 | 
                      getSelectionMode() == TreeSelectionModel.  | 
 | 
                      SINGLE_TREE_SELECTION) { | 
 | 
                tree.setSelectionPath(path);  | 
 | 
            }  | 
 | 
            else { | 
 | 
                int          row = getRowForPath(tree, path);  | 
 | 
                TreePath     lastAnchorPath = anchor;  | 
 | 
 | 
 | 
                if (isToggleSelectionEvent(event)) { | 
 | 
                    if (tree.isRowSelected(anchorRow)) { | 
 | 
                        tree.addSelectionInterval(anchorRow, row);  | 
 | 
                    } else { | 
 | 
                        tree.removeSelectionInterval(anchorRow, row);  | 
 | 
                        tree.addSelectionInterval(row, row);  | 
 | 
                    }  | 
 | 
                } else if(row < anchorRow) { | 
 | 
                    tree.setSelectionInterval(row, anchorRow);  | 
 | 
                } else { | 
 | 
                    tree.setSelectionInterval(anchorRow, row);  | 
 | 
                }  | 
 | 
                lastSelectedRow = row;  | 
 | 
                setAnchorSelectionPath(lastAnchorPath);  | 
 | 
                setLeadSelectionPath(path);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        // Should this event toggle the selection of this row?  | 
 | 
          | 
 | 
        else if(isToggleSelectionEvent(event)) { | 
 | 
            if(tree.isPathSelected(path))  | 
 | 
                tree.removeSelectionPath(path);  | 
 | 
            else  | 
 | 
                tree.addSelectionPath(path);  | 
 | 
            lastSelectedRow = getRowForPath(tree, path);  | 
 | 
            setAnchorSelectionPath(path);  | 
 | 
            setLeadSelectionPath(path);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        else if(SwingUtilities.isLeftMouseButton(event)) { | 
 | 
            tree.setSelectionPath(path);  | 
 | 
            if(isToggleEvent(event)) { | 
 | 
                toggleExpandState(path);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean isLeaf(int row) { | 
 | 
        TreePath          path = getPathForRow(tree, row);  | 
 | 
 | 
 | 
        if(path != null)  | 
 | 
            return treeModel.isLeaf(path.getLastPathComponent());  | 
 | 
          | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
    //  | 
 | 
    // The following selection methods (lead/anchor) are covers for the  | 
 | 
    // methods in JTree.  | 
 | 
      | 
 | 
    private void setAnchorSelectionPath(TreePath newPath) { | 
 | 
        ignoreLAChange = true;  | 
 | 
        try { | 
 | 
            tree.setAnchorSelectionPath(newPath);  | 
 | 
        } finally{ | 
 | 
            ignoreLAChange = false;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private TreePath getAnchorSelectionPath() { | 
 | 
        return tree.getAnchorSelectionPath();  | 
 | 
    }  | 
 | 
 | 
 | 
    private void setLeadSelectionPath(TreePath newPath) { | 
 | 
        setLeadSelectionPath(newPath, false);  | 
 | 
    }  | 
 | 
 | 
 | 
    private void setLeadSelectionPath(TreePath newPath, boolean repaint) { | 
 | 
        Rectangle       bounds = repaint ?  | 
 | 
                            getPathBounds(tree, getLeadSelectionPath()) : null;  | 
 | 
 | 
 | 
        ignoreLAChange = true;  | 
 | 
        try { | 
 | 
            tree.setLeadSelectionPath(newPath);  | 
 | 
        } finally { | 
 | 
            ignoreLAChange = false;  | 
 | 
        }  | 
 | 
        leadRow = getRowForPath(tree, newPath);  | 
 | 
 | 
 | 
        if (repaint) { | 
 | 
            if (bounds != null) { | 
 | 
                tree.repaint(getRepaintPathBounds(bounds));  | 
 | 
            }  | 
 | 
            bounds = getPathBounds(tree, newPath);  | 
 | 
            if (bounds != null) { | 
 | 
                tree.repaint(getRepaintPathBounds(bounds));  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private Rectangle getRepaintPathBounds(Rectangle bounds) { | 
 | 
        if (UIManager.getBoolean("Tree.repaintWholeRow")) { | 
 | 
           bounds.x = 0;  | 
 | 
           bounds.width = tree.getWidth();  | 
 | 
        }  | 
 | 
        return bounds;  | 
 | 
    }  | 
 | 
 | 
 | 
    private TreePath getLeadSelectionPath() { | 
 | 
        return tree.getLeadSelectionPath();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void updateLeadSelectionRow() { | 
 | 
        leadRow = getRowForPath(tree, getLeadSelectionPath());  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected int getLeadSelectionRow() { | 
 | 
        return leadRow;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void extendSelection(TreePath newLead) { | 
 | 
        TreePath           aPath = getAnchorSelectionPath();  | 
 | 
        int                aRow = (aPath == null) ? -1 :  | 
 | 
                                  getRowForPath(tree, aPath);  | 
 | 
        int                newIndex = getRowForPath(tree, newLead);  | 
 | 
 | 
 | 
        if(aRow == -1) { | 
 | 
            tree.setSelectionRow(newIndex);  | 
 | 
        }  | 
 | 
        else { | 
 | 
            if(aRow < newIndex) { | 
 | 
                tree.setSelectionInterval(aRow, newIndex);  | 
 | 
            }  | 
 | 
            else { | 
 | 
                tree.setSelectionInterval(newIndex, aRow);  | 
 | 
            }  | 
 | 
            setAnchorSelectionPath(aPath);  | 
 | 
            setLeadSelectionPath(newLead);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void repaintPath(TreePath path) { | 
 | 
        if (path != null) { | 
 | 
            Rectangle bounds = getPathBounds(tree, path);  | 
 | 
            if (bounds != null) { | 
 | 
                tree.repaint(bounds.x, bounds.y, bounds.width, bounds.height);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public class TreeExpansionHandler implements TreeExpansionListener { | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        public void treeExpanded(TreeExpansionEvent event) { | 
 | 
            getHandler().treeExpanded(event);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        public void treeCollapsed(TreeExpansionEvent event) { | 
 | 
            getHandler().treeCollapsed(event);  | 
 | 
        }  | 
 | 
    } // BasicTreeUI.TreeExpansionHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public class ComponentHandler extends ComponentAdapter implements  | 
 | 
                 ActionListener { | 
 | 
          | 
 | 
         * adjusting. */  | 
 | 
        protected Timer                timer;  | 
 | 
          | 
 | 
        protected JScrollBar           scrollBar;  | 
 | 
 | 
 | 
        public void componentMoved(ComponentEvent e) { | 
 | 
            if(timer == null) { | 
 | 
                JScrollPane   scrollPane = getScrollPane();  | 
 | 
 | 
 | 
                if(scrollPane == null)  | 
 | 
                    updateSize();  | 
 | 
                else { | 
 | 
                    scrollBar = scrollPane.getVerticalScrollBar();  | 
 | 
                    if(scrollBar == null ||  | 
 | 
                        !scrollBar.getValueIsAdjusting()) { | 
 | 
                          | 
 | 
                        if((scrollBar = scrollPane.getHorizontalScrollBar())  | 
 | 
                            != null && scrollBar.getValueIsAdjusting())  | 
 | 
                            startTimer();  | 
 | 
                        else  | 
 | 
                            updateSize();  | 
 | 
                    }  | 
 | 
                    else  | 
 | 
                        startTimer();  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        protected void startTimer() { | 
 | 
            if(timer == null) { | 
 | 
                timer = new Timer(200, this);  | 
 | 
                timer.setRepeats(true);  | 
 | 
            }  | 
 | 
            timer.start();  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        protected JScrollPane getScrollPane() { | 
 | 
            Component       c = tree.getParent();  | 
 | 
 | 
 | 
            while(c != null && !(c instanceof JScrollPane))  | 
 | 
                c = c.getParent();  | 
 | 
            if(c instanceof JScrollPane)  | 
 | 
                return (JScrollPane)c;  | 
 | 
            return null;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void actionPerformed(ActionEvent ae) { | 
 | 
            if(scrollBar == null || !scrollBar.getValueIsAdjusting()) { | 
 | 
                if(timer != null)  | 
 | 
                    timer.stop();  | 
 | 
                updateSize();  | 
 | 
                timer = null;  | 
 | 
                scrollBar = null;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    } // End of BasicTreeUI.ComponentHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public class TreeModelHandler implements TreeModelListener { | 
 | 
 | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
        public void treeNodesChanged(TreeModelEvent e) { | 
 | 
            getHandler().treeNodesChanged(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        public void treeNodesInserted(TreeModelEvent e) { | 
 | 
            getHandler().treeNodesInserted(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        public void treeNodesRemoved(TreeModelEvent e) { | 
 | 
            getHandler().treeNodesRemoved(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        public void treeStructureChanged(TreeModelEvent e) { | 
 | 
            getHandler().treeStructureChanged(e);  | 
 | 
        }  | 
 | 
    } // End of BasicTreeUI.TreeModelHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public class TreeSelectionHandler implements TreeSelectionListener { | 
 | 
 | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void valueChanged(TreeSelectionEvent event) { | 
 | 
            getHandler().valueChanged(event);  | 
 | 
        }  | 
 | 
    }// End of BasicTreeUI.TreeSelectionHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public class CellEditorHandler implements CellEditorListener { | 
 | 
 | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
          | 
 | 
        public void editingStopped(ChangeEvent e) { | 
 | 
            getHandler().editingStopped(e);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        public void editingCanceled(ChangeEvent e) { | 
 | 
            getHandler().editingCanceled(e);  | 
 | 
        }  | 
 | 
    } // BasicTreeUI.CellEditorHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public class KeyHandler extends KeyAdapter { | 
 | 
 | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
        // Also note these fields aren't use anymore, nor does Handler have  | 
 | 
        // the old functionality. This behavior worked around an old bug  | 
 | 
        // in JComponent that has long since been fixed.  | 
 | 
 | 
 | 
          | 
 | 
        protected Action              repeatKeyAction;  | 
 | 
 | 
 | 
          | 
 | 
        protected boolean            isKeyDown;  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void keyTyped(KeyEvent e) { | 
 | 
            getHandler().keyTyped(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        public void keyPressed(KeyEvent e) { | 
 | 
            getHandler().keyPressed(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        public void keyReleased(KeyEvent e) { | 
 | 
            getHandler().keyReleased(e);  | 
 | 
        }  | 
 | 
    } // End of BasicTreeUI.KeyHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public class FocusHandler implements FocusListener { | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void focusGained(FocusEvent e) { | 
 | 
            getHandler().focusGained(e);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void focusLost(FocusEvent e) { | 
 | 
            getHandler().focusLost(e);  | 
 | 
        }  | 
 | 
    } // End of class BasicTreeUI.FocusHandler  | 
 | 
 | 
 | 
 | 
 | 
    /**  | 
 | 
     * Class responsible for getting size of node, method is forwarded  | 
 | 
     * to BasicTreeUI method. X location does not include insets, that is  | 
 | 
     * handled in getPathBounds.  | 
 | 
     */  | 
 | 
      | 
 | 
    public class NodeDimensionsHandler extends  | 
 | 
                 AbstractLayoutCache.NodeDimensions { | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        public Rectangle getNodeDimensions(Object value, int row,  | 
 | 
                                           int depth, boolean expanded,  | 
 | 
                                           Rectangle size) { | 
 | 
            // Return size of editing component, if editing and asking  | 
 | 
              | 
 | 
            if(editingComponent != null && editingRow == row) { | 
 | 
                Dimension        prefSize = editingComponent.  | 
 | 
                                              getPreferredSize();  | 
 | 
                int              rh = getRowHeight();  | 
 | 
 | 
 | 
                if(rh > 0 && rh != prefSize.height)  | 
 | 
                    prefSize.height = rh;  | 
 | 
                if(size != null) { | 
 | 
                    size.x = getRowX(row, depth);  | 
 | 
                    size.width = prefSize.width;  | 
 | 
                    size.height = prefSize.height;  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    size = new Rectangle(getRowX(row, depth), 0,  | 
 | 
                                         prefSize.width, prefSize.height);  | 
 | 
                }  | 
 | 
                return size;  | 
 | 
            }  | 
 | 
              | 
 | 
            if(currentCellRenderer != null) { | 
 | 
                Component          aComponent;  | 
 | 
 | 
 | 
                aComponent = currentCellRenderer.getTreeCellRendererComponent  | 
 | 
                    (tree, value, tree.isRowSelected(row),  | 
 | 
                     expanded, treeModel.isLeaf(value), row,  | 
 | 
                     false);  | 
 | 
                if(tree != null) { | 
 | 
                      | 
 | 
                    rendererPane.add(aComponent);  | 
 | 
                    aComponent.validate();  | 
 | 
                }  | 
 | 
                Dimension        prefSize = aComponent.getPreferredSize();  | 
 | 
 | 
 | 
                if(size != null) { | 
 | 
                    size.x = getRowX(row, depth);  | 
 | 
                    size.width = prefSize.width;  | 
 | 
                    size.height = prefSize.height;  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    size = new Rectangle(getRowX(row, depth), 0,  | 
 | 
                                         prefSize.width, prefSize.height);  | 
 | 
                }  | 
 | 
                return size;  | 
 | 
            }  | 
 | 
            return null;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        protected int getRowX(int row, int depth) { | 
 | 
            return BasicTreeUI.this.getRowX(row, depth);  | 
 | 
        }  | 
 | 
 | 
 | 
    } // End of class BasicTreeUI.NodeDimensionsHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public class MouseHandler extends MouseAdapter implements MouseMotionListener  | 
 | 
 { | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        public void mousePressed(MouseEvent e) { | 
 | 
            getHandler().mousePressed(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseDragged(MouseEvent e) { | 
 | 
            getHandler().mouseDragged(e);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void mouseMoved(MouseEvent e) { | 
 | 
            getHandler().mouseMoved(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseReleased(MouseEvent e) { | 
 | 
            getHandler().mouseReleased(e);  | 
 | 
        }  | 
 | 
    } // End of BasicTreeUI.MouseHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public class PropertyChangeHandler implements  | 
 | 
                       PropertyChangeListener { | 
 | 
 | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
        public void propertyChange(PropertyChangeEvent event) { | 
 | 
            getHandler().propertyChange(event);  | 
 | 
        }  | 
 | 
    } // End of BasicTreeUI.PropertyChangeHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public class SelectionModelPropertyChangeHandler implements  | 
 | 
                      PropertyChangeListener { | 
 | 
 | 
 | 
        // NOTE: This class exists only for backward compatibility. All  | 
 | 
        // its functionality has been moved into Handler. If you need to add  | 
 | 
        // new functionality add it to the Handler, but make sure this  | 
 | 
        // class calls into the Handler.  | 
 | 
 | 
 | 
        public void propertyChange(PropertyChangeEvent event) { | 
 | 
            getHandler().propertyChange(event);  | 
 | 
        }  | 
 | 
    } // End of BasicTreeUI.SelectionModelPropertyChangeHandler  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public class TreeTraverseAction extends AbstractAction { | 
 | 
          | 
 | 
          * collapse. */  | 
 | 
        protected int direction;  | 
 | 
          | 
 | 
         * changes. */  | 
 | 
        private boolean changeSelection;  | 
 | 
 | 
 | 
        public TreeTraverseAction(int direction, String name) { | 
 | 
            this(direction, name, true);  | 
 | 
        }  | 
 | 
 | 
 | 
        private TreeTraverseAction(int direction, String name,  | 
 | 
                                   boolean changeSelection) { | 
 | 
            this.direction = direction;  | 
 | 
            this.changeSelection = changeSelection;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void actionPerformed(ActionEvent e) { | 
 | 
            if (tree != null) { | 
 | 
                SHARED_ACTION.traverse(tree, BasicTreeUI.this, direction,  | 
 | 
                                       changeSelection);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isEnabled() { return (tree != null && | 
 | 
                                             tree.isEnabled()); }  | 
 | 
    } // BasicTreeUI.TreeTraverseAction  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
      */  | 
 | 
    public class TreePageAction extends AbstractAction { | 
 | 
          | 
 | 
        protected int         direction;  | 
 | 
          | 
 | 
        private boolean       addToSelection;  | 
 | 
        private boolean       changeSelection;  | 
 | 
 | 
 | 
        public TreePageAction(int direction, String name) { | 
 | 
            this(direction, name, false, true);  | 
 | 
        }  | 
 | 
 | 
 | 
        private TreePageAction(int direction, String name,  | 
 | 
                               boolean addToSelection,  | 
 | 
                               boolean changeSelection) { | 
 | 
            this.direction = direction;  | 
 | 
            this.addToSelection = addToSelection;  | 
 | 
            this.changeSelection = changeSelection;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void actionPerformed(ActionEvent e) { | 
 | 
            if (tree != null) { | 
 | 
                SHARED_ACTION.page(tree, BasicTreeUI.this, direction,  | 
 | 
                                   addToSelection, changeSelection);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isEnabled() { return (tree != null && | 
 | 
                                             tree.isEnabled()); }  | 
 | 
 | 
 | 
    } // BasicTreeUI.TreePageAction  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    public class TreeIncrementAction extends AbstractAction  { | 
 | 
          | 
 | 
        protected int         direction;  | 
 | 
          | 
 | 
         * selection is reset. */  | 
 | 
        private boolean       addToSelection;  | 
 | 
        private boolean       changeSelection;  | 
 | 
 | 
 | 
        public TreeIncrementAction(int direction, String name) { | 
 | 
            this(direction, name, false, true);  | 
 | 
        }  | 
 | 
 | 
 | 
        private TreeIncrementAction(int direction, String name,  | 
 | 
                                   boolean addToSelection,  | 
 | 
                                    boolean changeSelection) { | 
 | 
            this.direction = direction;  | 
 | 
            this.addToSelection = addToSelection;  | 
 | 
            this.changeSelection = changeSelection;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void actionPerformed(ActionEvent e) { | 
 | 
            if (tree != null) { | 
 | 
                SHARED_ACTION.increment(tree, BasicTreeUI.this, direction,  | 
 | 
                                        addToSelection, changeSelection);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isEnabled() { return (tree != null && | 
 | 
                                             tree.isEnabled()); }  | 
 | 
 | 
 | 
    } // End of class BasicTreeUI.TreeIncrementAction  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public class TreeHomeAction extends AbstractAction { | 
 | 
        protected int            direction;  | 
 | 
          | 
 | 
        private boolean          addToSelection;  | 
 | 
        private boolean          changeSelection;  | 
 | 
 | 
 | 
        public TreeHomeAction(int direction, String name) { | 
 | 
            this(direction, name, false, true);  | 
 | 
        }  | 
 | 
 | 
 | 
        private TreeHomeAction(int direction, String name,  | 
 | 
                               boolean addToSelection,  | 
 | 
                               boolean changeSelection) { | 
 | 
            this.direction = direction;  | 
 | 
            this.changeSelection = changeSelection;  | 
 | 
            this.addToSelection = addToSelection;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void actionPerformed(ActionEvent e) { | 
 | 
            if (tree != null) { | 
 | 
                SHARED_ACTION.home(tree, BasicTreeUI.this, direction,  | 
 | 
                                   addToSelection, changeSelection);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isEnabled() { return (tree != null && | 
 | 
                                             tree.isEnabled()); }  | 
 | 
 | 
 | 
    } // End of class BasicTreeUI.TreeHomeAction  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
      */  | 
 | 
    public class TreeToggleAction extends AbstractAction { | 
 | 
        public TreeToggleAction(String name) { | 
 | 
        }  | 
 | 
 | 
 | 
        public void actionPerformed(ActionEvent e) { | 
 | 
            if(tree != null) { | 
 | 
                SHARED_ACTION.toggle(tree, BasicTreeUI.this);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isEnabled() { return (tree != null && | 
 | 
                                             tree.isEnabled()); }  | 
 | 
 | 
 | 
    } // End of class BasicTreeUI.TreeToggleAction  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public class TreeCancelEditingAction extends AbstractAction { | 
 | 
        public TreeCancelEditingAction(String name) { | 
 | 
        }  | 
 | 
 | 
 | 
        public void actionPerformed(ActionEvent e) { | 
 | 
            if(tree != null) { | 
 | 
                SHARED_ACTION.cancelEditing(tree, BasicTreeUI.this);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isEnabled() { return (tree != null && | 
 | 
                                             tree.isEnabled() &&  | 
 | 
                                             isEditing(tree)); }  | 
 | 
    } // End of class BasicTreeUI.TreeCancelEditingAction  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      */  | 
 | 
    public class MouseInputHandler extends Object implements  | 
 | 
                     MouseInputListener  | 
 | 
    { | 
 | 
          | 
 | 
        protected Component        source;  | 
 | 
          | 
 | 
        protected Component        destination;  | 
 | 
        private Component          focusComponent;  | 
 | 
        private boolean            dispatchedEvent;  | 
 | 
 | 
 | 
        public MouseInputHandler(Component source, Component destination,  | 
 | 
                                      MouseEvent event){ | 
 | 
            this(source, destination, event, null);  | 
 | 
        }  | 
 | 
 | 
 | 
        MouseInputHandler(Component source, Component destination,  | 
 | 
                          MouseEvent event, Component focusComponent) { | 
 | 
            this.source = source;  | 
 | 
            this.destination = destination;  | 
 | 
            this.source.addMouseListener(this);  | 
 | 
            this.source.addMouseMotionListener(this);  | 
 | 
 | 
 | 
            SwingUtilities2.setSkipClickCount(destination,  | 
 | 
                                              event.getClickCount() - 1);  | 
 | 
 | 
 | 
              | 
 | 
            destination.dispatchEvent(SwingUtilities.convertMouseEvent  | 
 | 
                                          (source, event, destination));  | 
 | 
            this.focusComponent = focusComponent;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseClicked(MouseEvent e) { | 
 | 
            if(destination != null) { | 
 | 
                dispatchedEvent = true;  | 
 | 
                destination.dispatchEvent(SwingUtilities.convertMouseEvent  | 
 | 
                                          (source, e, destination));  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mousePressed(MouseEvent e) { | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseReleased(MouseEvent e) { | 
 | 
            if(destination != null)  | 
 | 
                destination.dispatchEvent(SwingUtilities.convertMouseEvent  | 
 | 
                                          (source, e, destination));  | 
 | 
            removeFromSource();  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseEntered(MouseEvent e) { | 
 | 
            if (!SwingUtilities.isLeftMouseButton(e)) { | 
 | 
                removeFromSource();  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseExited(MouseEvent e) { | 
 | 
            if (!SwingUtilities.isLeftMouseButton(e)) { | 
 | 
                removeFromSource();  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseDragged(MouseEvent e) { | 
 | 
            if(destination != null) { | 
 | 
                dispatchedEvent = true;  | 
 | 
                destination.dispatchEvent(SwingUtilities.convertMouseEvent  | 
 | 
                                          (source, e, destination));  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseMoved(MouseEvent e) { | 
 | 
            removeFromSource();  | 
 | 
        }  | 
 | 
 | 
 | 
        protected void removeFromSource() { | 
 | 
            if(source != null) { | 
 | 
                source.removeMouseListener(this);  | 
 | 
                source.removeMouseMotionListener(this);  | 
 | 
                if (focusComponent != null &&  | 
 | 
                      focusComponent == destination && !dispatchedEvent &&  | 
 | 
                      (focusComponent instanceof JTextField)) { | 
 | 
                    ((JTextField)focusComponent).selectAll();  | 
 | 
                }  | 
 | 
            }  | 
 | 
            source = destination = null;  | 
 | 
        }  | 
 | 
 | 
 | 
    } // End of class BasicTreeUI.MouseInputHandler  | 
 | 
 | 
 | 
    private static final TransferHandler defaultTransferHandler = new TreeTransferHandler();  | 
 | 
 | 
 | 
    static class TreeTransferHandler extends TransferHandler implements UIResource, Comparator<TreePath> { | 
 | 
 | 
 | 
        private JTree tree;  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        protected Transferable createTransferable(JComponent c) { | 
 | 
            if (c instanceof JTree) { | 
 | 
                tree = (JTree) c;  | 
 | 
                TreePath[] paths = tree.getSelectionPaths();  | 
 | 
 | 
 | 
                if (paths == null || paths.length == 0) { | 
 | 
                    return null;  | 
 | 
                }  | 
 | 
 | 
 | 
                StringBuffer plainBuf = new StringBuffer();  | 
 | 
                StringBuffer htmlBuf = new StringBuffer();  | 
 | 
 | 
 | 
                htmlBuf.append("<html>\n<body>\n<ul>\n"); | 
 | 
 | 
 | 
                TreeModel model = tree.getModel();  | 
 | 
                TreePath lastPath = null;  | 
 | 
                TreePath[] displayPaths = getDisplayOrderPaths(paths);  | 
 | 
 | 
 | 
                for (TreePath path : displayPaths) { | 
 | 
                    Object node = path.getLastPathComponent();  | 
 | 
                    boolean leaf = model.isLeaf(node);  | 
 | 
                    String label = getDisplayString(path, true, leaf);  | 
 | 
 | 
 | 
                    plainBuf.append(label + "\n");  | 
 | 
                    htmlBuf.append("  <li>" + label + "\n"); | 
 | 
                }  | 
 | 
 | 
 | 
                  | 
 | 
                plainBuf.deleteCharAt(plainBuf.length() - 1);  | 
 | 
                htmlBuf.append("</ul>\n</body>\n</html>"); | 
 | 
 | 
 | 
                tree = null;  | 
 | 
 | 
 | 
                return new BasicTransferable(plainBuf.toString(), htmlBuf.toString());  | 
 | 
            }  | 
 | 
 | 
 | 
            return null;  | 
 | 
        }  | 
 | 
 | 
 | 
        public int compare(TreePath o1, TreePath o2) { | 
 | 
            int row1 = tree.getRowForPath(o1);  | 
 | 
            int row2 = tree.getRowForPath(o2);  | 
 | 
            return row1 - row2;  | 
 | 
        }  | 
 | 
 | 
 | 
        String getDisplayString(TreePath path, boolean selected, boolean leaf) { | 
 | 
            int row = tree.getRowForPath(path);  | 
 | 
            boolean hasFocus = tree.getLeadSelectionRow() == row;  | 
 | 
            Object node = path.getLastPathComponent();  | 
 | 
            return tree.convertValueToText(node, selected, tree.isExpanded(row),  | 
 | 
                                           leaf, row, hasFocus);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        TreePath[] getDisplayOrderPaths(TreePath[] paths) { | 
 | 
              | 
 | 
            ArrayList<TreePath> selOrder = new ArrayList<TreePath>();  | 
 | 
            for (TreePath path : paths) { | 
 | 
                selOrder.add(path);  | 
 | 
            }  | 
 | 
            Collections.sort(selOrder, this);  | 
 | 
            int n = selOrder.size();  | 
 | 
            TreePath[] displayPaths = new TreePath[n];  | 
 | 
            for (int i = 0; i < n; i++) { | 
 | 
                displayPaths[i] = selOrder.get(i);  | 
 | 
            }  | 
 | 
            return displayPaths;  | 
 | 
        }  | 
 | 
 | 
 | 
        public int getSourceActions(JComponent c) { | 
 | 
            return COPY;  | 
 | 
        }  | 
 | 
 | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    private class Handler implements CellEditorListener, FocusListener,  | 
 | 
                  KeyListener, MouseListener, MouseMotionListener,  | 
 | 
                  PropertyChangeListener, TreeExpansionListener,  | 
 | 
                  TreeModelListener, TreeSelectionListener,  | 
 | 
                  BeforeDrag { | 
 | 
        //  | 
 | 
        // KeyListener  | 
 | 
          | 
 | 
        private String prefix = "";  | 
 | 
        private String typedString = "";  | 
 | 
        private long lastTime = 0L;  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void keyTyped(KeyEvent e) { | 
 | 
              | 
 | 
            if(tree != null && tree.getRowCount()>0 && tree.hasFocus() &&  | 
 | 
               tree.isEnabled()) { | 
 | 
                if (e.isAltDown() || BasicGraphicsUtils.isMenuShortcutKeyDown(e) ||  | 
 | 
                    isNavigationKey(e)) { | 
 | 
                    return;  | 
 | 
                }  | 
 | 
                boolean startingFromSelection = true;  | 
 | 
 | 
 | 
                char c = e.getKeyChar();  | 
 | 
 | 
 | 
                long time = e.getWhen();  | 
 | 
                int startingRow = tree.getLeadSelectionRow();  | 
 | 
                if (time - lastTime < timeFactor) { | 
 | 
                    typedString += c;  | 
 | 
                    if((prefix.length() == 1) && (c == prefix.charAt(0))) { | 
 | 
                        // Subsequent same key presses move the keyboard focus to the next  | 
 | 
                          | 
 | 
                        startingRow++;  | 
 | 
                    } else { | 
 | 
                        prefix = typedString;  | 
 | 
                    }  | 
 | 
                } else { | 
 | 
                    startingRow++;  | 
 | 
                    typedString = "" + c;  | 
 | 
                    prefix = typedString;  | 
 | 
                }  | 
 | 
                lastTime = time;  | 
 | 
 | 
 | 
                if (startingRow < 0 || startingRow >= tree.getRowCount()) { | 
 | 
                    startingFromSelection = false;  | 
 | 
                    startingRow = 0;  | 
 | 
                }  | 
 | 
                TreePath path = tree.getNextMatch(prefix, startingRow,  | 
 | 
                                                  Position.Bias.Forward);  | 
 | 
                if (path != null) { | 
 | 
                    tree.setSelectionPath(path);  | 
 | 
                    int row = getRowForPath(tree, path);  | 
 | 
                    ensureRowsAreVisible(row, row);  | 
 | 
                } else if (startingFromSelection) { | 
 | 
                    path = tree.getNextMatch(prefix, 0,  | 
 | 
                                             Position.Bias.Forward);  | 
 | 
                    if (path != null) { | 
 | 
                        tree.setSelectionPath(path);  | 
 | 
                        int row = getRowForPath(tree, path);  | 
 | 
                        ensureRowsAreVisible(row, row);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void keyPressed(KeyEvent e) { | 
 | 
            if (tree != null && isNavigationKey(e)) { | 
 | 
                prefix = "";  | 
 | 
                typedString = "";  | 
 | 
                lastTime = 0L;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void keyReleased(KeyEvent e) { | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        private boolean isNavigationKey(KeyEvent event) { | 
 | 
            InputMap inputMap = tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);  | 
 | 
            KeyStroke key = KeyStroke.getKeyStrokeForEvent(event);  | 
 | 
 | 
 | 
            return inputMap != null && inputMap.get(key) != null;  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
        //  | 
 | 
        // PropertyChangeListener  | 
 | 
          | 
 | 
        public void propertyChange(PropertyChangeEvent event) { | 
 | 
            if (event.getSource() == treeSelectionModel) { | 
 | 
                treeSelectionModel.resetRowSelection();  | 
 | 
            }  | 
 | 
            else if(event.getSource() == tree) { | 
 | 
                String              changeName = event.getPropertyName();  | 
 | 
 | 
 | 
                if (changeName == JTree.LEAD_SELECTION_PATH_PROPERTY) { | 
 | 
                    if (!ignoreLAChange) { | 
 | 
                        updateLeadSelectionRow();  | 
 | 
                        repaintPath((TreePath)event.getOldValue());  | 
 | 
                        repaintPath((TreePath)event.getNewValue());  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                else if (changeName == JTree.ANCHOR_SELECTION_PATH_PROPERTY) { | 
 | 
                    if (!ignoreLAChange) { | 
 | 
                        repaintPath((TreePath)event.getOldValue());  | 
 | 
                        repaintPath((TreePath)event.getNewValue());  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                if(changeName == JTree.CELL_RENDERER_PROPERTY) { | 
 | 
                    setCellRenderer((TreeCellRenderer)event.getNewValue());  | 
 | 
                    redoTheLayout();  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.TREE_MODEL_PROPERTY) { | 
 | 
                    setModel((TreeModel)event.getNewValue());  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.ROOT_VISIBLE_PROPERTY) { | 
 | 
                    setRootVisible(((Boolean)event.getNewValue()).  | 
 | 
                                   booleanValue());  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.SHOWS_ROOT_HANDLES_PROPERTY) { | 
 | 
                    setShowsRootHandles(((Boolean)event.getNewValue()).  | 
 | 
                                        booleanValue());  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.ROW_HEIGHT_PROPERTY) { | 
 | 
                    setRowHeight(((Integer)event.getNewValue()).  | 
 | 
                                 intValue());  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.CELL_EDITOR_PROPERTY) { | 
 | 
                    setCellEditor((TreeCellEditor)event.getNewValue());  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.EDITABLE_PROPERTY) { | 
 | 
                    setEditable(((Boolean)event.getNewValue()).booleanValue());  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.LARGE_MODEL_PROPERTY) { | 
 | 
                    setLargeModel(tree.isLargeModel());  | 
 | 
                }  | 
 | 
                else if(changeName == JTree.SELECTION_MODEL_PROPERTY) { | 
 | 
                    setSelectionModel(tree.getSelectionModel());  | 
 | 
                }  | 
 | 
                else if(changeName == "font") { | 
 | 
                    completeEditing();  | 
 | 
                    if(treeState != null)  | 
 | 
                        treeState.invalidateSizes();  | 
 | 
                    updateSize();  | 
 | 
                }  | 
 | 
                else if (changeName == "componentOrientation") { | 
 | 
                    if (tree != null) { | 
 | 
                        leftToRight = BasicGraphicsUtils.isLeftToRight(tree);  | 
 | 
                        redoTheLayout();  | 
 | 
                        tree.treeDidChange();  | 
 | 
 | 
 | 
                        InputMap km = getInputMap(JComponent.WHEN_FOCUSED);  | 
 | 
                        SwingUtilities.replaceUIInputMap(tree,  | 
 | 
                                                JComponent.WHEN_FOCUSED, km);  | 
 | 
                    }  | 
 | 
                } else if ("dropLocation" == changeName) { | 
 | 
                    JTree.DropLocation oldValue = (JTree.DropLocation)event.getOldValue();  | 
 | 
                    repaintDropLocation(oldValue);  | 
 | 
                    repaintDropLocation(tree.getDropLocation());  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void repaintDropLocation(JTree.DropLocation loc) { | 
 | 
            if (loc == null) { | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
            Rectangle r;  | 
 | 
 | 
 | 
            if (isDropLine(loc)) { | 
 | 
                r = getDropLineRect(loc);  | 
 | 
            } else { | 
 | 
                r = tree.getPathBounds(loc.getPath());  | 
 | 
            }  | 
 | 
 | 
 | 
            if (r != null) { | 
 | 
                tree.repaint(r);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        //  | 
 | 
        // MouseListener  | 
 | 
        //  | 
 | 
 | 
 | 
        // Whether or not the mouse press (which is being considered as part  | 
 | 
        // of a drag sequence) also caused the selection change to be fully  | 
 | 
          | 
 | 
        private boolean dragPressDidSelection;  | 
 | 
 | 
 | 
        // Set to true when a drag gesture has been fully recognized and DnD  | 
 | 
        // begins. Use this to ignore further mouse events which could be  | 
 | 
          | 
 | 
        private boolean dragStarted;  | 
 | 
 | 
 | 
          | 
 | 
        private TreePath pressedPath;  | 
 | 
        private MouseEvent pressedEvent;  | 
 | 
 | 
 | 
        // Used to detect whether the press event causes a selection change.  | 
 | 
          | 
 | 
        private boolean valueChangedOnPress;  | 
 | 
 | 
 | 
        private boolean isActualPath(TreePath path, int x, int y) { | 
 | 
            if (path == null) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
 | 
 | 
            Rectangle bounds = getPathBounds(tree, path);  | 
 | 
            if (bounds == null || y > (bounds.y + bounds.height)) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
 | 
 | 
            return (x >= bounds.x) && (x <= (bounds.x + bounds.width));  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseClicked(MouseEvent e) { | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseEntered(MouseEvent e) { | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseExited(MouseEvent e) { | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        public void mousePressed(MouseEvent e) { | 
 | 
            if (SwingUtilities2.shouldIgnore(e, tree)) { | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            if (isEditing(tree) && tree.getInvokesStopCellEditing()  | 
 | 
                                && !stopEditing(tree)) { | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
            completeEditing();  | 
 | 
 | 
 | 
            pressedPath = getClosestPathForLocation(tree, e.getX(), e.getY());  | 
 | 
 | 
 | 
            if (tree.getDragEnabled()) { | 
 | 
                mousePressedDND(e);  | 
 | 
            } else { | 
 | 
                SwingUtilities2.adjustFocus(tree);  | 
 | 
                handleSelection(e);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void mousePressedDND(MouseEvent e) { | 
 | 
            pressedEvent = e;  | 
 | 
            boolean grabFocus = true;  | 
 | 
            dragStarted = false;  | 
 | 
            valueChangedOnPress = false;  | 
 | 
 | 
 | 
              | 
 | 
            if (isActualPath(pressedPath, e.getX(), e.getY()) &&  | 
 | 
                    DragRecognitionSupport.mousePressed(e)) { | 
 | 
 | 
 | 
                dragPressDidSelection = false;  | 
 | 
 | 
 | 
                if (BasicGraphicsUtils.isMenuShortcutKeyDown(e)) { | 
 | 
                    // do nothing for control - will be handled on release  | 
 | 
                      | 
 | 
                    return;  | 
 | 
                } else if (!e.isShiftDown() && tree.isPathSelected(pressedPath)) { | 
 | 
                    // clicking on something that's already selected  | 
 | 
                      | 
 | 
                    setAnchorSelectionPath(pressedPath);  | 
 | 
                    setLeadSelectionPath(pressedPath, true);  | 
 | 
                    return;  | 
 | 
                }  | 
 | 
 | 
 | 
                dragPressDidSelection = true;  | 
 | 
 | 
 | 
                  | 
 | 
                grabFocus = false;  | 
 | 
            }  | 
 | 
 | 
 | 
            if (grabFocus) { | 
 | 
                SwingUtilities2.adjustFocus(tree);  | 
 | 
            }  | 
 | 
 | 
 | 
            handleSelection(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        void handleSelection(MouseEvent e) { | 
 | 
            if(pressedPath != null) { | 
 | 
                Rectangle bounds = getPathBounds(tree, pressedPath);  | 
 | 
 | 
 | 
                if (bounds == null || e.getY() >= (bounds.y + bounds.height)) { | 
 | 
                    return;  | 
 | 
                }  | 
 | 
 | 
 | 
                // Preferably checkForClickInExpandControl could take  | 
 | 
                  | 
 | 
                if(SwingUtilities.isLeftMouseButton(e)) { | 
 | 
                    checkForClickInExpandControl(pressedPath, e.getX(), e.getY());  | 
 | 
                }  | 
 | 
 | 
 | 
                int x = e.getX();  | 
 | 
 | 
 | 
                // Perhaps they clicked the cell itself. If so,  | 
 | 
                  | 
 | 
                if (x >= bounds.x && x < (bounds.x + bounds.width)) { | 
 | 
                    if (tree.getDragEnabled() || !startEditing(pressedPath, e)) { | 
 | 
                        selectPathForEvent(pressedPath, e);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void dragStarting(MouseEvent me) { | 
 | 
            dragStarted = true;  | 
 | 
 | 
 | 
            if (BasicGraphicsUtils.isMenuShortcutKeyDown(me)) { | 
 | 
                tree.addSelectionPath(pressedPath);  | 
 | 
                setAnchorSelectionPath(pressedPath);  | 
 | 
                setLeadSelectionPath(pressedPath, true);  | 
 | 
            }  | 
 | 
 | 
 | 
            pressedEvent = null;  | 
 | 
            pressedPath = null;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseDragged(MouseEvent e) { | 
 | 
            if (SwingUtilities2.shouldIgnore(e, tree)) { | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
            if (tree.getDragEnabled()) { | 
 | 
                DragRecognitionSupport.mouseDragged(e, this);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void mouseMoved(MouseEvent e) { | 
 | 
        }  | 
 | 
 | 
 | 
        public void mouseReleased(MouseEvent e) { | 
 | 
            if (SwingUtilities2.shouldIgnore(e, tree)) { | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
            if (tree.getDragEnabled()) { | 
 | 
                mouseReleasedDND(e);  | 
 | 
            }  | 
 | 
 | 
 | 
            pressedEvent = null;  | 
 | 
            pressedPath = null;  | 
 | 
        }  | 
 | 
 | 
 | 
        private void mouseReleasedDND(MouseEvent e) { | 
 | 
            MouseEvent me = DragRecognitionSupport.mouseReleased(e);  | 
 | 
            if (me != null) { | 
 | 
                SwingUtilities2.adjustFocus(tree);  | 
 | 
                if (!dragPressDidSelection) { | 
 | 
                    handleSelection(me);  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            if (!dragStarted) { | 
 | 
 | 
 | 
                // Note: We don't give the tree a chance to start editing if the  | 
 | 
                // mouse press caused a selection change. Otherwise the default  | 
 | 
                // tree cell editor will start editing on EVERY press and  | 
 | 
                // release. If it turns out that this affects some editors, we  | 
 | 
                // can always parameterize this with a client property. ex:  | 
 | 
                //  | 
 | 
                // if (pressedPath != null &&  | 
 | 
                //         (Boolean.TRUE == tree.getClientProperty("Tree.DnD.canEditOnValueChange") || | 
 | 
                  | 
 | 
                if (pressedPath != null && !valueChangedOnPress &&  | 
 | 
                        isActualPath(pressedPath, pressedEvent.getX(), pressedEvent.getY())) { | 
 | 
 | 
 | 
                    startEditingOnRelease(pressedPath, pressedEvent, e);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        //  | 
 | 
        // FocusListener  | 
 | 
          | 
 | 
        public void focusGained(FocusEvent e) { | 
 | 
            if(tree != null) { | 
 | 
                Rectangle                 pBounds;  | 
 | 
 | 
 | 
                pBounds = getPathBounds(tree, tree.getLeadSelectionPath());  | 
 | 
                if(pBounds != null)  | 
 | 
                    tree.repaint(getRepaintPathBounds(pBounds));  | 
 | 
                pBounds = getPathBounds(tree, getLeadSelectionPath());  | 
 | 
                if(pBounds != null)  | 
 | 
                    tree.repaint(getRepaintPathBounds(pBounds));  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void focusLost(FocusEvent e) { | 
 | 
            focusGained(e);  | 
 | 
        }  | 
 | 
 | 
 | 
        //  | 
 | 
        // CellEditorListener  | 
 | 
          | 
 | 
        public void editingStopped(ChangeEvent e) { | 
 | 
            completeEditing(false, false, true);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        public void editingCanceled(ChangeEvent e) { | 
 | 
            completeEditing(false, false, false);  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
        //  | 
 | 
        // TreeSelectionListener  | 
 | 
          | 
 | 
        public void valueChanged(TreeSelectionEvent event) { | 
 | 
            valueChangedOnPress = true;  | 
 | 
 | 
 | 
              | 
 | 
            completeEditing();  | 
 | 
            // Make sure all the paths are visible, if necessary.  | 
 | 
              | 
 | 
            if(tree.getExpandsSelectedPaths() && treeSelectionModel != null) { | 
 | 
                TreePath[]           paths = treeSelectionModel  | 
 | 
                                         .getSelectionPaths();  | 
 | 
 | 
 | 
                if(paths != null) { | 
 | 
                    for(int counter = paths.length - 1; counter >= 0;  | 
 | 
                        counter--) { | 
 | 
                        TreePath path = paths[counter].getParentPath();  | 
 | 
                        boolean expand = true;  | 
 | 
 | 
 | 
                        while (path != null) { | 
 | 
                            // Indicates this path isn't valid anymore,  | 
 | 
                              | 
 | 
                            if (treeModel.isLeaf(path.getLastPathComponent())){ | 
 | 
                                expand = false;  | 
 | 
                                path = null;  | 
 | 
                            }  | 
 | 
                            else { | 
 | 
                                path = path.getParentPath();  | 
 | 
                            }  | 
 | 
                        }  | 
 | 
                        if (expand) { | 
 | 
                            tree.makeVisible(paths[counter]);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            TreePath oldLead = getLeadSelectionPath();  | 
 | 
            lastSelectedRow = tree.getMinSelectionRow();  | 
 | 
            TreePath lead = tree.getSelectionModel().getLeadSelectionPath();  | 
 | 
            setAnchorSelectionPath(lead);  | 
 | 
            setLeadSelectionPath(lead);  | 
 | 
 | 
 | 
            TreePath[]       changedPaths = event.getPaths();  | 
 | 
            Rectangle        nodeBounds;  | 
 | 
            Rectangle        visRect = tree.getVisibleRect();  | 
 | 
            boolean          paintPaths = true;  | 
 | 
            int              nWidth = tree.getWidth();  | 
 | 
 | 
 | 
            if(changedPaths != null) { | 
 | 
                int              counter, maxCounter = changedPaths.length;  | 
 | 
 | 
 | 
                if(maxCounter > 4) { | 
 | 
                    tree.repaint();  | 
 | 
                    paintPaths = false;  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    for (counter = 0; counter < maxCounter; counter++) { | 
 | 
                        nodeBounds = getPathBounds(tree,  | 
 | 
                                                   changedPaths[counter]);  | 
 | 
                        if(nodeBounds != null &&  | 
 | 
                           visRect.intersects(nodeBounds))  | 
 | 
                            tree.repaint(0, nodeBounds.y, nWidth,  | 
 | 
                                         nodeBounds.height);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
            if(paintPaths) { | 
 | 
                nodeBounds = getPathBounds(tree, oldLead);  | 
 | 
                if(nodeBounds != null && visRect.intersects(nodeBounds))  | 
 | 
                    tree.repaint(0, nodeBounds.y, nWidth, nodeBounds.height);  | 
 | 
                nodeBounds = getPathBounds(tree, lead);  | 
 | 
                if(nodeBounds != null && visRect.intersects(nodeBounds))  | 
 | 
                    tree.repaint(0, nodeBounds.y, nWidth, nodeBounds.height);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
        //  | 
 | 
        // TreeExpansionListener  | 
 | 
          | 
 | 
        public void treeExpanded(TreeExpansionEvent event) { | 
 | 
            if(event != null && tree != null) { | 
 | 
                TreePath      path = event.getPath();  | 
 | 
 | 
 | 
                updateExpandedDescendants(path);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void treeCollapsed(TreeExpansionEvent event) { | 
 | 
            if(event != null && tree != null) { | 
 | 
                TreePath        path = event.getPath();  | 
 | 
 | 
 | 
                completeEditing();  | 
 | 
                if(path != null && tree.isVisible(path)) { | 
 | 
                    treeState.setExpandedState(path, false);  | 
 | 
                    updateLeadSelectionRow();  | 
 | 
                    updateSize();  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        //  | 
 | 
        // TreeModelListener  | 
 | 
          | 
 | 
        public void treeNodesChanged(TreeModelEvent e) { | 
 | 
            if(treeState != null && e != null) { | 
 | 
                TreePath parentPath = SwingUtilities2.getTreePath(e, getModel());  | 
 | 
                int[] indices = e.getChildIndices();  | 
 | 
                if (indices == null || indices.length == 0) { | 
 | 
                      | 
 | 
                    treeState.treeNodesChanged(e);  | 
 | 
                    updateSize();  | 
 | 
                }  | 
 | 
                else if (treeState.isExpanded(parentPath)) { | 
 | 
                    // Changed nodes are visible  | 
 | 
                    // Find the minimum index, we only need paint from there  | 
 | 
                      | 
 | 
                    int minIndex = indices[0];  | 
 | 
                    for (int i = indices.length - 1; i > 0; i--) { | 
 | 
                        minIndex = Math.min(indices[i], minIndex);  | 
 | 
                    }  | 
 | 
                    Object minChild = treeModel.getChild(  | 
 | 
                            parentPath.getLastPathComponent(), minIndex);  | 
 | 
                    TreePath minPath = parentPath.pathByAddingChild(minChild);  | 
 | 
                    Rectangle minBounds = getPathBounds(tree, minPath);  | 
 | 
 | 
 | 
                      | 
 | 
                    treeState.treeNodesChanged(e);  | 
 | 
 | 
 | 
                      | 
 | 
                    updateSize0();  | 
 | 
 | 
 | 
                      | 
 | 
                    Rectangle newMinBounds = getPathBounds(tree, minPath);  | 
 | 
                    if (minBounds == null || newMinBounds == null) { | 
 | 
                        return;  | 
 | 
                    }  | 
 | 
 | 
 | 
                    if (indices.length == 1 &&  | 
 | 
                            newMinBounds.height == minBounds.height) { | 
 | 
                        tree.repaint(0, minBounds.y, tree.getWidth(),  | 
 | 
                                     minBounds.height);  | 
 | 
                    }  | 
 | 
                    else { | 
 | 
                        tree.repaint(0, minBounds.y, tree.getWidth(),  | 
 | 
                                     tree.getHeight() - minBounds.y);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                else { | 
 | 
                      | 
 | 
                    treeState.treeNodesChanged(e);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void treeNodesInserted(TreeModelEvent e) { | 
 | 
            if(treeState != null && e != null) { | 
 | 
                treeState.treeNodesInserted(e);  | 
 | 
 | 
 | 
                updateLeadSelectionRow();  | 
 | 
 | 
 | 
                TreePath       path = SwingUtilities2.getTreePath(e, getModel());  | 
 | 
 | 
 | 
                if(treeState.isExpanded(path)) { | 
 | 
                    updateSize();  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    // PENDING(sky): Need a method in TreeModelEvent  | 
 | 
                    // that can return the count, getChildIndices allocs  | 
 | 
                      | 
 | 
                    int[]      indices = e.getChildIndices();  | 
 | 
                    int        childCount = treeModel.getChildCount  | 
 | 
                                            (path.getLastPathComponent());  | 
 | 
 | 
 | 
                    if(indices != null && (childCount - indices.length) == 0)  | 
 | 
                        updateSize();  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void treeNodesRemoved(TreeModelEvent e) { | 
 | 
            if(treeState != null && e != null) { | 
 | 
                treeState.treeNodesRemoved(e);  | 
 | 
 | 
 | 
                updateLeadSelectionRow();  | 
 | 
 | 
 | 
                TreePath       path = SwingUtilities2.getTreePath(e, getModel());  | 
 | 
 | 
 | 
                if(treeState.isExpanded(path) ||  | 
 | 
                   treeModel.getChildCount(path.getLastPathComponent()) == 0)  | 
 | 
                    updateSize();  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public void treeStructureChanged(TreeModelEvent e) { | 
 | 
            if(treeState != null && e != null) { | 
 | 
                treeState.treeStructureChanged(e);  | 
 | 
 | 
 | 
                updateLeadSelectionRow();  | 
 | 
 | 
 | 
                TreePath       pPath = SwingUtilities2.getTreePath(e, getModel());  | 
 | 
 | 
 | 
                if (pPath != null) { | 
 | 
                    pPath = pPath.getParentPath();  | 
 | 
                }  | 
 | 
                if(pPath == null || treeState.isExpanded(pPath))  | 
 | 
                    updateSize();  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    private static class Actions extends UIAction { | 
 | 
        private static final String SELECT_PREVIOUS = "selectPrevious";  | 
 | 
        private static final String SELECT_PREVIOUS_CHANGE_LEAD =  | 
 | 
                             "selectPreviousChangeLead";  | 
 | 
        private static final String SELECT_PREVIOUS_EXTEND_SELECTION =  | 
 | 
                             "selectPreviousExtendSelection";  | 
 | 
        private static final String SELECT_NEXT = "selectNext";  | 
 | 
        private static final String SELECT_NEXT_CHANGE_LEAD =  | 
 | 
                                    "selectNextChangeLead";  | 
 | 
        private static final String SELECT_NEXT_EXTEND_SELECTION =  | 
 | 
                                    "selectNextExtendSelection";  | 
 | 
        private static final String SELECT_CHILD = "selectChild";  | 
 | 
        private static final String SELECT_CHILD_CHANGE_LEAD =  | 
 | 
                                    "selectChildChangeLead";  | 
 | 
        private static final String SELECT_PARENT = "selectParent";  | 
 | 
        private static final String SELECT_PARENT_CHANGE_LEAD =  | 
 | 
                                    "selectParentChangeLead";  | 
 | 
        private static final String SCROLL_UP_CHANGE_SELECTION =  | 
 | 
                                    "scrollUpChangeSelection";  | 
 | 
        private static final String SCROLL_UP_CHANGE_LEAD =  | 
 | 
                                    "scrollUpChangeLead";  | 
 | 
        private static final String SCROLL_UP_EXTEND_SELECTION =  | 
 | 
                                    "scrollUpExtendSelection";  | 
 | 
        private static final String SCROLL_DOWN_CHANGE_SELECTION =  | 
 | 
                                    "scrollDownChangeSelection";  | 
 | 
        private static final String SCROLL_DOWN_EXTEND_SELECTION =  | 
 | 
                                    "scrollDownExtendSelection";  | 
 | 
        private static final String SCROLL_DOWN_CHANGE_LEAD =  | 
 | 
                                    "scrollDownChangeLead";  | 
 | 
        private static final String SELECT_FIRST = "selectFirst";  | 
 | 
        private static final String SELECT_FIRST_CHANGE_LEAD =  | 
 | 
                                    "selectFirstChangeLead";  | 
 | 
        private static final String SELECT_FIRST_EXTEND_SELECTION =  | 
 | 
                                    "selectFirstExtendSelection";  | 
 | 
        private static final String SELECT_LAST = "selectLast";  | 
 | 
        private static final String SELECT_LAST_CHANGE_LEAD =  | 
 | 
                                    "selectLastChangeLead";  | 
 | 
        private static final String SELECT_LAST_EXTEND_SELECTION =  | 
 | 
                                    "selectLastExtendSelection";  | 
 | 
        private static final String TOGGLE = "toggle";  | 
 | 
        private static final String CANCEL_EDITING = "cancel";  | 
 | 
        private static final String START_EDITING = "startEditing";  | 
 | 
        private static final String SELECT_ALL = "selectAll";  | 
 | 
        private static final String CLEAR_SELECTION = "clearSelection";  | 
 | 
        private static final String SCROLL_LEFT = "scrollLeft";  | 
 | 
        private static final String SCROLL_RIGHT = "scrollRight";  | 
 | 
        private static final String SCROLL_LEFT_EXTEND_SELECTION =  | 
 | 
                                    "scrollLeftExtendSelection";  | 
 | 
        private static final String SCROLL_RIGHT_EXTEND_SELECTION =  | 
 | 
                                    "scrollRightExtendSelection";  | 
 | 
        private static final String SCROLL_RIGHT_CHANGE_LEAD =  | 
 | 
                                    "scrollRightChangeLead";  | 
 | 
        private static final String SCROLL_LEFT_CHANGE_LEAD =  | 
 | 
                                    "scrollLeftChangeLead";  | 
 | 
        private static final String EXPAND = "expand";  | 
 | 
        private static final String COLLAPSE = "collapse";  | 
 | 
        private static final String MOVE_SELECTION_TO_PARENT =  | 
 | 
                                    "moveSelectionToParent";  | 
 | 
 | 
 | 
          | 
 | 
        private static final String ADD_TO_SELECTION = "addToSelection";  | 
 | 
 | 
 | 
          | 
 | 
        private static final String TOGGLE_AND_ANCHOR = "toggleAndAnchor";  | 
 | 
 | 
 | 
          | 
 | 
        private static final String EXTEND_TO = "extendTo";  | 
 | 
 | 
 | 
          | 
 | 
        private static final String MOVE_SELECTION_TO = "moveSelectionTo";  | 
 | 
 | 
 | 
        Actions() { | 
 | 
            super(null);  | 
 | 
        }  | 
 | 
 | 
 | 
        Actions(String key) { | 
 | 
            super(key);  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean isEnabled(Object o) { | 
 | 
            if (o instanceof JTree) { | 
 | 
                if (getName() == CANCEL_EDITING) { | 
 | 
                    return ((JTree)o).isEditing();  | 
 | 
                }  | 
 | 
            }  | 
 | 
            return true;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void actionPerformed(ActionEvent e) { | 
 | 
            JTree tree = (JTree)e.getSource();  | 
 | 
            BasicTreeUI ui = (BasicTreeUI)BasicLookAndFeel.getUIOfType(  | 
 | 
                             tree.getUI(), BasicTreeUI.class);  | 
 | 
            if (ui == null) { | 
 | 
                return;  | 
 | 
            }  | 
 | 
            String key = getName();  | 
 | 
            if (key == SELECT_PREVIOUS) { | 
 | 
                increment(tree, ui, -1, false, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_PREVIOUS_CHANGE_LEAD) { | 
 | 
                increment(tree, ui, -1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_PREVIOUS_EXTEND_SELECTION) { | 
 | 
                increment(tree, ui, -1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_NEXT) { | 
 | 
                increment(tree, ui, 1, false, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_NEXT_CHANGE_LEAD) { | 
 | 
                increment(tree, ui, 1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_NEXT_EXTEND_SELECTION) { | 
 | 
                increment(tree, ui, 1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_CHILD) { | 
 | 
                traverse(tree, ui, 1, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_CHILD_CHANGE_LEAD) { | 
 | 
                traverse(tree, ui, 1, false);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_PARENT) { | 
 | 
                traverse(tree, ui, -1, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_PARENT_CHANGE_LEAD) { | 
 | 
                traverse(tree, ui, -1, false);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_UP_CHANGE_SELECTION) { | 
 | 
                page(tree, ui, -1, false, true);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_UP_CHANGE_LEAD) { | 
 | 
                page(tree, ui, -1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_UP_EXTEND_SELECTION) { | 
 | 
                page(tree, ui, -1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_DOWN_CHANGE_SELECTION) { | 
 | 
                page(tree, ui, 1, false, true);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_DOWN_EXTEND_SELECTION) { | 
 | 
                page(tree, ui, 1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_DOWN_CHANGE_LEAD) { | 
 | 
                page(tree, ui, 1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_FIRST) { | 
 | 
                home(tree, ui, -1, false, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_FIRST_CHANGE_LEAD) { | 
 | 
                home(tree, ui, -1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_FIRST_EXTEND_SELECTION) { | 
 | 
                home(tree, ui, -1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_LAST) { | 
 | 
                home(tree, ui, 1, false, true);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_LAST_CHANGE_LEAD) { | 
 | 
                home(tree, ui, 1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_LAST_EXTEND_SELECTION) { | 
 | 
                home(tree, ui, 1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == TOGGLE) { | 
 | 
                toggle(tree, ui);  | 
 | 
            }  | 
 | 
            else if (key == CANCEL_EDITING) { | 
 | 
                cancelEditing(tree, ui);  | 
 | 
            }  | 
 | 
            else if (key == START_EDITING) { | 
 | 
                startEditing(tree, ui);  | 
 | 
            }  | 
 | 
            else if (key == SELECT_ALL) { | 
 | 
                selectAll(tree, ui, true);  | 
 | 
            }  | 
 | 
            else if (key == CLEAR_SELECTION) { | 
 | 
                selectAll(tree, ui, false);  | 
 | 
            }  | 
 | 
            else if (key == ADD_TO_SELECTION) { | 
 | 
                if (ui.getRowCount(tree) > 0) { | 
 | 
                    int lead = ui.getLeadSelectionRow();  | 
 | 
                    if (!tree.isRowSelected(lead)) { | 
 | 
                        TreePath aPath = ui.getAnchorSelectionPath();  | 
 | 
                        tree.addSelectionRow(lead);  | 
 | 
                        ui.setAnchorSelectionPath(aPath);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
            else if (key == TOGGLE_AND_ANCHOR) { | 
 | 
                if (ui.getRowCount(tree) > 0) { | 
 | 
                    int lead = ui.getLeadSelectionRow();  | 
 | 
                    TreePath lPath = ui.getLeadSelectionPath();  | 
 | 
                    if (!tree.isRowSelected(lead)) { | 
 | 
                        tree.addSelectionRow(lead);  | 
 | 
                    } else { | 
 | 
                        tree.removeSelectionRow(lead);  | 
 | 
                        ui.setLeadSelectionPath(lPath);  | 
 | 
                    }  | 
 | 
                    ui.setAnchorSelectionPath(lPath);  | 
 | 
                }  | 
 | 
            }  | 
 | 
            else if (key == EXTEND_TO) { | 
 | 
                extendSelection(tree, ui);  | 
 | 
            }  | 
 | 
            else if (key == MOVE_SELECTION_TO) { | 
 | 
                if (ui.getRowCount(tree) > 0) { | 
 | 
                    int lead = ui.getLeadSelectionRow();  | 
 | 
                    tree.setSelectionInterval(lead, lead);  | 
 | 
                }  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_LEFT) { | 
 | 
                scroll(tree, ui, SwingConstants.HORIZONTAL, -10);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_RIGHT) { | 
 | 
                scroll(tree, ui, SwingConstants.HORIZONTAL, 10);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_LEFT_EXTEND_SELECTION) { | 
 | 
                scrollChangeSelection(tree, ui, -1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_RIGHT_EXTEND_SELECTION) { | 
 | 
                scrollChangeSelection(tree, ui, 1, true, true);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_RIGHT_CHANGE_LEAD) { | 
 | 
                scrollChangeSelection(tree, ui, 1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == SCROLL_LEFT_CHANGE_LEAD) { | 
 | 
                scrollChangeSelection(tree, ui, -1, false, false);  | 
 | 
            }  | 
 | 
            else if (key == EXPAND) { | 
 | 
                expand(tree, ui);  | 
 | 
            }  | 
 | 
            else if (key == COLLAPSE) { | 
 | 
                collapse(tree, ui);  | 
 | 
            }  | 
 | 
            else if (key == MOVE_SELECTION_TO_PARENT) { | 
 | 
                moveSelectionToParent(tree, ui);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void scrollChangeSelection(JTree tree, BasicTreeUI ui,  | 
 | 
                           int direction, boolean addToSelection,  | 
 | 
                           boolean changeSelection) { | 
 | 
            int           rowCount;  | 
 | 
 | 
 | 
            if((rowCount = ui.getRowCount(tree)) > 0 &&  | 
 | 
                ui.treeSelectionModel != null) { | 
 | 
                TreePath          newPath;  | 
 | 
                Rectangle         visRect = tree.getVisibleRect();  | 
 | 
 | 
 | 
                if (direction == -1) { | 
 | 
                    newPath = ui.getClosestPathForLocation(tree, visRect.x,  | 
 | 
                                                        visRect.y);  | 
 | 
                    visRect.x = Math.max(0, visRect.x - visRect.width);  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    visRect.x = Math.min(Math.max(0, tree.getWidth() -  | 
 | 
                                   visRect.width), visRect.x + visRect.width);  | 
 | 
                    newPath = ui.getClosestPathForLocation(tree, visRect.x,  | 
 | 
                                                 visRect.y + visRect.height);  | 
 | 
                }  | 
 | 
                  | 
 | 
                tree.scrollRectToVisible(visRect);  | 
 | 
                  | 
 | 
                if (addToSelection) { | 
 | 
                    ui.extendSelection(newPath);  | 
 | 
                }  | 
 | 
                else if(changeSelection) { | 
 | 
                    tree.setSelectionPath(newPath);  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    ui.setLeadSelectionPath(newPath, true);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void scroll(JTree component, BasicTreeUI ui, int direction,  | 
 | 
                            int amount) { | 
 | 
            Rectangle visRect = component.getVisibleRect();  | 
 | 
            Dimension size = component.getSize();  | 
 | 
            if (direction == SwingConstants.HORIZONTAL) { | 
 | 
                visRect.x += amount;  | 
 | 
                visRect.x = Math.max(0, visRect.x);  | 
 | 
                visRect.x = Math.min(Math.max(0, size.width - visRect.width),  | 
 | 
                                     visRect.x);  | 
 | 
            }  | 
 | 
            else { | 
 | 
                visRect.y += amount;  | 
 | 
                visRect.y = Math.max(0, visRect.y);  | 
 | 
                visRect.y = Math.min(Math.max(0, size.width - visRect.height),  | 
 | 
                                     visRect.y);  | 
 | 
            }  | 
 | 
            component.scrollRectToVisible(visRect);  | 
 | 
        }  | 
 | 
 | 
 | 
        private void extendSelection(JTree tree, BasicTreeUI ui) { | 
 | 
            if (ui.getRowCount(tree) > 0) { | 
 | 
                int       lead = ui.getLeadSelectionRow();  | 
 | 
 | 
 | 
                if (lead != -1) { | 
 | 
                    TreePath      leadP = ui.getLeadSelectionPath();  | 
 | 
                    TreePath      aPath = ui.getAnchorSelectionPath();  | 
 | 
                    int           aRow = ui.getRowForPath(tree, aPath);  | 
 | 
 | 
 | 
                    if(aRow == -1)  | 
 | 
                        aRow = 0;  | 
 | 
                    tree.setSelectionInterval(aRow, lead);  | 
 | 
                    ui.setLeadSelectionPath(leadP);  | 
 | 
                    ui.setAnchorSelectionPath(aPath);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void selectAll(JTree tree, BasicTreeUI ui, boolean selectAll) { | 
 | 
            int                   rowCount = ui.getRowCount(tree);  | 
 | 
 | 
 | 
            if(rowCount > 0) { | 
 | 
                if(selectAll) { | 
 | 
                    if (tree.getSelectionModel().getSelectionMode() ==  | 
 | 
                            TreeSelectionModel.SINGLE_TREE_SELECTION) { | 
 | 
 | 
 | 
                        int lead = ui.getLeadSelectionRow();  | 
 | 
                        if (lead != -1) { | 
 | 
                            tree.setSelectionRow(lead);  | 
 | 
                        } else if (tree.getMinSelectionRow() == -1) { | 
 | 
                            tree.setSelectionRow(0);  | 
 | 
                            ui.ensureRowsAreVisible(0, 0);  | 
 | 
                        }  | 
 | 
                        return;  | 
 | 
                    }  | 
 | 
 | 
 | 
                    TreePath      lastPath = ui.getLeadSelectionPath();  | 
 | 
                    TreePath      aPath = ui.getAnchorSelectionPath();  | 
 | 
 | 
 | 
                    if(lastPath != null && !tree.isVisible(lastPath)) { | 
 | 
                        lastPath = null;  | 
 | 
                    }  | 
 | 
                    tree.setSelectionInterval(0, rowCount - 1);  | 
 | 
                    if(lastPath != null) { | 
 | 
                        ui.setLeadSelectionPath(lastPath);  | 
 | 
                    }  | 
 | 
                    if(aPath != null && tree.isVisible(aPath)) { | 
 | 
                        ui.setAnchorSelectionPath(aPath);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    TreePath      lastPath = ui.getLeadSelectionPath();  | 
 | 
                    TreePath      aPath = ui.getAnchorSelectionPath();  | 
 | 
 | 
 | 
                    tree.clearSelection();  | 
 | 
                    ui.setAnchorSelectionPath(aPath);  | 
 | 
                    ui.setLeadSelectionPath(lastPath);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void startEditing(JTree tree, BasicTreeUI ui) { | 
 | 
            TreePath   lead = ui.getLeadSelectionPath();  | 
 | 
            int        editRow = (lead != null) ?  | 
 | 
                                     ui.getRowForPath(tree, lead) : -1;  | 
 | 
 | 
 | 
            if(editRow != -1) { | 
 | 
                tree.startEditingAtPath(lead);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void cancelEditing(JTree tree, BasicTreeUI ui) { | 
 | 
            tree.cancelEditing();  | 
 | 
        }  | 
 | 
 | 
 | 
        private void toggle(JTree tree, BasicTreeUI ui) { | 
 | 
            int            selRow = ui.getLeadSelectionRow();  | 
 | 
 | 
 | 
            if(selRow != -1 && !ui.isLeaf(selRow)) { | 
 | 
                TreePath aPath = ui.getAnchorSelectionPath();  | 
 | 
                TreePath lPath = ui.getLeadSelectionPath();  | 
 | 
 | 
 | 
                ui.toggleExpandState(ui.getPathForRow(tree, selRow));  | 
 | 
                ui.setAnchorSelectionPath(aPath);  | 
 | 
                ui.setLeadSelectionPath(lPath);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void expand(JTree tree, BasicTreeUI ui) { | 
 | 
            int selRow = ui.getLeadSelectionRow();  | 
 | 
            tree.expandRow(selRow);  | 
 | 
        }  | 
 | 
 | 
 | 
        private void collapse(JTree tree, BasicTreeUI ui) { | 
 | 
            int selRow = ui.getLeadSelectionRow();  | 
 | 
            tree.collapseRow(selRow);  | 
 | 
        }  | 
 | 
 | 
 | 
        private void increment(JTree tree, BasicTreeUI ui, int direction,  | 
 | 
                               boolean addToSelection,  | 
 | 
                               boolean changeSelection) { | 
 | 
 | 
 | 
              | 
 | 
            if (!addToSelection && !changeSelection &&  | 
 | 
                    tree.getSelectionModel().getSelectionMode() !=  | 
 | 
                        TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { | 
 | 
                changeSelection = true;  | 
 | 
            }  | 
 | 
 | 
 | 
            int              rowCount;  | 
 | 
 | 
 | 
            if(ui.treeSelectionModel != null &&  | 
 | 
                  (rowCount = tree.getRowCount()) > 0) { | 
 | 
                int                  selIndex = ui.getLeadSelectionRow();  | 
 | 
                int                  newIndex;  | 
 | 
 | 
 | 
                if(selIndex == -1) { | 
 | 
                    if(direction == 1)  | 
 | 
                        newIndex = 0;  | 
 | 
                    else  | 
 | 
                        newIndex = rowCount - 1;  | 
 | 
                }  | 
 | 
                else  | 
 | 
                      | 
 | 
                    newIndex = Math.min(rowCount - 1, Math.max  | 
 | 
                                        (0, (selIndex + direction)));  | 
 | 
                if(addToSelection && ui.treeSelectionModel.  | 
 | 
                        getSelectionMode() != TreeSelectionModel.  | 
 | 
                        SINGLE_TREE_SELECTION) { | 
 | 
                    ui.extendSelection(tree.getPathForRow(newIndex));  | 
 | 
                }  | 
 | 
                else if(changeSelection) { | 
 | 
                    tree.setSelectionInterval(newIndex, newIndex);  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    ui.setLeadSelectionPath(tree.getPathForRow(newIndex),true);  | 
 | 
                }  | 
 | 
                ui.ensureRowsAreVisible(newIndex, newIndex);  | 
 | 
                ui.lastSelectedRow = newIndex;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void traverse(JTree tree, BasicTreeUI ui, int direction,  | 
 | 
                              boolean changeSelection) { | 
 | 
 | 
 | 
              | 
 | 
            if (!changeSelection &&  | 
 | 
                    tree.getSelectionModel().getSelectionMode() !=  | 
 | 
                        TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { | 
 | 
                changeSelection = true;  | 
 | 
            }  | 
 | 
 | 
 | 
            int                rowCount;  | 
 | 
 | 
 | 
            if((rowCount = tree.getRowCount()) > 0) { | 
 | 
                int               minSelIndex = ui.getLeadSelectionRow();  | 
 | 
                int               newIndex;  | 
 | 
 | 
 | 
                if(minSelIndex == -1)  | 
 | 
                    newIndex = 0;  | 
 | 
                else { | 
 | 
                      | 
 | 
                       node. */  | 
 | 
                    if(direction == 1) { | 
 | 
                        TreePath minSelPath = ui.getPathForRow(tree, minSelIndex);  | 
 | 
                        int childCount = tree.getModel().  | 
 | 
                            getChildCount(minSelPath.getLastPathComponent());  | 
 | 
                        newIndex = -1;  | 
 | 
                        if (!ui.isLeaf(minSelIndex)) { | 
 | 
                            if (!tree.isExpanded(minSelIndex)) { | 
 | 
                                ui.toggleExpandState(minSelPath);  | 
 | 
                            }  | 
 | 
                            else if (childCount > 0) { | 
 | 
                                newIndex = Math.min(minSelIndex + 1, rowCount - 1);  | 
 | 
                            }  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                      | 
 | 
                    else { | 
 | 
                        if(!ui.isLeaf(minSelIndex) &&  | 
 | 
                           tree.isExpanded(minSelIndex)) { | 
 | 
                            ui.toggleExpandState(ui.getPathForRow  | 
 | 
                                              (tree, minSelIndex));  | 
 | 
                            newIndex = -1;  | 
 | 
                        }  | 
 | 
                        else { | 
 | 
                            TreePath         path = ui.getPathForRow(tree,  | 
 | 
                                                                  minSelIndex);  | 
 | 
 | 
 | 
                            if(path != null && path.getPathCount() > 1) { | 
 | 
                                newIndex = ui.getRowForPath(tree, path.  | 
 | 
                                                         getParentPath());  | 
 | 
                            }  | 
 | 
                            else  | 
 | 
                                newIndex = -1;  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                if(newIndex != -1) { | 
 | 
                    if(changeSelection) { | 
 | 
                        tree.setSelectionInterval(newIndex, newIndex);  | 
 | 
                    }  | 
 | 
                    else { | 
 | 
                        ui.setLeadSelectionPath(ui.getPathForRow(  | 
 | 
                                                    tree, newIndex), true);  | 
 | 
                    }  | 
 | 
                    ui.ensureRowsAreVisible(newIndex, newIndex);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void moveSelectionToParent(JTree tree, BasicTreeUI ui) { | 
 | 
            int selRow = ui.getLeadSelectionRow();  | 
 | 
            TreePath path = ui.getPathForRow(tree, selRow);  | 
 | 
            if (path != null && path.getPathCount() > 1) { | 
 | 
                int  newIndex = ui.getRowForPath(tree, path.getParentPath());  | 
 | 
                if (newIndex != -1) { | 
 | 
                    tree.setSelectionInterval(newIndex, newIndex);  | 
 | 
                    ui.ensureRowsAreVisible(newIndex, newIndex);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void page(JTree tree, BasicTreeUI ui, int direction,  | 
 | 
                          boolean addToSelection, boolean changeSelection) { | 
 | 
 | 
 | 
              | 
 | 
            if (!addToSelection && !changeSelection &&  | 
 | 
                    tree.getSelectionModel().getSelectionMode() !=  | 
 | 
                        TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { | 
 | 
                changeSelection = true;  | 
 | 
            }  | 
 | 
 | 
 | 
            int           rowCount;  | 
 | 
 | 
 | 
            if((rowCount = ui.getRowCount(tree)) > 0 &&  | 
 | 
                           ui.treeSelectionModel != null) { | 
 | 
                Dimension         maxSize = tree.getSize();  | 
 | 
                TreePath          lead = ui.getLeadSelectionPath();  | 
 | 
                TreePath          newPath;  | 
 | 
                Rectangle         visRect = tree.getVisibleRect();  | 
 | 
 | 
 | 
                if(direction == -1) { | 
 | 
                      | 
 | 
                    newPath = ui.getClosestPathForLocation(tree, visRect.x,  | 
 | 
                                                         visRect.y);  | 
 | 
                    if(newPath.equals(lead)) { | 
 | 
                        visRect.y = Math.max(0, visRect.y - visRect.height);  | 
 | 
                        newPath = tree.getClosestPathForLocation(visRect.x,  | 
 | 
                                                                 visRect.y);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                else { | 
 | 
                      | 
 | 
                    visRect.y = Math.min(maxSize.height, visRect.y +  | 
 | 
                                         visRect.height - 1);  | 
 | 
                    newPath = tree.getClosestPathForLocation(visRect.x,  | 
 | 
                                                             visRect.y);  | 
 | 
                    if(newPath.equals(lead)) { | 
 | 
                        visRect.y = Math.min(maxSize.height, visRect.y +  | 
 | 
                                             visRect.height - 1);  | 
 | 
                        newPath = tree.getClosestPathForLocation(visRect.x,  | 
 | 
                                                                 visRect.y);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                Rectangle            newRect = ui.getPathBounds(tree, newPath);  | 
 | 
                if (newRect != null) { | 
 | 
                    newRect.x = visRect.x;  | 
 | 
                    newRect.width = visRect.width;  | 
 | 
                    if(direction == -1) { | 
 | 
                        newRect.height = visRect.height;  | 
 | 
                    }  | 
 | 
                    else { | 
 | 
                        newRect.y -= (visRect.height - newRect.height);  | 
 | 
                        newRect.height = visRect.height;  | 
 | 
                    }  | 
 | 
 | 
 | 
                    if(addToSelection) { | 
 | 
                        ui.extendSelection(newPath);  | 
 | 
                    }  | 
 | 
                    else if(changeSelection) { | 
 | 
                        tree.setSelectionPath(newPath);  | 
 | 
                    }  | 
 | 
                    else { | 
 | 
                        ui.setLeadSelectionPath(newPath, true);  | 
 | 
                    }  | 
 | 
                    tree.scrollRectToVisible(newRect);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void home(JTree tree, final BasicTreeUI ui, int direction,  | 
 | 
                          boolean addToSelection, boolean changeSelection) { | 
 | 
 | 
 | 
              | 
 | 
            if (!addToSelection && !changeSelection &&  | 
 | 
                    tree.getSelectionModel().getSelectionMode() !=  | 
 | 
                        TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) { | 
 | 
                changeSelection = true;  | 
 | 
            }  | 
 | 
 | 
 | 
            final int rowCount = ui.getRowCount(tree);  | 
 | 
 | 
 | 
            if (rowCount > 0) { | 
 | 
                if(direction == -1) { | 
 | 
                    ui.ensureRowsAreVisible(0, 0);  | 
 | 
                    if (addToSelection) { | 
 | 
                        TreePath        aPath = ui.getAnchorSelectionPath();  | 
 | 
                        int             aRow = (aPath == null) ? -1 :  | 
 | 
                                        ui.getRowForPath(tree, aPath);  | 
 | 
 | 
 | 
                        if (aRow == -1) { | 
 | 
                            tree.setSelectionInterval(0, 0);  | 
 | 
                        }  | 
 | 
                        else { | 
 | 
                            tree.setSelectionInterval(0, aRow);  | 
 | 
                            ui.setAnchorSelectionPath(aPath);  | 
 | 
                            ui.setLeadSelectionPath(ui.getPathForRow(tree, 0));  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    else if(changeSelection) { | 
 | 
                        tree.setSelectionInterval(0, 0);  | 
 | 
                    }  | 
 | 
                    else { | 
 | 
                        ui.setLeadSelectionPath(ui.getPathForRow(tree, 0),  | 
 | 
                                                true);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                else { | 
 | 
                    ui.ensureRowsAreVisible(rowCount - 1, rowCount - 1);  | 
 | 
                    if (addToSelection) { | 
 | 
                        TreePath        aPath = ui.getAnchorSelectionPath();  | 
 | 
                        int             aRow = (aPath == null) ? -1 :  | 
 | 
                                        ui.getRowForPath(tree, aPath);  | 
 | 
 | 
 | 
                        if (aRow == -1) { | 
 | 
                            tree.setSelectionInterval(rowCount - 1,  | 
 | 
                                                      rowCount -1);  | 
 | 
                        }  | 
 | 
                        else { | 
 | 
                            tree.setSelectionInterval(aRow, rowCount - 1);  | 
 | 
                            ui.setAnchorSelectionPath(aPath);  | 
 | 
                            ui.setLeadSelectionPath(ui.getPathForRow(tree,  | 
 | 
                                                               rowCount -1));  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    else if(changeSelection) { | 
 | 
                        tree.setSelectionInterval(rowCount - 1, rowCount - 1);  | 
 | 
                    }  | 
 | 
                    else { | 
 | 
                        ui.setLeadSelectionPath(ui.getPathForRow(tree,  | 
 | 
                                                          rowCount - 1), true);  | 
 | 
                    }  | 
 | 
                    if (ui.isLargeModel()){ | 
 | 
                        SwingUtilities.invokeLater(new Runnable() { | 
 | 
                            public void run() { | 
 | 
                                ui.ensureRowsAreVisible(rowCount - 1, rowCount - 1);  | 
 | 
                            }  | 
 | 
                        });  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
} // End of class BasicTreeUI  |