1. /*
  2. * @(#)MetalTreeUI.java 1.15 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.metal;
  8. import javax.swing.*;
  9. import javax.swing.event.*;
  10. import javax.swing.text.DefaultTextUI;
  11. import java.awt.*;
  12. import java.awt.event.*;
  13. import java.beans.*;
  14. import java.io.*;
  15. import java.util.*;
  16. import javax.swing.plaf.*;
  17. import javax.swing.tree.*;
  18. import javax.swing.plaf.basic.*;
  19. /**
  20. * MetalTreeUI supports the client property "value-add" system of customization
  21. * It uses it to determine what style of line to draw. There are three choices.
  22. * The default choice is to draw no lines.
  23. * Also available is a more variant with angled legs running from parent to child.
  24. * Lastly you can choose an option with horizonl lines be lines at all.
  25. * Here is some code to turn on angled legs.
  26. *
  27. * tree.putClientProperty("JTree.lineStyle", "Angled");
  28. *
  29. * Here is some code to turn on horizontal lines between root nodes.
  30. *
  31. * tree.putClientProperty("JTree.lineStyle", "Horizontal");
  32. *
  33. *
  34. * Here is some code to turn off lines all together (which is the default).
  35. *
  36. * tree.putClientProperty("JTree.lineStyle", "None");
  37. *
  38. *
  39. * @version 1.15 11/29/01
  40. * @author Tom Santos
  41. * @author Steve Wilson (value add stuff)
  42. */
  43. public class MetalTreeUI extends BasicTreeUI {
  44. private static Color lineColor;
  45. private static final String LINE_STYLE = "JTree.lineStyle";
  46. private static final String LEG_LINE_STYLE_STRING = "Angled";
  47. private static final String HORIZ_STYLE_STRING = "Horizontal";
  48. private static final String NO_STYLE_STRING = "None";
  49. private static final int LEG_LINE_STYLE = 2;
  50. private static final int HORIZ_LINE_STYLE = 1;
  51. private static final int NO_LINE_STYLE = 0;
  52. private int lineStyle = HORIZ_LINE_STYLE;
  53. private PropertyChangeListener lineStyleListener = new LineListener();
  54. // Boilerplate
  55. public static ComponentUI createUI(JComponent x) {
  56. return new MetalTreeUI();
  57. }
  58. public MetalTreeUI()
  59. {
  60. super();
  61. }
  62. protected int getHorizontalLegBuffer()
  63. {
  64. return 4;
  65. }
  66. public void installUI( JComponent c ) {
  67. super.installUI( c );
  68. lineColor = UIManager.getColor( "Tree.line" );
  69. Object lineStyleFlag = c.getClientProperty( LINE_STYLE );
  70. decodeLineStyle(lineStyleFlag);
  71. c.addPropertyChangeListener(lineStyleListener);
  72. }
  73. public void uninstallUI( JComponent c) {
  74. c.removePropertyChangeListener(lineStyleListener);
  75. super.uninstallUI(c);
  76. }
  77. /** this function converts between the string passed into the client property
  78. * and the internal representation (currently and int)
  79. *
  80. */
  81. protected void decodeLineStyle(Object lineStyleFlag) {
  82. if ( lineStyleFlag == null || lineStyleFlag.equals(NO_STYLE_STRING) ){
  83. lineStyle = NO_LINE_STYLE; // default case
  84. } else {
  85. if ( lineStyleFlag.equals(LEG_LINE_STYLE_STRING) ) {
  86. lineStyle = LEG_LINE_STYLE;
  87. } else if ( lineStyleFlag.equals(HORIZ_STYLE_STRING) ) {
  88. lineStyle = HORIZ_LINE_STYLE;
  89. }
  90. }
  91. }
  92. protected boolean isLocationInExpandControl(int row, int rowLevel,
  93. int mouseX, int mouseY) {
  94. if(tree != null && !isLeaf(row)) {
  95. int boxWidth;
  96. if(getExpandedIcon() != null)
  97. boxWidth = getExpandedIcon().getIconWidth() + 6;
  98. else
  99. boxWidth = 8;
  100. Insets i = tree.getInsets();
  101. int boxLeftX = (i != null) ? i.left : 0;
  102. boxLeftX += (((rowLevel + depthOffset - 1) * totalChildIndent) +
  103. getLeftChildIndent()) - boxWidth2;
  104. int boxRightX = boxLeftX + boxWidth;
  105. return mouseX >= boxLeftX && mouseX <= boxRightX;
  106. }
  107. return false;
  108. }
  109. public void paint(Graphics g, JComponent c) {
  110. super.paint( g, c );
  111. // Paint the lines
  112. if (lineStyle == HORIZ_LINE_STYLE && !largeModel) {
  113. paintHorizontalSeparators(g,c);
  114. }
  115. }
  116. protected void paintHorizontalSeparators(Graphics g, JComponent c) {
  117. g.setColor( lineColor );
  118. Rectangle clipBounds = g.getClipBounds();
  119. int beginRow = getRowForPath(tree, getClosestPathForLocation
  120. (tree, 0, clipBounds.y));
  121. int endRow = getRowForPath(tree, getClosestPathForLocation
  122. (tree, 0, clipBounds.y + clipBounds.height - 1));
  123. if ( beginRow <= -1 || endRow <= -1 ) {
  124. return;
  125. }
  126. for ( int i = beginRow; i <= endRow; ++i ) {
  127. TreePath path = getPathForRow(tree, i);
  128. if(path != null && path.getPathCount() == 2) {
  129. Rectangle rowBounds = getPathBounds(tree,getPathForRow
  130. (tree, i));
  131. // Draw a line at the top
  132. if(rowBounds != null)
  133. g.drawLine(clipBounds.x, rowBounds.y,
  134. clipBounds.x + clipBounds.width, rowBounds.y);
  135. }
  136. }
  137. }
  138. protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds,
  139. Insets insets, TreePath path) {
  140. if (lineStyle == LEG_LINE_STYLE) {
  141. super.paintVerticalPartOfLeg(g, clipBounds, insets, path);
  142. }
  143. }
  144. protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds,
  145. Insets insets, Rectangle bounds,
  146. TreePath path, int row,
  147. boolean isExpanded,
  148. boolean hasBeenExpanded, boolean
  149. isLeaf) {
  150. if (lineStyle == LEG_LINE_STYLE) {
  151. super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds,
  152. path, row, isExpanded,
  153. hasBeenExpanded, isLeaf);
  154. }
  155. }
  156. /** This class listens for changes in line style */
  157. class LineListener implements PropertyChangeListener {
  158. public void propertyChange(PropertyChangeEvent e) {
  159. String name = e.getPropertyName();
  160. if ( name.equals( LINE_STYLE ) ) {
  161. decodeLineStyle(e.getNewValue());
  162. }
  163. }
  164. } // end class PaletteListener
  165. }