1. /*
  2. * @(#)MetalSplitPaneDivider.java 1.12 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 java.awt.*;
  9. import javax.swing.*;
  10. import javax.swing.border.*;
  11. import javax.swing.plaf.basic.*;
  12. /**
  13. * Metal's split pane divider
  14. * <p>
  15. * <strong>Warning:</strong>
  16. * Serialized objects of this class will not be compatible with
  17. * future Swing releases. The current serialization support is appropriate
  18. * for short term storage or RMI between applications running the same
  19. * version of Swing. A future release of Swing will provide support for
  20. * long term persistence.
  21. *
  22. * @version 1.12 11/29/01
  23. * @author Steve Wilson
  24. * @author Ralph kar
  25. */
  26. class MetalSplitPaneDivider extends BasicSplitPaneDivider
  27. {
  28. private MetalBumps bumps = new MetalBumps(10, 10,
  29. MetalLookAndFeel.getControlHighlight(),
  30. MetalLookAndFeel.getControlDarkShadow(),
  31. MetalLookAndFeel.getControl() );
  32. private MetalBumps focusBumps = new MetalBumps(10, 10,
  33. MetalLookAndFeel.getPrimaryControlHighlight(),
  34. MetalLookAndFeel.getPrimaryControlDarkShadow(),
  35. MetalLookAndFeel.getPrimaryControl() );
  36. private int inset = 2;
  37. private Color controlColor = MetalLookAndFeel.getControl();
  38. private Color primaryControlColor = MetalLookAndFeel.getPrimaryControl();
  39. public MetalSplitPaneDivider(BasicSplitPaneUI ui) {
  40. super(ui);
  41. setLayout(new MetalDividerLayout());
  42. }
  43. public void paint(Graphics g) {
  44. MetalBumps usedBumps;
  45. if (splitPane.hasFocus()) {
  46. usedBumps = focusBumps;
  47. g.setColor(primaryControlColor);
  48. }
  49. else {
  50. usedBumps = bumps;
  51. g.setColor(controlColor);
  52. }
  53. Rectangle clip = g.getClipBounds();
  54. g.fillRect(clip.x, clip.y, clip.width, clip.height);
  55. Dimension size = getSize();
  56. size.width -= inset * 2;
  57. size.height -= inset * 2;
  58. usedBumps.setBumpArea(size);
  59. usedBumps.paintIcon(this, g, inset, inset);
  60. super.paint(g);
  61. }
  62. /**
  63. * Creates and return an instance of JButton that can be used to
  64. * collapse the left component in the metal split pane.
  65. */
  66. protected JButton createLeftOneTouchButton() {
  67. JButton b = new JButton() {
  68. // Sprite buffer for the arrow image of the left button
  69. int[][] buffer = {{0, 0, 0, 2, 2, 0, 0, 0, 0},
  70. {0, 0, 2, 1, 1, 1, 0, 0, 0},
  71. {0, 2, 1, 1, 1, 1, 1, 0, 0},
  72. {2, 1, 1, 1, 1, 1, 1, 1, 0},
  73. {0, 3, 3, 3, 3, 3, 3, 3, 3}};
  74. public void setBorder(Border b) {
  75. }
  76. public void paint(Graphics g) {
  77. JSplitPane splitPane = getSplitPaneFromSuper();
  78. if(splitPane != null) {
  79. int oneTouchSize = getOneTouchSizeFromSuper();
  80. int orientation = getOrientationFromSuper();
  81. int blockSize = Math.min(getDividerSize(),
  82. oneTouchSize);
  83. // Initialize the color array
  84. Color[] colors = {
  85. this.getBackground(),
  86. MetalLookAndFeel.getPrimaryControlDarkShadow(),
  87. MetalLookAndFeel.getPrimaryControlInfo(),
  88. MetalLookAndFeel.getPrimaryControlHighlight()};
  89. // Fill the background first ...
  90. g.setColor(this.getBackground());
  91. g.fillRect(0, 0, this.getWidth(),
  92. this.getHeight());
  93. // ... then draw the arrow.
  94. if (getModel().isPressed()) {
  95. // Adjust color mapping for pressed button state
  96. colors[1] = colors[2];
  97. }
  98. if(orientation == JSplitPane.VERTICAL_SPLIT) {
  99. // Draw the image for a vertical split
  100. for (int i=1; i<=buffer[0].length; i++) {
  101. for (int j=1; j<blockSize; j++) {
  102. if (buffer[j-1][i-1] == 0) {
  103. continue;
  104. }
  105. else {
  106. g.setColor(
  107. colors[buffer[j-1][i-1]]);
  108. }
  109. g.drawLine(i, j, i, j);
  110. }
  111. }
  112. }
  113. else {
  114. // Draw the image for a horizontal split
  115. // by simply swaping the i and j axis.
  116. // Except the drawLine() call this code is
  117. // identical to the code block above. This was done
  118. // in order to remove the additional orientation
  119. // check for each pixel.
  120. for (int i=1; i<=buffer[0].length; i++) {
  121. for (int j=1; j<blockSize; j++) {
  122. if (buffer[j-1][i-1] == 0) {
  123. // Nothing needs
  124. // to be drawn
  125. continue;
  126. }
  127. else {
  128. // Set the color from the
  129. // color map
  130. g.setColor(
  131. colors[buffer[j-1][i-1]]);
  132. }
  133. // Draw a pixel
  134. g.drawLine(j, i, j, i);
  135. }
  136. }
  137. }
  138. }
  139. }
  140. // Don't want the button to participate in focus traversable.
  141. public boolean isFocusTraversable() {
  142. return false;
  143. }
  144. };
  145. b.setFocusPainted(false);
  146. b.setBorderPainted(false);
  147. return b;
  148. }
  149. /**
  150. * Creates and return an instance of JButton that can be used to
  151. * collapse the right component in the metal split pane.
  152. */
  153. protected JButton createRightOneTouchButton() {
  154. JButton b = new JButton() {
  155. // Sprite buffer for the arrow image of the right button
  156. int[][] buffer = {{2, 2, 2, 2, 2, 2, 2, 2},
  157. {0, 1, 1, 1, 1, 1, 1, 3},
  158. {0, 0, 1, 1, 1, 1, 3, 0},
  159. {0, 0, 0, 1, 1, 3, 0, 0},
  160. {0, 0, 0, 0, 3, 0, 0, 0}};
  161. public void setBorder(Border border) {
  162. }
  163. public void paint(Graphics g) {
  164. JSplitPane splitPane = getSplitPaneFromSuper();
  165. if(splitPane != null) {
  166. int oneTouchSize = getOneTouchSizeFromSuper();
  167. int orientation = getOrientationFromSuper();
  168. int blockSize = Math.min(getDividerSize(),
  169. oneTouchSize);
  170. // Initialize the color array
  171. Color[] colors = {
  172. this.getBackground(),
  173. MetalLookAndFeel.getPrimaryControlDarkShadow(),
  174. MetalLookAndFeel.getPrimaryControlInfo(),
  175. MetalLookAndFeel.getPrimaryControlHighlight()};
  176. // Fill the background first ...
  177. g.setColor(this.getBackground());
  178. g.fillRect(0, 0, this.getWidth(),
  179. this.getHeight());
  180. // ... then draw the arrow.
  181. if (getModel().isPressed()) {
  182. // Adjust color mapping for pressed button state
  183. colors[1] = colors[2];
  184. }
  185. if(orientation == JSplitPane.VERTICAL_SPLIT) {
  186. // Draw the image for a vertical split
  187. for (int i=1; i<=buffer[0].length; i++) {
  188. for (int j=1; j<blockSize; j++) {
  189. if (buffer[j-1][i-1] == 0) {
  190. continue;
  191. }
  192. else {
  193. g.setColor(
  194. colors[buffer[j-1][i-1]]);
  195. }
  196. g.drawLine(i, j, i, j);
  197. }
  198. }
  199. }
  200. else {
  201. // Draw the image for a horizontal split
  202. // by simply swaping the i and j axis.
  203. // Except the drawLine() call this code is
  204. // identical to the code block above. This was done
  205. // in order to remove the additional orientation
  206. // check for each pixel.
  207. for (int i=1; i<=buffer[0].length; i++) {
  208. for (int j=1; j<blockSize; j++) {
  209. if (buffer[j-1][i-1] == 0) {
  210. // Nothing needs
  211. // to be drawn
  212. continue;
  213. }
  214. else {
  215. // Set the color from the
  216. // color map
  217. g.setColor(
  218. colors[buffer[j-1][i-1]]);
  219. }
  220. // Draw a pixel
  221. g.drawLine(j, i, j, i);
  222. }
  223. }
  224. }
  225. }
  226. }
  227. // Don't want the button to participate in focus traversable.
  228. public boolean isFocusTraversable() {
  229. return false;
  230. }
  231. };
  232. b.setFocusPainted(false);
  233. b.setBorderPainted(false);
  234. return b;
  235. }
  236. /**
  237. * Used to layout a MetalSplitPaneDivider. Layout for the divider
  238. * involves appropriately moving the left/right buttons around.
  239. * <p>
  240. * This inner class is marked "public" due to a compiler bug.
  241. * This class should be treated as a "protected" inner class.
  242. * Instantiate it only within subclasses of MetalSplitPaneDivider.
  243. */
  244. public class MetalDividerLayout implements LayoutManager {
  245. public void layoutContainer(Container c) {
  246. JButton leftButton = getLeftButtonFromSuper();
  247. JButton rightButton = getRightButtonFromSuper();
  248. JSplitPane splitPane = getSplitPaneFromSuper();
  249. int orientation = getOrientationFromSuper();
  250. int oneTouchSize = getOneTouchSizeFromSuper();
  251. int oneTouchOffset = getOneTouchOffsetFromSuper();
  252. int blockSize = Math.min(getDividerSize(), oneTouchSize);
  253. // This layout differs from the one used in BasicSplitPaneDivider.
  254. // It does not center justify the oneTouchExpadable buttons.
  255. // This was necessary in order to meet the spec of the Metal
  256. // splitpane divider.
  257. if (leftButton != null && rightButton != null &&
  258. c == MetalSplitPaneDivider.this) {
  259. if (splitPane.isOneTouchExpandable()) {
  260. if (orientation == JSplitPane.VERTICAL_SPLIT) {
  261. leftButton.setBounds(oneTouchOffset, 0,
  262. blockSize * 2, blockSize);
  263. rightButton.setBounds(oneTouchOffset +
  264. oneTouchSize * 2, 0,
  265. blockSize * 2, blockSize);
  266. }
  267. else {
  268. leftButton.setBounds(0, oneTouchOffset,
  269. blockSize, blockSize * 2);
  270. rightButton.setBounds(0, oneTouchOffset +
  271. oneTouchSize * 2, blockSize,
  272. blockSize * 2);
  273. }
  274. }
  275. else {
  276. leftButton.setBounds(-5, -5, 1, 1);
  277. rightButton.setBounds(-5, -5, 1, 1);
  278. }
  279. }
  280. }
  281. public Dimension minimumLayoutSize(Container c) {
  282. return new Dimension(0,0);
  283. }
  284. public Dimension preferredLayoutSize(Container c) {
  285. return new Dimension(0, 0);
  286. }
  287. public void removeLayoutComponent(Component c) {}
  288. public void addLayoutComponent(String string, Component c) {}
  289. }
  290. /*
  291. * The following methods only exist in order to be able to access protected
  292. * members in the superclass, because these are otherwise not available
  293. * in any inner class.
  294. */
  295. int getOneTouchSizeFromSuper() {
  296. return super.ONE_TOUCH_SIZE;
  297. }
  298. int getOneTouchOffsetFromSuper() {
  299. return super.ONE_TOUCH_OFFSET;
  300. }
  301. int getOrientationFromSuper() {
  302. return super.orientation;
  303. }
  304. JSplitPane getSplitPaneFromSuper() {
  305. return super.splitPane;
  306. }
  307. JButton getLeftButtonFromSuper() {
  308. return super.leftButton;
  309. }
  310. JButton getRightButtonFromSuper() {
  311. return super.rightButton;
  312. }
  313. }