jdk/src/share/classes/javax/swing/plaf/synth/SynthTreeUI.java
changeset 4394 92a8ec883f5d
parent 2658 43e06bc950ec
child 4848 ffcc849b9351
equal deleted inserted replaced
4393:4e81657271ba 4394:92a8ec883f5d
    46 import javax.swing.tree.TreeCellEditor;
    46 import javax.swing.tree.TreeCellEditor;
    47 import javax.swing.tree.TreeCellRenderer;
    47 import javax.swing.tree.TreeCellRenderer;
    48 import javax.swing.tree.TreeModel;
    48 import javax.swing.tree.TreeModel;
    49 import javax.swing.tree.TreePath;
    49 import javax.swing.tree.TreePath;
    50 import sun.swing.plaf.synth.SynthIcon;
    50 import sun.swing.plaf.synth.SynthIcon;
    51 import sun.swing.plaf.synth.SynthUI;
       
    52 
    51 
    53 /**
    52 /**
    54  * Skinnable TreeUI.
    53  * Provides the Synth L&F UI delegate for
       
    54  * {@link javax.swing.JTree}.
    55  *
    55  *
    56  * @author Scott Violet
    56  * @author Scott Violet
       
    57  * @since 1.7
    57  */
    58  */
    58 class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener,
    59 public class SynthTreeUI extends BasicTreeUI
    59                                SynthUI {
    60                          implements PropertyChangeListener, SynthUI {
    60     private SynthStyle style;
    61     private SynthStyle style;
    61     private SynthStyle cellStyle;
    62     private SynthStyle cellStyle;
    62 
    63 
    63     private SynthContext paintContext;
    64     private SynthContext paintContext;
    64 
    65 
    65     private boolean drawHorizontalLines;
    66     private boolean drawHorizontalLines;
    66     private boolean drawVerticalLines;
    67     private boolean drawVerticalLines;
    67 
    68 
    68     private Object linesStyle;
    69     private Object linesStyle;
    69 
    70 
    70     private int leadRow;
       
    71 
       
    72     private int padding;
    71     private int padding;
    73 
    72 
    74     private boolean useTreeColors;
    73     private boolean useTreeColors;
    75 
    74 
    76     private Icon expandedIconWrapper;
    75     private Icon expandedIconWrapper = new ExpandedIconWrapper();
    77 
    76 
       
    77     /**
       
    78      * Creates a new UI object for the given component.
       
    79      *
       
    80      * @param x component to create UI object for
       
    81      * @return the UI object
       
    82      */
    78     public static ComponentUI createUI(JComponent x) {
    83     public static ComponentUI createUI(JComponent x) {
    79         return new SynthTreeUI();
    84         return new SynthTreeUI();
    80     }
    85     }
    81 
    86 
    82     SynthTreeUI() {
    87     /**
    83         expandedIconWrapper = new ExpandedIconWrapper();
    88      * @inheritDoc
    84     }
    89      */
    85 
       
    86     @Override
    90     @Override
    87     public Icon getExpandedIcon() {
    91     public Icon getExpandedIcon() {
    88         return expandedIconWrapper;
    92         return expandedIconWrapper;
    89     }
    93     }
    90 
    94 
       
    95     /**
       
    96      * @inheritDoc
       
    97      */
    91     @Override
    98     @Override
    92     protected void installDefaults() {
    99     protected void installDefaults() {
    93         updateStyle(tree);
   100         updateStyle(tree);
    94     }
   101     }
    95 
   102 
   146         context = getContext(tree, Region.TREE_CELL, ENABLED);
   153         context = getContext(tree, Region.TREE_CELL, ENABLED);
   147         cellStyle = SynthLookAndFeel.updateStyle(context, this);
   154         cellStyle = SynthLookAndFeel.updateStyle(context, this);
   148         context.dispose();
   155         context.dispose();
   149     }
   156     }
   150 
   157 
       
   158     /**
       
   159      * @inheritDoc
       
   160      */
   151     @Override
   161     @Override
   152     protected void installListeners() {
   162     protected void installListeners() {
   153         super.installListeners();
   163         super.installListeners();
   154         tree.addPropertyChangeListener(this);
   164         tree.addPropertyChangeListener(this);
   155     }
   165     }
   156 
   166 
       
   167     /**
       
   168      * @inheritDoc
       
   169      */
   157     @Override
   170     @Override
   158     public SynthContext getContext(JComponent c) {
   171     public SynthContext getContext(JComponent c) {
   159         return getContext(c, getComponentState(c));
   172         return getContext(c, SynthLookAndFeel.getComponentState(c));
   160     }
   173     }
   161 
   174 
   162     private SynthContext getContext(JComponent c, int state) {
   175     private SynthContext getContext(JComponent c, int state) {
   163         return SynthContext.getContext(SynthContext.class, c,
   176         return SynthContext.getContext(SynthContext.class, c,
   164                     SynthLookAndFeel.getRegion(c), style, state);
   177                     SynthLookAndFeel.getRegion(c), style, state);
   165     }
       
   166 
       
   167     private Region getRegion(JTree c) {
       
   168         return SynthLookAndFeel.getRegion(c);
       
   169     }
       
   170 
       
   171     private int getComponentState(JComponent c) {
       
   172         return SynthLookAndFeel.getComponentState(c);
       
   173     }
   178     }
   174 
   179 
   175     private SynthContext getContext(JComponent c, Region region) {
   180     private SynthContext getContext(JComponent c, Region region) {
   176         return getContext(c, region, getComponentState(c, region));
   181         return getContext(c, region, getComponentState(c, region));
   177     }
   182     }
   185         // Always treat the cell as selected, will be adjusted appropriately
   190         // Always treat the cell as selected, will be adjusted appropriately
   186         // when painted.
   191         // when painted.
   187         return ENABLED | SELECTED;
   192         return ENABLED | SELECTED;
   188     }
   193     }
   189 
   194 
       
   195     /**
       
   196      * @inheritDoc
       
   197      */
   190     @Override
   198     @Override
   191     protected TreeCellEditor createDefaultCellEditor() {
   199     protected TreeCellEditor createDefaultCellEditor() {
   192         TreeCellRenderer renderer = tree.getCellRenderer();
   200         TreeCellRenderer renderer = tree.getCellRenderer();
   193         DefaultTreeCellEditor editor;
   201         DefaultTreeCellEditor editor;
   194 
   202 
   200             editor = new SynthTreeCellEditor(tree, null);
   208             editor = new SynthTreeCellEditor(tree, null);
   201         }
   209         }
   202         return editor;
   210         return editor;
   203     }
   211     }
   204 
   212 
       
   213     /**
       
   214      * @inheritDoc
       
   215      */
   205     @Override
   216     @Override
   206     protected TreeCellRenderer createDefaultCellRenderer() {
   217     protected TreeCellRenderer createDefaultCellRenderer() {
   207         return new SynthTreeCellRenderer();
   218         return new SynthTreeCellRenderer();
   208     }
   219     }
   209 
   220 
       
   221     /**
       
   222      * @inheritDoc
       
   223      */
   210     @Override
   224     @Override
   211     protected void uninstallDefaults() {
   225     protected void uninstallDefaults() {
   212         SynthContext context = getContext(tree, ENABLED);
   226         SynthContext context = getContext(tree, ENABLED);
   213 
   227 
   214         style.uninstallDefaults(context);
   228         style.uninstallDefaults(context);
   224         if (tree.getTransferHandler() instanceof UIResource) {
   238         if (tree.getTransferHandler() instanceof UIResource) {
   225             tree.setTransferHandler(null);
   239             tree.setTransferHandler(null);
   226         }
   240         }
   227     }
   241     }
   228 
   242 
       
   243     /**
       
   244      * @inheritDoc
       
   245      */
   229     @Override
   246     @Override
   230     protected void uninstallListeners() {
   247     protected void uninstallListeners() {
   231         super.uninstallListeners();
   248         super.uninstallListeners();
   232         tree.removePropertyChangeListener(this);
   249         tree.removePropertyChangeListener(this);
   233     }
   250     }
   234 
   251 
       
   252     /**
       
   253      * @inheritDoc
       
   254      */
   235     @Override
   255     @Override
   236     public void update(Graphics g, JComponent c) {
   256     public void update(Graphics g, JComponent c) {
   237         SynthContext context = getContext(c);
   257         SynthContext context = getContext(c);
   238 
   258 
   239         SynthLookAndFeel.update(context, g);
   259         SynthLookAndFeel.update(context, g);
   241                           g, 0, 0, c.getWidth(), c.getHeight());
   261                           g, 0, 0, c.getWidth(), c.getHeight());
   242         paint(context, g);
   262         paint(context, g);
   243         context.dispose();
   263         context.dispose();
   244     }
   264     }
   245 
   265 
       
   266     /**
       
   267      * @inheritDoc
       
   268      */
       
   269     @Override
   246     public void paintBorder(SynthContext context, Graphics g, int x,
   270     public void paintBorder(SynthContext context, Graphics g, int x,
   247                             int y, int w, int h) {
   271                             int y, int w, int h) {
   248         context.getPainter().paintTreeBorder(context, g, x, y, w, h);
   272         context.getPainter().paintTreeBorder(context, g, x, y, w, h);
   249     }
   273     }
   250 
   274 
       
   275     /**
       
   276      * @inheritDoc
       
   277      */
   251     @Override
   278     @Override
   252     public void paint(Graphics g, JComponent c) {
   279     public void paint(Graphics g, JComponent c) {
   253         SynthContext context = getContext(c);
   280         SynthContext context = getContext(c);
   254 
   281 
   255         paint(context, g);
   282         paint(context, g);
   256         context.dispose();
   283         context.dispose();
   257     }
   284     }
   258 
   285 
   259     private void updateLeadRow() {
   286     /**
   260         leadRow = getRowForPath(tree, tree.getLeadSelectionPath());
   287      * Paints the specified component.
   261     }
   288      *
   262 
   289      * @param context context for the component being painted
       
   290      * @param g {@code Graphics} object used for painting
       
   291      */
   263     protected void paint(SynthContext context, Graphics g) {
   292     protected void paint(SynthContext context, Graphics g) {
   264         paintContext = context;
   293         paintContext = context;
   265 
   294 
   266         updateLeadRow();
   295         updateLeadSelectionRow();
   267 
   296 
   268         Rectangle paintBounds = g.getClipBounds();
   297         Rectangle paintBounds = g.getClipBounds();
   269         Insets insets = tree.getInsets();
   298         Insets insets = tree.getInsets();
   270         TreePath initialPath = getClosestPathForLocation(tree, 0,
   299         TreePath initialPath = getClosestPathForLocation(tree, 0,
   271                                                          paintBounds.y);
   300                                                          paintBounds.y);
   286 
   315 
   287             boolean done = false;
   316             boolean done = false;
   288             boolean isExpanded;
   317             boolean isExpanded;
   289             boolean hasBeenExpanded;
   318             boolean hasBeenExpanded;
   290             boolean isLeaf;
   319             boolean isLeaf;
   291             Rectangle boundsBuffer = new Rectangle();
       
   292             Rectangle rowBounds = new Rectangle(0, 0, tree.getWidth(),0);
   320             Rectangle rowBounds = new Rectangle(0, 0, tree.getWidth(),0);
   293             Rectangle bounds;
   321             Rectangle bounds;
   294             TreePath path;
   322             TreePath path;
   295             TreeCellRenderer renderer = tree.getCellRenderer();
   323             TreeCellRenderer renderer = tree.getCellRenderer();
   296             DefaultTreeCellRenderer dtcr = (renderer instanceof
   324             DefaultTreeCellRenderer dtcr = (renderer instanceof
   390 
   418 
   391         // Empty out the renderer pane, allowing renderers to be gc'ed.
   419         // Empty out the renderer pane, allowing renderers to be gc'ed.
   392         rendererPane.removeAll();
   420         rendererPane.removeAll();
   393     }
   421     }
   394 
   422 
   395     private boolean isDropLine(JTree.DropLocation loc) {
       
   396         return loc != null && loc.getPath() != null && loc.getChildIndex() != -1;
       
   397     }
       
   398 
       
   399     private void paintDropLine(Graphics g) {
       
   400         JTree.DropLocation loc = tree.getDropLocation();
       
   401         if (!isDropLine(loc)) {
       
   402             return;
       
   403         }
       
   404 
       
   405         Color c = (Color)style.get(paintContext, "Tree.dropLineColor");
       
   406         if (c != null) {
       
   407             g.setColor(c);
       
   408             Rectangle rect = getDropLineRect(loc);
       
   409             g.fillRect(rect.x, rect.y, rect.width, rect.height);
       
   410         }
       
   411     }
       
   412 
       
   413     private Rectangle getDropLineRect(JTree.DropLocation loc) {
       
   414         Rectangle rect;
       
   415         TreePath path = loc.getPath();
       
   416         int index = loc.getChildIndex();
       
   417         boolean ltr = tree.getComponentOrientation().isLeftToRight();
       
   418 
       
   419         Insets insets = tree.getInsets();
       
   420 
       
   421         if (tree.getRowCount() == 0) {
       
   422             rect = new Rectangle(insets.left,
       
   423                                  insets.top,
       
   424                                  tree.getWidth() - insets.left - insets.right,
       
   425                                  0);
       
   426         } else {
       
   427             int row = tree.getRowForPath(path);
       
   428             TreeModel model = getModel();
       
   429             Object root = model.getRoot();
       
   430 
       
   431             if (path.getLastPathComponent() == root
       
   432                     && index >= model.getChildCount(root)) {
       
   433 
       
   434                 rect = tree.getRowBounds(tree.getRowCount() - 1);
       
   435                 rect.y = rect.y + rect.height;
       
   436                 Rectangle xRect;
       
   437 
       
   438                 if (!tree.isRootVisible()) {
       
   439                     xRect = tree.getRowBounds(0);
       
   440                 } else if (model.getChildCount(root) == 0){
       
   441                     xRect = tree.getRowBounds(0);
       
   442                     xRect.x += totalChildIndent;
       
   443                     xRect.width -= totalChildIndent + totalChildIndent;
       
   444                 } else {
       
   445                     TreePath lastChildPath = path.pathByAddingChild(
       
   446                         model.getChild(root, model.getChildCount(root) - 1));
       
   447                     xRect = tree.getPathBounds(lastChildPath);
       
   448                 }
       
   449 
       
   450                 rect.x = xRect.x;
       
   451                 rect.width = xRect.width;
       
   452             } else {
       
   453                 rect = tree.getPathBounds(path.pathByAddingChild(
       
   454                     model.getChild(path.getLastPathComponent(), index)));
       
   455             }
       
   456         }
       
   457 
       
   458         if (rect.y != 0) {
       
   459             rect.y--;
       
   460         }
       
   461 
       
   462         if (!ltr) {
       
   463             rect.x = rect.x + rect.width - 100;
       
   464         }
       
   465 
       
   466         rect.width = 100;
       
   467         rect.height = 2;
       
   468 
       
   469         return rect;
       
   470     }
       
   471 
       
   472     private void configureRenderer(SynthContext context) {
   423     private void configureRenderer(SynthContext context) {
   473         TreeCellRenderer renderer = tree.getCellRenderer();
   424         TreeCellRenderer renderer = tree.getCellRenderer();
   474 
   425 
   475         if (renderer instanceof DefaultTreeCellRenderer) {
   426         if (renderer instanceof DefaultTreeCellRenderer) {
   476             DefaultTreeCellRenderer r = (DefaultTreeCellRenderer)renderer;
   427             DefaultTreeCellRenderer r = (DefaultTreeCellRenderer)renderer;
   500                                   context, ColorType.TEXT_BACKGROUND));
   451                                   context, ColorType.TEXT_BACKGROUND));
   501             }
   452             }
   502         }
   453         }
   503     }
   454     }
   504 
   455 
       
   456     /**
       
   457      * @inheritDoc
       
   458      */
   505     @Override
   459     @Override
   506     protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
   460     protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
   507                                             Insets insets, Rectangle bounds,
   461                                             Insets insets, Rectangle bounds,
   508                                             TreePath path, int row,
   462                                             TreePath path, int row,
   509                                             boolean isExpanded,
   463                                             boolean isExpanded,
   514                                            path, row, isExpanded,
   468                                            path, row, isExpanded,
   515                                            hasBeenExpanded, isLeaf);
   469                                            hasBeenExpanded, isLeaf);
   516         }
   470         }
   517     }
   471     }
   518 
   472 
       
   473     /**
       
   474      * @inheritDoc
       
   475      */
   519     @Override
   476     @Override
   520     protected void paintHorizontalLine(Graphics g, JComponent c, int y,
   477     protected void paintHorizontalLine(Graphics g, JComponent c, int y,
   521                                       int left, int right) {
   478                                       int left, int right) {
   522         paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
   479         paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
   523             paintContext, "Tree.horizontalLine", g, left, y, right, y, linesStyle);
   480             paintContext, "Tree.horizontalLine", g, left, y, right, y, linesStyle);
   524     }
   481     }
   525 
   482 
       
   483     /**
       
   484      * @inheritDoc
       
   485      */
   526     @Override
   486     @Override
   527     protected void paintVerticalPartOfLeg(Graphics g,
   487     protected void paintVerticalPartOfLeg(Graphics g,
   528                                           Rectangle clipBounds, Insets insets,
   488                                           Rectangle clipBounds, Insets insets,
   529                                           TreePath path) {
   489                                           TreePath path) {
   530         if (drawVerticalLines) {
   490         if (drawVerticalLines) {
   531             super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
   491             super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
   532         }
   492         }
   533     }
   493     }
   534 
   494 
       
   495     /**
       
   496      * @inheritDoc
       
   497      */
   535     @Override
   498     @Override
   536     protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
   499     protected void paintVerticalLine(Graphics g, JComponent c, int x, int top,
   537                                     int bottom) {
   500                                     int bottom) {
   538         paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
   501         paintContext.getStyle().getGraphicsUtils(paintContext).drawLine(
   539             paintContext, "Tree.verticalLine", g, x, top, x, bottom, linesStyle);
   502             paintContext, "Tree.verticalLine", g, x, top, x, bottom, linesStyle);
   540     }
   503     }
   541 
   504 
   542     protected void paintRow(TreeCellRenderer renderer,
   505     private void paintRow(TreeCellRenderer renderer,
   543                DefaultTreeCellRenderer dtcr, SynthContext treeContext,
   506                DefaultTreeCellRenderer dtcr, SynthContext treeContext,
   544                SynthContext cellContext, Graphics g, Rectangle clipBounds,
   507                SynthContext cellContext, Graphics g, Rectangle clipBounds,
   545                Insets insets, Rectangle bounds, Rectangle rowBounds,
   508                Insets insets, Rectangle bounds, Rectangle rowBounds,
   546                TreePath path, int row, boolean isExpanded,
   509                TreePath path, int row, boolean isExpanded,
   547                boolean hasBeenExpanded, boolean isLeaf) {
   510                boolean hasBeenExpanded, boolean isLeaf) {
   556         int state = ENABLED;
   519         int state = ENABLED;
   557         if (selected || isDrop) {
   520         if (selected || isDrop) {
   558             state |= SELECTED;
   521             state |= SELECTED;
   559         }
   522         }
   560 
   523 
   561         if (tree.isFocusOwner() && row == leadRow) {
   524         if (tree.isFocusOwner() && row == getLeadSelectionRow()) {
   562             state |= FOCUSED;
   525             state |= FOCUSED;
   563         }
   526         }
   564 
   527 
   565         cellContext.setComponentState(state);
   528         cellContext.setComponentState(state);
   566 
   529 
   581         }
   544         }
   582 
   545 
   583         int leadIndex;
   546         int leadIndex;
   584 
   547 
   585         if (tree.hasFocus()) {
   548         if (tree.hasFocus()) {
   586             leadIndex = leadRow;
   549             leadIndex = getLeadSelectionRow();
   587         }
   550         }
   588         else {
   551         else {
   589             leadIndex = -1;
   552             leadIndex = -1;
   590         }
   553         }
   591 
   554 
   623         super.paintExpandControl(g, clipBounds, insets, bounds, path, row,
   586         super.paintExpandControl(g, clipBounds, insets, bounds, path, row,
   624                 isExpanded, hasBeenExpanded, isLeaf);
   587                 isExpanded, hasBeenExpanded, isLeaf);
   625         paintContext.setComponentState(state);
   588         paintContext.setComponentState(state);
   626     }
   589     }
   627 
   590 
       
   591     /**
       
   592      * @inheritDoc
       
   593      */
   628     @Override
   594     @Override
   629     protected void drawCentered(Component c, Graphics graphics, Icon icon,
   595     protected void drawCentered(Component c, Graphics graphics, Icon icon,
   630                                 int x, int y) {
   596                                 int x, int y) {
   631         int w = SynthIcon.getIconWidth(icon, paintContext);
   597         int w = SynthIcon.getIconWidth(icon, paintContext);
   632         int h = SynthIcon.getIconHeight(icon, paintContext);
   598         int h = SynthIcon.getIconHeight(icon, paintContext);
   634         SynthIcon.paintIcon(icon, paintContext, graphics,
   600         SynthIcon.paintIcon(icon, paintContext, graphics,
   635                             findCenteredX(x, w),
   601                             findCenteredX(x, w),
   636                             y - h/2, w, h);
   602                             y - h/2, w, h);
   637     }
   603     }
   638 
   604 
       
   605     /**
       
   606      * @inheritDoc
       
   607      */
       
   608     @Override
   639     public void propertyChange(PropertyChangeEvent event) {
   609     public void propertyChange(PropertyChangeEvent event) {
   640         if (SynthLookAndFeel.shouldUpdateStyle(event)) {
   610         if (SynthLookAndFeel.shouldUpdateStyle(event)) {
   641             updateStyle((JTree)event.getSource());
   611             updateStyle((JTree)event.getSource());
   642         }
   612         }
   643 
   613 
   644         if ("dropLocation" == event.getPropertyName()) {
   614         if ("dropLocation" == event.getPropertyName()) {
   645             JTree.DropLocation oldValue = (JTree.DropLocation)event.getOldValue();
   615             JTree.DropLocation oldValue = (JTree.DropLocation)event.getOldValue();
   646             repaintDropLocation(oldValue);
   616             repaintDropLocation(oldValue);
   647             repaintDropLocation(tree.getDropLocation());
   617             repaintDropLocation(tree.getDropLocation());
       
   618         }
       
   619     }
       
   620 
       
   621     /**
       
   622      * @inheritDoc
       
   623      */
       
   624     @Override
       
   625     protected void paintDropLine(Graphics g) {
       
   626         JTree.DropLocation loc = tree.getDropLocation();
       
   627         if (!isDropLine(loc)) {
       
   628             return;
       
   629         }
       
   630 
       
   631         Color c = (Color)style.get(paintContext, "Tree.dropLineColor");
       
   632         if (c != null) {
       
   633             g.setColor(c);
       
   634             Rectangle rect = getDropLineRect(loc);
       
   635             g.fillRect(rect.x, rect.y, rect.width, rect.height);
   648         }
   636         }
   649     }
   637     }
   650 
   638 
   651     private void repaintDropLocation(JTree.DropLocation loc) {
   639     private void repaintDropLocation(JTree.DropLocation loc) {
   652         if (loc == null) {
   640         if (loc == null) {
   668         if (r != null) {
   656         if (r != null) {
   669             tree.repaint(r);
   657             tree.repaint(r);
   670         }
   658         }
   671     }
   659     }
   672 
   660 
       
   661     /**
       
   662      * @inheritDoc
       
   663      */
   673     @Override
   664     @Override
   674     protected int getRowX(int row, int depth) {
   665     protected int getRowX(int row, int depth) {
   675         return super.getRowX(row, depth) + padding;
   666         return super.getRowX(row, depth) + padding;
   676     }
   667     }
   677 
   668