< prev index next >

src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTreeUI.java

Print this page




  56  */
  57 
  58 public class BasicTreeUI extends TreeUI
  59 {
  60     private static final StringBuilder BASELINE_COMPONENT_KEY =
  61         new StringBuilder("Tree.baselineComponent");
  62 
  63     // Old actions forward to an instance of this.
  64     private static final Actions SHARED_ACTION = new Actions();
  65 
  66     /**
  67      * The collapsed icon.
  68      */
  69     protected transient Icon        collapsedIcon;
  70     /**
  71      * The expanded icon.
  72      */
  73     protected transient Icon        expandedIcon;
  74 
  75     /**
  76       * Color used to draw hash marks.  If <code>null</code> no hash marks
  77       * will be drawn.
  78       */
  79     private Color hashColor;
  80 
  81     /** Distance between left margin and where vertical dashes will be
  82       * drawn. */
  83     protected int               leftChildIndent;
  84     /** Distance to add to leftChildIndent to determine where cell
  85       * contents will be drawn. */
  86     protected int               rightChildIndent;
  87     /** Total distance that will be indented.  The sum of leftChildIndent
  88       * and rightChildIndent. */
  89     protected int               totalChildIndent;
  90 
  91     /** Minimum preferred size. */
  92     protected Dimension         preferredMinSize;
  93 
  94     /** Index of the row that was last selected. */
  95     protected int               lastSelectedRow;
  96 


2107             if(isLargeModel()) {
2108                 if(componentListener == null) {
2109                     componentListener = createComponentListener();
2110                     if(componentListener != null)
2111                         tree.addComponentListener(componentListener);
2112                 }
2113             }
2114             else if(componentListener != null) {
2115                 tree.removeComponentListener(componentListener);
2116                 componentListener = null;
2117             }
2118         }
2119         else if(componentListener != null) {
2120             tree.removeComponentListener(componentListener);
2121             componentListener = null;
2122         }
2123     }
2124 
2125     /**
2126      * Marks the cached size as being invalid, and messages the
2127      * tree with <code>treeDidChange</code>.
2128      */
2129     protected void updateSize() {
2130         validCachedPreferredSize = false;
2131         tree.treeDidChange();
2132     }
2133 
2134     private void updateSize0() {
2135         validCachedPreferredSize = false;
2136         tree.revalidate();
2137     }
2138 
2139     /**
2140      * Updates the <code>preferredSize</code> instance variable,
2141      * which is returned from <code>getPreferredSize()</code>.<p>
2142      * For left to right orientations, the size is determined from the
2143      * current AbstractLayoutCache. For RTL orientations, the preferred size
2144      * becomes the width minus the minimum x position.
2145      */
2146     protected void updateCachedPreferredSize() {
2147         if(treeState != null) {
2148             Insets               i = tree.getInsets();
2149 
2150             if(isLargeModel()) {
2151                 Rectangle            visRect = tree.getVisibleRect();
2152 
2153                 if (visRect.x == 0 && visRect.y == 0 &&
2154                         visRect.width == 0 && visRect.height == 0 &&
2155                         tree.getVisibleRowCount() > 0) {
2156                     // The tree doesn't have a valid bounds yet. Calculate
2157                     // based on visible row count.
2158                     visRect.width = 1;
2159                     visRect.height = tree.getRowHeight() *
2160                             tree.getVisibleRowCount();
2161                 } else {


2327             return this.getPreferredMinSize();
2328         return new Dimension(0, 0);
2329     }
2330 
2331     /**
2332       * Returns the maximum size for this component, which will be the
2333       * preferred size if the instance is currently in a JTree, or 0, 0.
2334       */
2335     public Dimension getMaximumSize(JComponent c) {
2336         if(tree != null)
2337             return getPreferredSize(tree);
2338         if(this.getPreferredMinSize() != null)
2339             return this.getPreferredMinSize();
2340         return new Dimension(0, 0);
2341     }
2342 
2343 
2344     /**
2345      * Messages to stop the editing session. If the UI the receiver
2346      * is providing the look and feel for returns true from
2347      * <code>getInvokesStopCellEditing</code>, stopCellEditing will
2348      * invoked on the current editor. Then completeEditing will
2349      * be messaged with false, true, false to cancel any lingering
2350      * editing.
2351      */
2352     protected void completeEditing() {
2353         /* If should invoke stopCellEditing, try that */
2354         if(tree.getInvokesStopCellEditing() &&
2355            stopEditingInCompleteEditing && editingComponent != null) {
2356             cellEditor.stopCellEditing();
2357         }
2358         /* Invoke cancelCellEditing, this will do nothing if stopCellEditing
2359            was successful. */
2360         completeEditing(false, true, false);
2361     }
2362 
2363     /**
2364      * Stops the editing session. If {@code messageStop} is {@code true} the editor
2365      * is messaged with {@code stopEditing}, if {@code messageCancel}
2366      * is {@code true} the editor is messaged with {@code cancelEditing}.
2367      * If {@code messageTree} is {@code true} the {@code treeModel} is messaged


2813 
2814     /**
2815      * Updates the lead row of the selection.
2816      * @since 1.7
2817      */
2818     protected void updateLeadSelectionRow() {
2819         leadRow = getRowForPath(tree, getLeadSelectionPath());
2820     }
2821 
2822     /**
2823      * Returns the lead row of the selection.
2824      *
2825      * @return selection lead row
2826      * @since 1.7
2827      */
2828     protected int getLeadSelectionRow() {
2829         return leadRow;
2830     }
2831 
2832     /**
2833      * Extends the selection from the anchor to make <code>newLead</code>
2834      * the lead of the selection. This does not scroll.
2835      */
2836     private void extendSelection(TreePath newLead) {
2837         TreePath           aPath = getAnchorSelectionPath();
2838         int                aRow = (aPath == null) ? -1 :
2839                                   getRowForPath(tree, aPath);
2840         int                newIndex = getRowForPath(tree, newLead);
2841 
2842         if(aRow == -1) {
2843             tree.setSelectionRow(newIndex);
2844         }
2845         else {
2846             if(aRow < newIndex) {
2847                 tree.setSelectionInterval(aRow, newIndex);
2848             }
2849             else {
2850                 tree.setSelectionInterval(newIndex, aRow);
2851             }
2852             setAnchorSelectionPath(aPath);
2853             setLeadSelectionPath(newLead);
2854         }
2855     }
2856 
2857     /**
2858      * Invokes <code>repaint</code> on the JTree for the passed in TreePath,
2859      * <code>path</code>.
2860      */
2861     private void repaintPath(TreePath path) {
2862         if (path != null) {
2863             Rectangle bounds = getPathBounds(tree, path);
2864             if (bounds != null) {
2865                 tree.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
2866             }
2867         }
2868     }
2869 
2870     /**
2871      * Updates the TreeState in response to nodes expanding/collapsing.
2872      */
2873     public class TreeExpansionHandler implements TreeExpansionListener {
2874         // NOTE: This class exists only for backward compatibility. All
2875         // its functionality has been moved into Handler. If you need to add
2876         // new functionality add it to the Handler, but make sure this
2877         // class calls into the Handler.
2878 
2879         /**


3247 
3248     /**
3249      * Listener on the TreeSelectionModel, resets the row selection if
3250      * any of the properties of the model change.
3251      */
3252     public class SelectionModelPropertyChangeHandler implements
3253                       PropertyChangeListener {
3254 
3255         // NOTE: This class exists only for backward compatibility. All
3256         // its functionality has been moved into Handler. If you need to add
3257         // new functionality add it to the Handler, but make sure this
3258         // class calls into the Handler.
3259 
3260         public void propertyChange(PropertyChangeEvent event) {
3261             getHandler().propertyChange(event);
3262         }
3263     } // End of BasicTreeUI.SelectionModelPropertyChangeHandler
3264 
3265 
3266     /**
3267      * <code>TreeTraverseAction</code> is the action used for left/right keys.
3268      * Will toggle the expandedness of a node, as well as potentially
3269      * incrementing the selection.
3270      */
3271     @SuppressWarnings("serial") // Superclass is not serializable across versions
3272     public class TreeTraverseAction extends AbstractAction {
3273         /** Determines direction to traverse, 1 means expand, -1 means
3274           * collapse. */
3275         protected int direction;
3276         /** True if the selection is reset, false means only the lead path
3277          * changes. */
3278         private boolean changeSelection;
3279 
3280         /**
3281          * Constructs a new instance of {@code TreeTraverseAction}.
3282          *
3283          * @param direction the direction
3284          * @param name the name of action
3285          */
3286         public TreeTraverseAction(int direction, String name) {
3287             this(direction, name, true);


3684     }
3685 
3686 
3687     private class Handler implements CellEditorListener, FocusListener,
3688                   KeyListener, MouseListener, MouseMotionListener,
3689                   PropertyChangeListener, TreeExpansionListener,
3690                   TreeModelListener, TreeSelectionListener,
3691                   BeforeDrag {
3692         //
3693         // KeyListener
3694         //
3695         private String prefix = "";
3696         private String typedString = "";
3697         private long lastTime = 0L;
3698 
3699         /**
3700          * Invoked when a key has been typed.
3701          *
3702          * Moves the keyboard focus to the first element whose prefix matches the
3703          * sequence of alphanumeric keys pressed by the user with delay less
3704          * than value of <code>timeFactor</code> property (or 1000 milliseconds
3705          * if it is not defined). Subsequent same key presses move the keyboard
3706          * focus to the next object that starts with the same letter until another
3707          * key is pressed, then it is treated as the prefix with appropriate number
3708          * of the same letters followed by first typed another letter.
3709          */
3710         public void keyTyped(KeyEvent e) {
3711             // handle first letter navigation
3712             if(tree != null && tree.getRowCount()>0 && tree.hasFocus() &&
3713                tree.isEnabled()) {
3714                 if (e.isAltDown() || BasicGraphicsUtils.isMenuShortcutKeyDown(e) ||
3715                     isNavigationKey(e)) {
3716                     return;
3717                 }
3718                 boolean startingFromSelection = true;
3719 
3720                 char c = e.getKeyChar();
3721 
3722                 long time = e.getWhen();
3723                 int startingRow = tree.getLeadSelectionRow();
3724                 if (time - lastTime < timeFactor) {




  56  */
  57 
  58 public class BasicTreeUI extends TreeUI
  59 {
  60     private static final StringBuilder BASELINE_COMPONENT_KEY =
  61         new StringBuilder("Tree.baselineComponent");
  62 
  63     // Old actions forward to an instance of this.
  64     private static final Actions SHARED_ACTION = new Actions();
  65 
  66     /**
  67      * The collapsed icon.
  68      */
  69     protected transient Icon        collapsedIcon;
  70     /**
  71      * The expanded icon.
  72      */
  73     protected transient Icon        expandedIcon;
  74 
  75     /**
  76       * Color used to draw hash marks.  If {@code null} no hash marks
  77       * will be drawn.
  78       */
  79     private Color hashColor;
  80 
  81     /** Distance between left margin and where vertical dashes will be
  82       * drawn. */
  83     protected int               leftChildIndent;
  84     /** Distance to add to leftChildIndent to determine where cell
  85       * contents will be drawn. */
  86     protected int               rightChildIndent;
  87     /** Total distance that will be indented.  The sum of leftChildIndent
  88       * and rightChildIndent. */
  89     protected int               totalChildIndent;
  90 
  91     /** Minimum preferred size. */
  92     protected Dimension         preferredMinSize;
  93 
  94     /** Index of the row that was last selected. */
  95     protected int               lastSelectedRow;
  96 


2107             if(isLargeModel()) {
2108                 if(componentListener == null) {
2109                     componentListener = createComponentListener();
2110                     if(componentListener != null)
2111                         tree.addComponentListener(componentListener);
2112                 }
2113             }
2114             else if(componentListener != null) {
2115                 tree.removeComponentListener(componentListener);
2116                 componentListener = null;
2117             }
2118         }
2119         else if(componentListener != null) {
2120             tree.removeComponentListener(componentListener);
2121             componentListener = null;
2122         }
2123     }
2124 
2125     /**
2126      * Marks the cached size as being invalid, and messages the
2127      * tree with {@code treeDidChange}.
2128      */
2129     protected void updateSize() {
2130         validCachedPreferredSize = false;
2131         tree.treeDidChange();
2132     }
2133 
2134     private void updateSize0() {
2135         validCachedPreferredSize = false;
2136         tree.revalidate();
2137     }
2138 
2139     /**
2140      * Updates the {@code preferredSize} instance variable,
2141      * which is returned from {@code getPreferredSize()}.<p>
2142      * For left to right orientations, the size is determined from the
2143      * current AbstractLayoutCache. For RTL orientations, the preferred size
2144      * becomes the width minus the minimum x position.
2145      */
2146     protected void updateCachedPreferredSize() {
2147         if(treeState != null) {
2148             Insets               i = tree.getInsets();
2149 
2150             if(isLargeModel()) {
2151                 Rectangle            visRect = tree.getVisibleRect();
2152 
2153                 if (visRect.x == 0 && visRect.y == 0 &&
2154                         visRect.width == 0 && visRect.height == 0 &&
2155                         tree.getVisibleRowCount() > 0) {
2156                     // The tree doesn't have a valid bounds yet. Calculate
2157                     // based on visible row count.
2158                     visRect.width = 1;
2159                     visRect.height = tree.getRowHeight() *
2160                             tree.getVisibleRowCount();
2161                 } else {


2327             return this.getPreferredMinSize();
2328         return new Dimension(0, 0);
2329     }
2330 
2331     /**
2332       * Returns the maximum size for this component, which will be the
2333       * preferred size if the instance is currently in a JTree, or 0, 0.
2334       */
2335     public Dimension getMaximumSize(JComponent c) {
2336         if(tree != null)
2337             return getPreferredSize(tree);
2338         if(this.getPreferredMinSize() != null)
2339             return this.getPreferredMinSize();
2340         return new Dimension(0, 0);
2341     }
2342 
2343 
2344     /**
2345      * Messages to stop the editing session. If the UI the receiver
2346      * is providing the look and feel for returns true from
2347      * {@code getInvokesStopCellEditing}, stopCellEditing will
2348      * invoked on the current editor. Then completeEditing will
2349      * be messaged with false, true, false to cancel any lingering
2350      * editing.
2351      */
2352     protected void completeEditing() {
2353         /* If should invoke stopCellEditing, try that */
2354         if(tree.getInvokesStopCellEditing() &&
2355            stopEditingInCompleteEditing && editingComponent != null) {
2356             cellEditor.stopCellEditing();
2357         }
2358         /* Invoke cancelCellEditing, this will do nothing if stopCellEditing
2359            was successful. */
2360         completeEditing(false, true, false);
2361     }
2362 
2363     /**
2364      * Stops the editing session. If {@code messageStop} is {@code true} the editor
2365      * is messaged with {@code stopEditing}, if {@code messageCancel}
2366      * is {@code true} the editor is messaged with {@code cancelEditing}.
2367      * If {@code messageTree} is {@code true} the {@code treeModel} is messaged


2813 
2814     /**
2815      * Updates the lead row of the selection.
2816      * @since 1.7
2817      */
2818     protected void updateLeadSelectionRow() {
2819         leadRow = getRowForPath(tree, getLeadSelectionPath());
2820     }
2821 
2822     /**
2823      * Returns the lead row of the selection.
2824      *
2825      * @return selection lead row
2826      * @since 1.7
2827      */
2828     protected int getLeadSelectionRow() {
2829         return leadRow;
2830     }
2831 
2832     /**
2833      * Extends the selection from the anchor to make {@code newLead}
2834      * the lead of the selection. This does not scroll.
2835      */
2836     private void extendSelection(TreePath newLead) {
2837         TreePath           aPath = getAnchorSelectionPath();
2838         int                aRow = (aPath == null) ? -1 :
2839                                   getRowForPath(tree, aPath);
2840         int                newIndex = getRowForPath(tree, newLead);
2841 
2842         if(aRow == -1) {
2843             tree.setSelectionRow(newIndex);
2844         }
2845         else {
2846             if(aRow < newIndex) {
2847                 tree.setSelectionInterval(aRow, newIndex);
2848             }
2849             else {
2850                 tree.setSelectionInterval(newIndex, aRow);
2851             }
2852             setAnchorSelectionPath(aPath);
2853             setLeadSelectionPath(newLead);
2854         }
2855     }
2856 
2857     /**
2858      * Invokes {@code repaint} on the JTree for the passed in TreePath,
2859      * {@code path}.
2860      */
2861     private void repaintPath(TreePath path) {
2862         if (path != null) {
2863             Rectangle bounds = getPathBounds(tree, path);
2864             if (bounds != null) {
2865                 tree.repaint(bounds.x, bounds.y, bounds.width, bounds.height);
2866             }
2867         }
2868     }
2869 
2870     /**
2871      * Updates the TreeState in response to nodes expanding/collapsing.
2872      */
2873     public class TreeExpansionHandler implements TreeExpansionListener {
2874         // NOTE: This class exists only for backward compatibility. All
2875         // its functionality has been moved into Handler. If you need to add
2876         // new functionality add it to the Handler, but make sure this
2877         // class calls into the Handler.
2878 
2879         /**


3247 
3248     /**
3249      * Listener on the TreeSelectionModel, resets the row selection if
3250      * any of the properties of the model change.
3251      */
3252     public class SelectionModelPropertyChangeHandler implements
3253                       PropertyChangeListener {
3254 
3255         // NOTE: This class exists only for backward compatibility. All
3256         // its functionality has been moved into Handler. If you need to add
3257         // new functionality add it to the Handler, but make sure this
3258         // class calls into the Handler.
3259 
3260         public void propertyChange(PropertyChangeEvent event) {
3261             getHandler().propertyChange(event);
3262         }
3263     } // End of BasicTreeUI.SelectionModelPropertyChangeHandler
3264 
3265 
3266     /**
3267      * {@code TreeTraverseAction} is the action used for left/right keys.
3268      * Will toggle the expandedness of a node, as well as potentially
3269      * incrementing the selection.
3270      */
3271     @SuppressWarnings("serial") // Superclass is not serializable across versions
3272     public class TreeTraverseAction extends AbstractAction {
3273         /** Determines direction to traverse, 1 means expand, -1 means
3274           * collapse. */
3275         protected int direction;
3276         /** True if the selection is reset, false means only the lead path
3277          * changes. */
3278         private boolean changeSelection;
3279 
3280         /**
3281          * Constructs a new instance of {@code TreeTraverseAction}.
3282          *
3283          * @param direction the direction
3284          * @param name the name of action
3285          */
3286         public TreeTraverseAction(int direction, String name) {
3287             this(direction, name, true);


3684     }
3685 
3686 
3687     private class Handler implements CellEditorListener, FocusListener,
3688                   KeyListener, MouseListener, MouseMotionListener,
3689                   PropertyChangeListener, TreeExpansionListener,
3690                   TreeModelListener, TreeSelectionListener,
3691                   BeforeDrag {
3692         //
3693         // KeyListener
3694         //
3695         private String prefix = "";
3696         private String typedString = "";
3697         private long lastTime = 0L;
3698 
3699         /**
3700          * Invoked when a key has been typed.
3701          *
3702          * Moves the keyboard focus to the first element whose prefix matches the
3703          * sequence of alphanumeric keys pressed by the user with delay less
3704          * than value of {@code timeFactor} property (or 1000 milliseconds
3705          * if it is not defined). Subsequent same key presses move the keyboard
3706          * focus to the next object that starts with the same letter until another
3707          * key is pressed, then it is treated as the prefix with appropriate number
3708          * of the same letters followed by first typed another letter.
3709          */
3710         public void keyTyped(KeyEvent e) {
3711             // handle first letter navigation
3712             if(tree != null && tree.getRowCount()>0 && tree.hasFocus() &&
3713                tree.isEnabled()) {
3714                 if (e.isAltDown() || BasicGraphicsUtils.isMenuShortcutKeyDown(e) ||
3715                     isNavigationKey(e)) {
3716                     return;
3717                 }
3718                 boolean startingFromSelection = true;
3719 
3720                 char c = e.getKeyChar();
3721 
3722                 long time = e.getWhen();
3723                 int startingRow = tree.getLeadSelectionRow();
3724                 if (time - lastTime < timeFactor) {


< prev index next >