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