1 7 package javax.swing.plaf.synth; 8 9 import javax.swing.*; 10 import javax.swing.event.*; 11 import java.awt.*; 12 import java.awt.event.*; 13 import java.awt.datatransfer.*; 14 import java.awt.dnd.*; 15 import java.beans.*; 16 import java.io.*; 17 import java.util.*; 18 import javax.swing.plaf.*; 19 import javax.swing.plaf.basic.*; 20 import javax.swing.tree.*; 21 import javax.swing.text.Position ; 22 import sun.swing.plaf.synth.*; 23 24 30 class SynthTreeUI extends BasicTreeUI implements PropertyChangeListener, 31 SynthUI { 32 private SynthStyle style; 33 private SynthStyle cellStyle; 34 35 private SynthContext paintContext; 36 37 private boolean drawHorizontalLines; 38 private boolean drawVerticalLines; 39 40 private int leadRow; 41 42 private int padding; 43 44 private boolean useTreeColors; 45 46 private Icon expandedIconWrapper; 47 48 49 public static ComponentUI createUI(JComponent x) { 50 return new SynthTreeUI (); 51 } 52 53 SynthTreeUI() { 54 expandedIconWrapper = new ExpandedIconWrapper(); 55 } 56 57 public Icon getExpandedIcon() { 58 return expandedIconWrapper; 59 } 60 61 protected void installDefaults() { 62 updateStyle(tree); 63 } 64 65 private void updateStyle(JTree tree) { 66 SynthContext context = getContext(tree, ENABLED); 67 SynthStyle oldStyle = style; 68 69 style = SynthLookAndFeel.updateStyle(context, this); 70 if (style != oldStyle) { 71 Object value; 72 73 setExpandedIcon(style.getIcon(context, "Tree.expandedIcon")); 74 setCollapsedIcon(style.getIcon(context, "Tree.collapsedIcon")); 75 76 setLeftChildIndent(style.getInt(context, "Tree.leftChildIndent", 77 0)); 78 setRightChildIndent(style.getInt(context, "Tree.rightChildIndent", 79 0)); 80 81 drawHorizontalLines = style.getBoolean( 82 context, "Tree.drawHorizontalLines",true); 83 drawVerticalLines = style.getBoolean( 84 context, "Tree.drawVerticalLines", true); 85 86 value = style.get(context, "Tree.rowHeight"); 87 if (value != null) { 88 LookAndFeel.installProperty(tree, "rowHeight", value); 89 } 90 91 value = style.get(context, "Tree.scrollsOnExpand"); 92 LookAndFeel.installProperty(tree, "scrollsOnExpand", 93 value != null? value : Boolean.TRUE); 94 95 padding = style.getInt(context, "Tree.padding", 0); 96 97 largeModel = (tree.isLargeModel() && tree.getRowHeight() > 0); 98 99 useTreeColors = style.getBoolean(context, 100 "Tree.rendererUseTreeColors", true); 101 102 Boolean showsRootHandles = style.getBoolean( 103 context, "Tree.showsRootHandles", Boolean.TRUE); 104 LookAndFeel.installProperty( 105 tree, JTree.SHOWS_ROOT_HANDLES_PROPERTY, showsRootHandles); 106 107 if (oldStyle != null) { 108 uninstallKeyboardActions(); 109 installKeyboardActions(); 110 } 111 } 112 context.dispose(); 113 114 context = getContext(tree, Region.TREE_CELL, ENABLED); 115 cellStyle = SynthLookAndFeel.updateStyle(context, this); 116 context.dispose(); 117 } 118 119 protected void installListeners() { 120 super.installListeners(); 121 tree.addPropertyChangeListener(this); 122 } 123 124 public SynthContext getContext(JComponent c) { 125 return getContext(c, getComponentState(c)); 126 } 127 128 private SynthContext getContext(JComponent c, int state) { 129 return SynthContext.getContext(SynthContext .class, c, 130 SynthLookAndFeel.getRegion(c), style, state); 131 } 132 133 private Region getRegion(JTree c) { 134 return SynthLookAndFeel.getRegion(c); 135 } 136 137 private int getComponentState(JComponent c) { 138 return SynthLookAndFeel.getComponentState(c); 139 } 140 141 private SynthContext getContext(JComponent c, Region region) { 142 return getContext(c, region, getComponentState(c, region)); 143 } 144 145 private SynthContext getContext(JComponent c, Region region, int state) { 146 return SynthContext.getContext(SynthContext .class, c, 147 region, cellStyle, state); 148 } 149 150 private int getComponentState(JComponent c, Region region) { 151 return ENABLED | SELECTED; 154 } 155 156 protected TreeCellEditor createDefaultCellEditor() { 157 TreeCellRenderer renderer = tree.getCellRenderer(); 158 DefaultTreeCellEditor editor; 159 160 if(renderer != null && (renderer instanceof DefaultTreeCellRenderer)) { 161 editor = new SynthTreeCellEditor(tree, (DefaultTreeCellRenderer) 162 renderer); 163 } 164 else { 165 editor = new SynthTreeCellEditor(tree, null); 166 } 167 return editor; 168 } 169 170 protected TreeCellRenderer createDefaultCellRenderer() { 171 return new SynthTreeCellRenderer(); 172 } 173 174 protected void uninstallDefaults() { 175 SynthContext context = getContext(tree, ENABLED); 176 177 style.uninstallDefaults(context); 178 context.dispose(); 179 style = null; 180 181 context = getContext(tree, Region.TREE_CELL, ENABLED); 182 cellStyle.uninstallDefaults(context); 183 context.dispose(); 184 cellStyle = null; 185 186 187 if (tree.getTransferHandler() instanceof UIResource) { 188 tree.setTransferHandler(null); 189 } 190 } 191 192 protected void uninstallListeners() { 193 super.uninstallListeners(); 194 tree.removePropertyChangeListener(this); 195 } 196 197 public void update(Graphics g, JComponent c) { 198 SynthContext context = getContext(c); 199 200 SynthLookAndFeel.update(context, g); 201 context.getPainter().paintTreeBackground(context, 202 g, 0, 0, c.getWidth(), c.getHeight()); 203 paint(context, g); 204 context.dispose(); 205 } 206 207 public void paintBorder(SynthContext context, Graphics g, int x, 208 int y, int w, int h) { 209 context.getPainter().paintTreeBorder(context, g, x, y, w, h); 210 } 211 212 public void paint(Graphics g, JComponent c) { 213 SynthContext context = getContext(c); 214 215 paint(context, g); 216 context.dispose(); 217 } 218 219 private void adjustCellBounds(JTree tree, Rectangle bounds, Insets i){ 220 if (bounds != null) { 221 if (i == null) { 222 i = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS; 223 } 224 bounds.x += i.left; 225 bounds.y += i.top; 226 } 227 } 228 229 private void updateLeadRow() { 230 leadRow = getRowForPath(tree, tree.getLeadSelectionPath()); 231 } 232 233 protected void paint(SynthContext context, Graphics g) { 234 paintContext = context; 235 236 updateLeadRow(); 237 238 Rectangle paintBounds = g.getClipBounds(); 239 Insets insets = tree.getInsets(); 240 TreePath initialPath = getClosestPathForLocation(tree, 0, 241 paintBounds.y); 242 Enumeration paintingEnumerator = treeState.getVisiblePathsFrom 243 (initialPath); 244 int row = treeState.getRowForPath(initialPath); 245 int endY = paintBounds.y + paintBounds.height; 246 TreeModel treeModel = tree.getModel(); 247 SynthContext cellContext = getContext(tree, Region.TREE_CELL); 248 249 drawingCache.clear(); 250 251 setHashColor(context.getStyle().getColor(context, 252 ColorType.FOREGROUND)); 253 254 if (paintingEnumerator != null) { 255 257 boolean done = false; 258 boolean isExpanded; 259 boolean hasBeenExpanded; 260 boolean isLeaf; 261 Rectangle boundsBuffer = new Rectangle(); 262 Rectangle rowBounds = new Rectangle(0, 0, tree.getWidth(),0); 263 Rectangle bounds; 264 TreePath path; 265 TreeCellRenderer renderer = tree.getCellRenderer(); 266 DefaultTreeCellRenderer dtcr = (renderer instanceof 267 DefaultTreeCellRenderer) ? (DefaultTreeCellRenderer) 268 renderer : null; 269 270 configureRenderer(cellContext); 271 while (!done && paintingEnumerator.hasMoreElements()) { 272 path = (TreePath)paintingEnumerator.nextElement(); 273 if (path != null) { 274 isLeaf = treeModel.isLeaf(path.getLastPathComponent()); 275 if (isLeaf) { 276 isExpanded = hasBeenExpanded = false; 277 } 278 else { 279 isExpanded = treeState.getExpandedState(path); 280 hasBeenExpanded = tree.hasBeenExpanded(path); 281 } 282 bounds = treeState.getBounds(path, boundsBuffer); 283 adjustCellBounds(tree, bounds, insets); 284 rowBounds.y = bounds.y; 285 rowBounds.height = bounds.height; 286 paintRow(renderer, dtcr, context, cellContext, g, 287 paintBounds, insets, bounds, rowBounds, path, 288 row, isExpanded, hasBeenExpanded, isLeaf); 289 if ((bounds.y + bounds.height) >= endY) { 290 done = true; 291 } 292 } 293 else { 294 done = true; 295 } 296 row++; 297 } 298 299 boolean rootVisible = tree.isRootVisible(); 302 TreePath parentPath = initialPath; 303 parentPath = parentPath.getParentPath(); 304 while (parentPath != null) { 305 paintVerticalPartOfLeg(g, paintBounds, insets, parentPath); 306 drawingCache.put(parentPath, Boolean.TRUE); 307 parentPath = parentPath.getParentPath(); 308 } 309 done = false; 310 paintingEnumerator = treeState.getVisiblePathsFrom(initialPath); 311 while (!done && paintingEnumerator.hasMoreElements()) { 312 path = (TreePath)paintingEnumerator.nextElement(); 313 if (path != null) { 314 isLeaf = treeModel.isLeaf(path.getLastPathComponent()); 315 if (isLeaf) { 316 isExpanded = hasBeenExpanded = false; 317 } 318 else { 319 isExpanded = treeState.getExpandedState(path); 320 hasBeenExpanded = tree.hasBeenExpanded(path); 321 } 322 bounds = treeState.getBounds(path, boundsBuffer); 323 adjustCellBounds(tree, bounds, insets); 324 parentPath = path.getParentPath(); 326 if (parentPath != null) { 327 if (drawingCache.get(parentPath) == null) { 328 paintVerticalPartOfLeg(g, paintBounds, insets, 329 parentPath); 330 drawingCache.put(parentPath, Boolean.TRUE); 331 } 332 paintHorizontalPartOfLeg(g, 333 paintBounds, insets, bounds, 334 path, row, isExpanded, 335 hasBeenExpanded, isLeaf); 336 } 337 else if (rootVisible && row == 0) { 338 paintHorizontalPartOfLeg(g, 339 paintBounds, insets, bounds, 340 path, row, isExpanded, 341 hasBeenExpanded, isLeaf); 342 } 343 if (shouldPaintExpandControl(path, row, isExpanded, 344 hasBeenExpanded, isLeaf)) { 345 paintExpandControl(g, paintBounds, 346 insets, bounds, path, row, 347 isExpanded, hasBeenExpanded,isLeaf); 348 } 349 if ((bounds.y + bounds.height) >= endY) { 350 done = true; 351 } 352 } 353 else { 354 done = true; 355 } 356 row++; 357 } 358 } 359 cellContext.dispose(); 360 rendererPane.removeAll(); 362 } 363 364 private void configureRenderer(SynthContext context) { 365 TreeCellRenderer renderer = tree.getCellRenderer(); 366 367 if (renderer instanceof DefaultTreeCellRenderer) { 368 DefaultTreeCellRenderer r = (DefaultTreeCellRenderer)renderer; 369 SynthStyle style = context.getStyle(); 370 371 context.setComponentState(ENABLED | SELECTED); 372 Color color = r.getTextSelectionColor(); 373 if (color == null || (color instanceof UIResource)) { 374 r.setTextSelectionColor(style.getColor( 375 context, ColorType.TEXT_FOREGROUND)); 376 } 377 color = r.getBackgroundSelectionColor(); 378 if (color == null || (color instanceof UIResource)) { 379 r.setBackgroundSelectionColor(style.getColor( 380 context, ColorType.TEXT_BACKGROUND)); 381 } 382 383 context.setComponentState(ENABLED); 384 color = r.getTextNonSelectionColor(); 385 if (color == null || color instanceof UIResource) { 386 r.setTextNonSelectionColor(style.getColor( 387 context, ColorType.TEXT_FOREGROUND)); 388 } 389 color = r.getBackgroundNonSelectionColor(); 390 if (color instanceof UIResource) { 391 r.setBackgroundNonSelectionColor(style.getColor( 392 context, ColorType.TEXT_BACKGROUND)); 393 } 394 } 395 } 396 397 protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, 398 Insets insets, Rectangle bounds, 399 TreePath path, int row, 400 boolean isExpanded, 401 boolean hasBeenExpanded, boolean 402 isLeaf) { 403 if (drawHorizontalLines) { 404 super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, 405 path, row, isExpanded, 406 hasBeenExpanded, isLeaf); 407 } 408 } 409 410 protected void paintHorizontalLine(Graphics g, JComponent c, int y, 411 int left, int right) { 412 paintContext.getStyle().getGraphicsUtils(paintContext).drawLine( 413 paintContext, "Tree.horizontalLine", g, left, y, right, y); 414 } 415 416 protected void paintVerticalPartOfLeg(Graphics g, 417 Rectangle clipBounds, Insets insets, 418 TreePath path) { 419 if (drawVerticalLines) { 420 super.paintVerticalPartOfLeg(g, clipBounds, insets, path); 421 } 422 } 423 424 protected void paintVerticalLine(Graphics g, JComponent c, int x, int top, 425 int bottom) { 426 paintContext.getStyle().getGraphicsUtils(paintContext).drawLine( 427 paintContext, "Tree.verticalLine", g, x, top, x, bottom); 428 } 429 430 protected void paintRow(TreeCellRenderer renderer, 431 DefaultTreeCellRenderer dtcr, SynthContext treeContext, 432 SynthContext cellContext, Graphics g, Rectangle clipBounds, 433 Insets insets, Rectangle bounds, Rectangle rowBounds, 434 TreePath path, int row, boolean isExpanded, 435 boolean hasBeenExpanded, boolean isLeaf) { 436 boolean selected = tree.isRowSelected(row); 438 439 if (selected) { 440 cellContext.setComponentState(ENABLED | SELECTED); 441 } 442 else { 443 cellContext.setComponentState(ENABLED); 444 } 445 if (dtcr != null && (dtcr.getBorderSelectionColor() instanceof 446 UIResource)) { 447 dtcr.setBorderSelectionColor(style.getColor( 448 cellContext, ColorType.FOCUS)); 449 } 450 SynthLookAndFeel.updateSubregion(cellContext, g, rowBounds); 451 cellContext.getPainter().paintTreeCellBackground(cellContext, g, 452 rowBounds.x, rowBounds.y, rowBounds.width, 453 rowBounds.height); 454 cellContext.getPainter().paintTreeCellBorder(cellContext, g, 455 rowBounds.x, rowBounds.y, rowBounds.width, 456 rowBounds.height); 457 if (editingComponent != null && editingRow == row) { 458 return; 459 } 460 461 int leadIndex; 462 463 if (tree.hasFocus()) { 464 leadIndex = leadRow; 465 } 466 else { 467 leadIndex = -1; 468 } 469 470 Component component = renderer.getTreeCellRendererComponent( 471 tree, path.getLastPathComponent(), 472 selected, isExpanded, isLeaf, row, 473 (leadIndex == row)); 474 475 rendererPane.paintComponent(g, component, tree, bounds.x, bounds.y, 476 bounds.width, bounds.height, true); 477 } 478 479 protected void drawCentered(Component c, Graphics graphics, Icon icon, 480 int x, int y) { 481 int w = SynthIcon.getIconWidth(icon, paintContext); 482 int h = SynthIcon.getIconHeight(icon, paintContext); 483 484 SynthIcon.paintIcon(icon, paintContext, graphics, x - w/2, y - h/2, w, 485 h); 486 } 487 488 public void propertyChange(PropertyChangeEvent event) { 489 if (SynthLookAndFeel.shouldUpdateStyle(event)) { 490 updateStyle((JTree)event.getSource()); 491 } 492 } 493 494 protected int getRowX(int row, int depth) { 495 return super.getRowX(row, depth) + padding; 496 } 497 498 499 private class SynthTreeCellRenderer extends DefaultTreeCellRenderer 500 implements UIResource { 501 SynthTreeCellRenderer() { 502 } 503 public String getName() { 504 return "Tree.cellRenderer"; 505 } 506 public Component getTreeCellRendererComponent(JTree tree, Object value, 507 boolean sel, 508 boolean expanded, 509 boolean leaf, int row, 510 boolean hasFocus) { 511 if (!useTreeColors && (sel || hasFocus)) { 512 SynthLookAndFeel.setSelectedUI((SynthLabelUI )SynthLookAndFeel. 513 getUIOfType(getUI(), SynthLabelUI .class), 514 sel, hasFocus, tree.isEnabled()); 515 } 516 else { 517 SynthLookAndFeel.resetSelectedUI(); 518 } 519 return super.getTreeCellRendererComponent(tree, value, sel, 520 expanded, leaf, row, hasFocus); 521 } 522 public void paint(Graphics g) { 523 paintComponent(g); 524 if (hasFocus) { 525 SynthContext context = getContext(tree, Region.TREE_CELL); 526 527 if (context.getStyle() == null) { 528 assert false: "SynthTreeCellRenderer is being used " + 529 "outside of UI that created it"; 530 return; 531 } 532 int imageOffset = 0; 533 Icon currentI = getIcon(); 534 535 if(currentI != null && getText() != null) { 536 imageOffset = currentI.getIconWidth() + 537 Math.max(0, getIconTextGap() - 1); 538 } 539 if (selected) { 540 context.setComponentState(ENABLED | SELECTED); 541 } 542 else { 543 context.setComponentState(ENABLED); 544 } 545 if(getComponentOrientation().isLeftToRight()) { 546 context.getPainter().paintTreeCellFocus(context, g, 547 imageOffset, 0, getWidth() - imageOffset, 548 getHeight()); 549 } 550 else { 551 context.getPainter().paintTreeCellFocus(context, g, 552 0, 0, getWidth() - imageOffset, getHeight()); 553 } 554 context.dispose(); 555 } 556 SynthLookAndFeel.resetSelectedUI(); 557 } 558 } 559 560 561 private static class SynthTreeCellEditor extends DefaultTreeCellEditor { 562 public SynthTreeCellEditor(JTree tree, 563 DefaultTreeCellRenderer renderer) { 564 super(tree, renderer); 565 setBorderSelectionColor(null); 566 } 567 568 protected TreeCellEditor createTreeCellEditor() { 569 JTextField tf = new JTextField() { 570 public String getName() { 571 return "Tree.cellEditor"; 572 } 573 }; 574 DefaultCellEditor editor = new DefaultCellEditor(tf); 575 576 editor.setClickCountToStart(1); 578 return editor; 579 } 580 } 581 582 583 private class ExpandedIconWrapper extends SynthIcon { 589 public void paintIcon(SynthContext context, Graphics g, int x, 590 int y, int w, int h) { 591 if (context == null) { 592 context = getContext(tree); 593 SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h); 594 context.dispose(); 595 } 596 else { 597 SynthIcon.paintIcon(expandedIcon, context, g, x, y, w, h); 598 } 599 } 600 601 public int getIconWidth(SynthContext context) { 602 int width; 603 if (context == null) { 604 context = getContext(tree); 605 width = SynthIcon.getIconWidth(expandedIcon, context); 606 context.dispose(); 607 } 608 else { 609 width = SynthIcon.getIconWidth(expandedIcon, context); 610 } 611 return width; 612 } 613 614 public int getIconHeight(SynthContext context) { 615 int height; 616 if (context == null) { 617 context = getContext(tree); 618 height = SynthIcon.getIconHeight(expandedIcon, context); 619 context.dispose(); 620 } 621 else { 622 height = SynthIcon.getIconHeight(expandedIcon, context); 623 } 624 return height; 625 } 626 } 627 } 628 | Popular Tags |