1 /* 2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing.plaf.synth; 26 27 import java.awt.Color; 28 import java.awt.Component; 29 import java.awt.Graphics; 30 import java.awt.Insets; 31 import java.awt.Rectangle; 32 import java.beans.PropertyChangeEvent; 33 import java.beans.PropertyChangeListener; 34 import java.util.Enumeration; 35 import javax.swing.DefaultCellEditor; 36 import javax.swing.Icon; 37 import javax.swing.JComponent; 38 import javax.swing.JTextField; 39 import javax.swing.JTree; 40 import javax.swing.LookAndFeel; 41 import javax.swing.plaf.ComponentUI; 42 import javax.swing.plaf.UIResource; 43 import javax.swing.plaf.basic.BasicTreeUI; 44 import javax.swing.tree.DefaultTreeCellEditor; 45 import javax.swing.tree.DefaultTreeCellRenderer; 46 import javax.swing.tree.TreeCellEditor; 47 import javax.swing.tree.TreeCellRenderer; 48 import javax.swing.tree.TreeModel; 49 import javax.swing.tree.TreePath; 50 import sun.swing.plaf.synth.SynthIcon; 51 52 /** 53 * Provides the Synth L&F UI delegate for 54 * {@link javax.swing.JTree}. 55 * 56 * @author Scott Violet 57 * @since 1.7 58 */ 59 public class SynthTreeUI extends BasicTreeUI 60 implements PropertyChangeListener, SynthUI { 61 private SynthStyle style; 62 private SynthStyle cellStyle; 63 64 private SynthContext paintContext; 65 66 private boolean drawHorizontalLines; 67 private boolean drawVerticalLines; 68 69 private Object linesStyle; 70 71 private int padding; 72 73 private boolean useTreeColors; 74 75 private Icon expandedIconWrapper = new ExpandedIconWrapper(); 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 */ 83 public static ComponentUI createUI(JComponent x) { 84 return new SynthTreeUI(); 85 } 86 87 /** 88 * {@inheritDoc} 89 */ 90 @Override 91 public Icon getExpandedIcon() { 92 return expandedIconWrapper; 93 } 94 95 /** 96 * {@inheritDoc} 97 */ 98 @Override 99 protected void installDefaults() { 100 updateStyle(tree); 101 } 102 103 private void updateStyle(JTree tree) { 104 SynthContext context = getContext(tree, ENABLED); 105 SynthStyle oldStyle = style; 106 107 style = SynthLookAndFeel.updateStyle(context, this); 108 if (style != oldStyle) { 109 Object value; 110 111 setExpandedIcon(style.getIcon(context, "Tree.expandedIcon")); 112 setCollapsedIcon(style.getIcon(context, "Tree.collapsedIcon")); 113 114 setLeftChildIndent(style.getInt(context, "Tree.leftChildIndent", 115 0)); 116 setRightChildIndent(style.getInt(context, "Tree.rightChildIndent", 117 0)); 118 119 drawHorizontalLines = style.getBoolean( 120 context, "Tree.drawHorizontalLines",true); 121 drawVerticalLines = style.getBoolean( 122 context, "Tree.drawVerticalLines", true); 123 linesStyle = style.get(context, "Tree.linesStyle"); 124 125 value = style.get(context, "Tree.rowHeight"); 126 if (value != null) { 127 LookAndFeel.installProperty(tree, "rowHeight", value); 128 } 129 130 value = style.get(context, "Tree.scrollsOnExpand"); 131 LookAndFeel.installProperty(tree, "scrollsOnExpand", 132 value != null? value : Boolean.TRUE); 133 134 padding = style.getInt(context, "Tree.padding", 0); 135 136 largeModel = (tree.isLargeModel() && tree.getRowHeight() > 0); 137 138 useTreeColors = style.getBoolean(context, 139 "Tree.rendererUseTreeColors", true); 140 141 Boolean showsRootHandles = style.getBoolean( 142 context, "Tree.showsRootHandles", Boolean.TRUE); 143 LookAndFeel.installProperty( 144 tree, JTree.SHOWS_ROOT_HANDLES_PROPERTY, showsRootHandles); 145 146 if (oldStyle != null) { 147 uninstallKeyboardActions(); 148 installKeyboardActions(); 149 } 150 } 151 context.dispose(); 152 153 context = getContext(tree, Region.TREE_CELL, ENABLED); 154 cellStyle = SynthLookAndFeel.updateStyle(context, this); 155 context.dispose(); 156 } 157 158 /** 159 * {@inheritDoc} 160 */ 161 @Override 162 protected void installListeners() { 163 super.installListeners(); 164 tree.addPropertyChangeListener(this); 165 } 166 167 /** 168 * {@inheritDoc} 169 */ 170 @Override 171 public SynthContext getContext(JComponent c) { 172 return getContext(c, SynthLookAndFeel.getComponentState(c)); 173 } 174 175 private SynthContext getContext(JComponent c, int state) { 176 return SynthContext.getContext(SynthContext.class, c, 177 SynthLookAndFeel.getRegion(c), style, state); 178 } 179 180 private SynthContext getContext(JComponent c, Region region) { 181 return getContext(c, region, getComponentState(c, region)); 182 } 183 184 private SynthContext getContext(JComponent c, Region region, int state) { 185 return SynthContext.getContext(SynthContext.class, c, 186 region, cellStyle, state); 187 } 188 189 private int getComponentState(JComponent c, Region region) { 190 // Always treat the cell as selected, will be adjusted appropriately 191 // when painted. 192 return ENABLED | SELECTED; 193 } 194 195 /** 196 * {@inheritDoc} 197 */ 198 @Override 199 protected TreeCellEditor createDefaultCellEditor() { 200 TreeCellRenderer renderer = tree.getCellRenderer(); 201 DefaultTreeCellEditor editor; 202 203 if(renderer != null && (renderer instanceof DefaultTreeCellRenderer)) { 204 editor = new SynthTreeCellEditor(tree, (DefaultTreeCellRenderer) 205 renderer); 206 } 207 else { 208 editor = new SynthTreeCellEditor(tree, null); 209 } 210 return editor; 211 } 212 213 /** 214 * {@inheritDoc} 215 */ 216 @Override 217 protected TreeCellRenderer createDefaultCellRenderer() { 218 return new SynthTreeCellRenderer(); 219 } 220 221 /** 222 * {@inheritDoc} 223 */ 224 @Override 225 protected void uninstallDefaults() { 226 SynthContext context = getContext(tree, ENABLED); 227 228 style.uninstallDefaults(context); 229 context.dispose(); 230 style = null; 231 232 context = getContext(tree, Region.TREE_CELL, ENABLED); 233 cellStyle.uninstallDefaults(context); 234 context.dispose(); 235 cellStyle = null; 236 237 238 if (tree.getTransferHandler() instanceof UIResource) { 239 tree.setTransferHandler(null); 240 } 241 } 242 243 /** 244 * {@inheritDoc} 245 */ 246 @Override 247 protected void uninstallListeners() { 248 super.uninstallListeners(); 249 tree.removePropertyChangeListener(this); 250 } 251 252 /** 253 * Notifies this UI delegate to repaint the specified component. 254 * This method paints the component background, then calls 255 * the {@link #paint(SynthContext,Graphics)} method. 256 * 257 * <p>In general, this method does not need to be overridden by subclasses. 258 * All Look and Feel rendering code should reside in the {@code paint} method. 259 * 260 * @param g the {@code Graphics} object used for painting 261 * @param c the component being painted 262 * @see #paint(SynthContext,Graphics) 263 */ 264 @Override 265 public void update(Graphics g, JComponent c) { 266 SynthContext context = getContext(c); 267 268 SynthLookAndFeel.update(context, g); 269 context.getPainter().paintTreeBackground(context, 270 g, 0, 0, c.getWidth(), c.getHeight()); 271 paint(context, g); 272 context.dispose(); 273 } 274 275 /** 276 * {@inheritDoc} 277 */ 278 @Override 279 public void paintBorder(SynthContext context, Graphics g, int x, 280 int y, int w, int h) { 281 context.getPainter().paintTreeBorder(context, g, x, y, w, h); 282 } 283 284 /** 285 * Paints the specified component according to the Look and Feel. 286 * <p>This method is not used by Synth Look and Feel. 287 * Painting is handled by the {@link #paint(SynthContext,Graphics)} method. 288 * 289 * @param g the {@code Graphics} object used for painting 290 * @param c the component being painted 291 * @see #paint(SynthContext,Graphics) 292 */ 293 @Override 294 public void paint(Graphics g, JComponent c) { 295 SynthContext context = getContext(c); 296 297 paint(context, g); 298 context.dispose(); 299 } 300 301 /** 302 * Paints the specified component. 303 * 304 * @param context context for the component being painted 305 * @param g the {@code Graphics} object used for painting 306 * @see #update(Graphics,JComponent) 307 */ 308 protected void paint(SynthContext context, Graphics g) { 309 paintContext = context; 310 311 updateLeadSelectionRow(); 312 313 Rectangle paintBounds = g.getClipBounds(); 314 Insets insets = tree.getInsets(); 315 TreePath initialPath = getClosestPathForLocation(tree, 0, 316 paintBounds.y); 317 Enumeration paintingEnumerator = treeState.getVisiblePathsFrom 318 (initialPath); 319 int row = treeState.getRowForPath(initialPath); 320 int endY = paintBounds.y + paintBounds.height; 321 TreeModel treeModel = tree.getModel(); 322 SynthContext cellContext = getContext(tree, Region.TREE_CELL); 323 324 drawingCache.clear(); 325 326 setHashColor(context.getStyle().getColor(context, 327 ColorType.FOREGROUND)); 328 329 if (paintingEnumerator != null) { 330 // First pass, draw the rows 331 332 boolean done = false; 333 boolean isExpanded; 334 boolean hasBeenExpanded; 335 boolean isLeaf; 336 Rectangle rowBounds = new Rectangle(0, 0, tree.getWidth(),0); 337 Rectangle bounds; 338 TreePath path; 339 TreeCellRenderer renderer = tree.getCellRenderer(); 340 DefaultTreeCellRenderer dtcr = (renderer instanceof 341 DefaultTreeCellRenderer) ? (DefaultTreeCellRenderer) 342 renderer : null; 343 344 configureRenderer(cellContext); 345 while (!done && paintingEnumerator.hasMoreElements()) { 346 path = (TreePath)paintingEnumerator.nextElement(); 347 bounds = getPathBounds(tree, path); 348 if ((path != null) && (bounds != null)) { 349 isLeaf = treeModel.isLeaf(path.getLastPathComponent()); 350 if (isLeaf) { 351 isExpanded = hasBeenExpanded = false; 352 } 353 else { 354 isExpanded = treeState.getExpandedState(path); 355 hasBeenExpanded = tree.hasBeenExpanded(path); 356 } 357 rowBounds.y = bounds.y; 358 rowBounds.height = bounds.height; 359 paintRow(renderer, dtcr, context, cellContext, g, 360 paintBounds, insets, bounds, rowBounds, path, 361 row, isExpanded, hasBeenExpanded, isLeaf); 362 if ((bounds.y + bounds.height) >= endY) { 363 done = true; 364 } 365 } 366 else { 367 done = true; 368 } 369 row++; 370 } 371 372 // Draw the connecting lines and controls. 373 // Find each parent and have them draw a line to their last child 374 boolean rootVisible = tree.isRootVisible(); 375 TreePath parentPath = initialPath; 376 parentPath = parentPath.getParentPath(); 377 while (parentPath != null) { 378 paintVerticalPartOfLeg(g, paintBounds, insets, parentPath); 379 drawingCache.put(parentPath, Boolean.TRUE); 380 parentPath = parentPath.getParentPath(); 381 } 382 done = false; 383 paintingEnumerator = treeState.getVisiblePathsFrom(initialPath); 384 while (!done && paintingEnumerator.hasMoreElements()) { 385 path = (TreePath)paintingEnumerator.nextElement(); 386 bounds = getPathBounds(tree, path); 387 if ((path != null) && (bounds != null)) { 388 isLeaf = treeModel.isLeaf(path.getLastPathComponent()); 389 if (isLeaf) { 390 isExpanded = hasBeenExpanded = false; 391 } 392 else { 393 isExpanded = treeState.getExpandedState(path); 394 hasBeenExpanded = tree.hasBeenExpanded(path); 395 } 396 // See if the vertical line to the parent has been drawn. 397 parentPath = path.getParentPath(); 398 if (parentPath != null) { 399 if (drawingCache.get(parentPath) == null) { 400 paintVerticalPartOfLeg(g, paintBounds, insets, 401 parentPath); 402 drawingCache.put(parentPath, Boolean.TRUE); 403 } 404 paintHorizontalPartOfLeg(g, 405 paintBounds, insets, bounds, 406 path, row, isExpanded, 407 hasBeenExpanded, isLeaf); 408 } 409 else if (rootVisible && row == 0) { 410 paintHorizontalPartOfLeg(g, 411 paintBounds, insets, bounds, 412 path, row, isExpanded, 413 hasBeenExpanded, isLeaf); 414 } 415 if (shouldPaintExpandControl(path, row, isExpanded, 416 hasBeenExpanded, isLeaf)) { 417 paintExpandControl(g, paintBounds, 418 insets, bounds, path, row, 419 isExpanded, hasBeenExpanded,isLeaf); 420 } 421 if ((bounds.y + bounds.height) >= endY) { 422 done = true; 423 } 424 } 425 else { 426 done = true; 427 } 428 row++; 429 } 430 } 431 cellContext.dispose(); 432 433 paintDropLine(g); 434 435 // Empty out the renderer pane, allowing renderers to be gc'ed. 436 rendererPane.removeAll(); 437 438 paintContext = null; 439 } 440 441 private void configureRenderer(SynthContext context) { 442 TreeCellRenderer renderer = tree.getCellRenderer(); 443 444 if (renderer instanceof DefaultTreeCellRenderer) { 445 DefaultTreeCellRenderer r = (DefaultTreeCellRenderer)renderer; 446 SynthStyle style = context.getStyle(); 447 448 context.setComponentState(ENABLED | SELECTED); 449 Color color = r.getTextSelectionColor(); 450 if (color == null || (color instanceof UIResource)) { 451 r.setTextSelectionColor(style.getColor( 452 context, ColorType.TEXT_FOREGROUND)); 453 } 454 color = r.getBackgroundSelectionColor(); 455 if (color == null || (color instanceof UIResource)) { 456 r.setBackgroundSelectionColor(style.getColor( 457 context, ColorType.TEXT_BACKGROUND)); 458 } 459 460 context.setComponentState(ENABLED); 461 color = r.getTextNonSelectionColor(); 462 if (color == null || color instanceof UIResource) { 463 r.setTextNonSelectionColor(style.getColorForState( 464 context, ColorType.TEXT_FOREGROUND)); 465 } 466 color = r.getBackgroundNonSelectionColor(); 467 if (color == null || color instanceof UIResource) { 468 r.setBackgroundNonSelectionColor(style.getColorForState( 469 context, ColorType.TEXT_BACKGROUND)); 470 } 471 } 472 } 473 474 /** 475 * {@inheritDoc} 476 */ 477 @Override 478 protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, 479 Insets insets, Rectangle bounds, 480 TreePath path, int row, 481 boolean isExpanded, 482 boolean hasBeenExpanded, boolean 483 isLeaf) { 484 if (drawHorizontalLines) { 485 super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, 486 path, row, isExpanded, 487 hasBeenExpanded, isLeaf); 488 } 489 } 490 491 /** 492 * {@inheritDoc} 493 */ 494 @Override 495 protected void paintHorizontalLine(Graphics g, JComponent c, int y, 496 int left, int right) { 497 paintContext.getStyle().getGraphicsUtils(paintContext).drawLine( 498 paintContext, "Tree.horizontalLine", g, left, y, right, y, linesStyle); 499 } 500 501 /** 502 * {@inheritDoc} 503 */ 504 @Override 505 protected void paintVerticalPartOfLeg(Graphics g, 506 Rectangle clipBounds, Insets insets, 507 TreePath path) { 508 if (drawVerticalLines) { 509 super.paintVerticalPartOfLeg(g, clipBounds, insets, path); 510 } 511 } 512 513 /** 514 * {@inheritDoc} 515 */ 516 @Override 517 protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, 518 int bottom) { 519 paintContext.getStyle().getGraphicsUtils(paintContext).drawLine( 520 paintContext, "Tree.verticalLine", g, x, top, x, bottom, linesStyle); 521 } 522 523 private void paintRow(TreeCellRenderer renderer, 524 DefaultTreeCellRenderer dtcr, SynthContext treeContext, 525 SynthContext cellContext, Graphics g, Rectangle clipBounds, 526 Insets insets, Rectangle bounds, Rectangle rowBounds, 527 TreePath path, int row, boolean isExpanded, 528 boolean hasBeenExpanded, boolean isLeaf) { 529 // Don't paint the renderer if editing this row. 530 boolean selected = tree.isRowSelected(row); 531 532 JTree.DropLocation dropLocation = tree.getDropLocation(); 533 boolean isDrop = dropLocation != null 534 && dropLocation.getChildIndex() == -1 535 && path == dropLocation.getPath(); 536 537 int state = ENABLED; 538 if (selected || isDrop) { 539 state |= SELECTED; 540 } 541 542 if (tree.isFocusOwner() && row == getLeadSelectionRow()) { 543 state |= FOCUSED; 544 } 545 546 cellContext.setComponentState(state); 547 548 if (dtcr != null && (dtcr.getBorderSelectionColor() instanceof 549 UIResource)) { 550 dtcr.setBorderSelectionColor(style.getColor( 551 cellContext, ColorType.FOCUS)); 552 } 553 SynthLookAndFeel.updateSubregion(cellContext, g, rowBounds); 554 cellContext.getPainter().paintTreeCellBackground(cellContext, g, 555 rowBounds.x, rowBounds.y, rowBounds.width, 556 rowBounds.height); 557 cellContext.getPainter().paintTreeCellBorder(cellContext, g, 558 rowBounds.x, rowBounds.y, rowBounds.width, 559 rowBounds.height); 560 if (editingComponent != null && editingRow == row) { 561 return; 562 } 563 564 int leadIndex; 565 566 if (tree.hasFocus()) { 567 leadIndex = getLeadSelectionRow(); 568 } 569 else { 570 leadIndex = -1; 571 } 572 573 Component component = renderer.getTreeCellRendererComponent( 574 tree, path.getLastPathComponent(), 575 selected, isExpanded, isLeaf, row, 576 (leadIndex == row)); 577 578 rendererPane.paintComponent(g, component, tree, bounds.x, bounds.y, 579 bounds.width, bounds.height, true); 580 } 581 582 private int findCenteredX(int x, int iconWidth) { 583 return tree.getComponentOrientation().isLeftToRight() 584 ? x - (int)Math.ceil(iconWidth / 2.0) 585 : x - (int)Math.floor(iconWidth / 2.0); 586 } 587 588 /** 589 * {@inheritDoc} 590 */ 591 @Override 592 protected void paintExpandControl(Graphics g, Rectangle clipBounds, 593 Insets insets, Rectangle bounds, TreePath path, int row, 594 boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf) { 595 //modify the paintContext's state to match the state for the row 596 //this is a hack in that it requires knowledge of the subsequent 597 //method calls. The point is, the context used in drawCentered 598 //should reflect the state of the row, not of the tree. 599 boolean isSelected = tree.getSelectionModel().isPathSelected(path); 600 int state = paintContext.getComponentState(); 601 if (isSelected) { 602 paintContext.setComponentState(state | SynthConstants.SELECTED); 603 } 604 super.paintExpandControl(g, clipBounds, insets, bounds, path, row, 605 isExpanded, hasBeenExpanded, isLeaf); 606 paintContext.setComponentState(state); 607 } 608 609 /** 610 * {@inheritDoc} 611 */ 612 @Override 613 protected void drawCentered(Component c, Graphics graphics, Icon icon, 614 int x, int y) { 615 int w = SynthIcon.getIconWidth(icon, paintContext); 616 int h = SynthIcon.getIconHeight(icon, paintContext); 617 618 SynthIcon.paintIcon(icon, paintContext, graphics, 619 findCenteredX(x, w), 620 y - h/2, w, h); 621 } 622 623 /** 624 * {@inheritDoc} 625 */ 626 @Override 627 public void propertyChange(PropertyChangeEvent event) { 628 if (SynthLookAndFeel.shouldUpdateStyle(event)) { 629 updateStyle((JTree)event.getSource()); 630 } 631 632 if ("dropLocation" == event.getPropertyName()) { 633 JTree.DropLocation oldValue = (JTree.DropLocation)event.getOldValue(); 634 repaintDropLocation(oldValue); 635 repaintDropLocation(tree.getDropLocation()); 636 } 637 } 638 639 /** 640 * {@inheritDoc} 641 */ 642 @Override 643 protected void paintDropLine(Graphics g) { 644 JTree.DropLocation loc = tree.getDropLocation(); 645 if (!isDropLine(loc)) { 646 return; 647 } 648 649 Color c = (Color)style.get(paintContext, "Tree.dropLineColor"); 650 if (c != null) { 651 g.setColor(c); 652 Rectangle rect = getDropLineRect(loc); 653 g.fillRect(rect.x, rect.y, rect.width, rect.height); 654 } 655 } 656 657 private void repaintDropLocation(JTree.DropLocation loc) { 658 if (loc == null) { 659 return; 660 } 661 662 Rectangle r; 663 664 if (isDropLine(loc)) { 665 r = getDropLineRect(loc); 666 } else { 667 r = tree.getPathBounds(loc.getPath()); 668 if (r != null) { 669 r.x = 0; 670 r.width = tree.getWidth(); 671 } 672 } 673 674 if (r != null) { 675 tree.repaint(r); 676 } 677 } 678 679 /** 680 * {@inheritDoc} 681 */ 682 @Override 683 protected int getRowX(int row, int depth) { 684 return super.getRowX(row, depth) + padding; 685 } 686 687 688 private class SynthTreeCellRenderer extends DefaultTreeCellRenderer 689 implements UIResource { 690 SynthTreeCellRenderer() { 691 } 692 693 @Override 694 public String getName() { 695 return "Tree.cellRenderer"; 696 } 697 698 @Override 699 public Component getTreeCellRendererComponent(JTree tree, Object value, 700 boolean sel, 701 boolean expanded, 702 boolean leaf, int row, 703 boolean hasFocus) { 704 if (!useTreeColors && (sel || hasFocus)) { 705 SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel. 706 getUIOfType(getUI(), SynthLabelUI.class), 707 sel, hasFocus, tree.isEnabled(), false); 708 } 709 else { 710 SynthLookAndFeel.resetSelectedUI(); 711 } 712 return super.getTreeCellRendererComponent(tree, value, sel, 713 expanded, leaf, row, hasFocus); 714 } 715 716 @Override 717 public void paint(Graphics g) { 718 paintComponent(g); 719 if (hasFocus) { 720 SynthContext context = getContext(tree, Region.TREE_CELL); 721 722 if (context.getStyle() == null) { 723 assert false: "SynthTreeCellRenderer is being used " + 724 "outside of UI that created it"; 725 return; 726 } 727 int imageOffset = 0; 728 Icon currentI = getIcon(); 729 730 if(currentI != null && getText() != null) { 731 imageOffset = currentI.getIconWidth() + 732 Math.max(0, getIconTextGap() - 1); 733 } 734 if (selected) { 735 context.setComponentState(ENABLED | SELECTED); 736 } 737 else { 738 context.setComponentState(ENABLED); 739 } 740 if(getComponentOrientation().isLeftToRight()) { 741 context.getPainter().paintTreeCellFocus(context, g, 742 imageOffset, 0, getWidth() - imageOffset, 743 getHeight()); 744 } 745 else { 746 context.getPainter().paintTreeCellFocus(context, g, 747 0, 0, getWidth() - imageOffset, getHeight()); 748 } 749 context.dispose(); 750 } 751 SynthLookAndFeel.resetSelectedUI(); 752 } 753 } 754 755 756 private static class SynthTreeCellEditor extends DefaultTreeCellEditor { 757 public SynthTreeCellEditor(JTree tree, 758 DefaultTreeCellRenderer renderer) { 759 super(tree, renderer); 760 setBorderSelectionColor(null); 761 } 762 763 @Override 764 protected TreeCellEditor createTreeCellEditor() { 765 JTextField tf = new JTextField() { 766 @Override 767 public String getName() { 768 return "Tree.cellEditor"; 769 } 770 }; 771 DefaultCellEditor editor = new DefaultCellEditor(tf); 772 773 // One click to edit. 774 editor.setClickCountToStart(1); 775 return editor; 776 } 777 } 778 779 // 780 // BasicTreeUI directly uses expandIcon outside of the Synth methods. 781 // To get the correct context we return an instance of this that fetches 782 // the SynthContext as needed. 783 // 784 private class ExpandedIconWrapper extends SynthIcon { 785 public void paintIcon(SynthContext context, Graphics g, int x, 786 int y, int w, int h) { 787 if (context == null) { 788 context = getContext(tree); 789 SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h); 790 context.dispose(); 791 } 792 else { 793 SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h); 794 } 795 } 796 797 public int getIconWidth(SynthContext context) { 798 int width; 799 if (context == null) { 800 context = getContext(tree); 801 width = SynthIcon.getIconWidth(expandedIcon, context); 802 context.dispose(); 803 } 804 else { 805 width = SynthIcon.getIconWidth(expandedIcon, context); 806 } 807 return width; 808 } 809 810 public int getIconHeight(SynthContext context) { 811 int height; 812 if (context == null) { 813 context = getContext(tree); 814 height = SynthIcon.getIconHeight(expandedIcon, context); 815 context.dispose(); 816 } 817 else { 818 height = SynthIcon.getIconHeight(expandedIcon, context); 819 } 820 return height; 821 } 822 } 823 }