1. /*
  2. * @(#)BasicBorders.java 1.20 00/02/02
  3. *
  4. * Copyright 1997-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.basic;
  11. import javax.swing.*;
  12. import javax.swing.border.*;
  13. import javax.swing.plaf.*;
  14. import javax.swing.text.JTextComponent;
  15. import java.awt.Component;
  16. import java.awt.Insets;
  17. import java.awt.Dimension;
  18. import java.awt.Rectangle;
  19. import java.awt.Color;
  20. import java.awt.Graphics;
  21. import java.io.Serializable;
  22. /**
  23. * Factory object that can vend Borders appropriate for the basic L & F.
  24. * @version 1.20 02/02/00
  25. * @author Georges Saab
  26. * @author Amy Fowler
  27. */
  28. public class BasicBorders {
  29. public static Border getButtonBorder() {
  30. UIDefaults table = UIManager.getLookAndFeelDefaults();
  31. Border buttonBorder = new BorderUIResource.CompoundBorderUIResource(
  32. new BasicBorders.ButtonBorder(
  33. table.getColor("controlShadow"),
  34. table.getColor("controlDkShadow"),
  35. table.getColor("controlHighlight"),
  36. table.getColor("controlLtHighlight")),
  37. new MarginBorder());
  38. return buttonBorder;
  39. }
  40. public static Border getRadioButtonBorder() {
  41. UIDefaults table = UIManager.getLookAndFeelDefaults();
  42. Border radioButtonBorder = new BorderUIResource.CompoundBorderUIResource(
  43. new BasicBorders.RadioButtonBorder(
  44. table.getColor("controlShadow"),
  45. table.getColor("controlDkShadow"),
  46. table.getColor("controlHighlight"),
  47. table.getColor("controlLtHighlight")),
  48. new MarginBorder());
  49. return radioButtonBorder;
  50. }
  51. public static Border getToggleButtonBorder() {
  52. UIDefaults table = UIManager.getLookAndFeelDefaults();
  53. Border toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
  54. new BasicBorders.ToggleButtonBorder(
  55. table.getColor("controlShadow"),
  56. table.getColor("controlDkShadow"),
  57. table.getColor("controlHighlight"),
  58. table.getColor("controlLtHighlight")),
  59. new MarginBorder());
  60. return toggleButtonBorder;
  61. }
  62. public static Border getMenuBarBorder() {
  63. UIDefaults table = UIManager.getLookAndFeelDefaults();
  64. Border menuBarBorder = new BasicBorders.MenuBarBorder(
  65. table.getColor("controlShadow"),
  66. table.getColor("controlLtHighlight")
  67. );
  68. return menuBarBorder;
  69. }
  70. public static Border getSplitPaneBorder() {
  71. UIDefaults table = UIManager.getLookAndFeelDefaults();
  72. Border splitPaneBorder = new BasicBorders.SplitPaneBorder(
  73. table.getColor("controlLtHighlight"),
  74. table.getColor("controlDkShadow"));
  75. return splitPaneBorder;
  76. }
  77. /**
  78. * Returns a border instance for a JSplitPane divider
  79. * @since 1.3
  80. */
  81. public static Border getSplitPaneDividerBorder() {
  82. UIDefaults table = UIManager.getLookAndFeelDefaults();
  83. Border splitPaneBorder = new BasicBorders.SplitPaneDividerBorder(
  84. table.getColor("controlLtHighlight"),
  85. table.getColor("controlDkShadow"));
  86. return splitPaneBorder;
  87. }
  88. public static Border getTextFieldBorder() {
  89. UIDefaults table = UIManager.getLookAndFeelDefaults();
  90. Border textFieldBorder = new BasicBorders.FieldBorder(
  91. table.getColor("controlShadow"),
  92. table.getColor("controlDkShadow"),
  93. table.getColor("controlHighlight"),
  94. table.getColor("controlLtHighlight"));
  95. return textFieldBorder;
  96. }
  97. public static Border getProgressBarBorder() {
  98. UIDefaults table = UIManager.getLookAndFeelDefaults();
  99. Border progressBarBorder = new BorderUIResource.LineBorderUIResource(Color.green, 2);
  100. return progressBarBorder;
  101. }
  102. public static Border getInternalFrameBorder() {
  103. UIDefaults table = UIManager.getLookAndFeelDefaults();
  104. Border internalFrameBorder = new BorderUIResource.CompoundBorderUIResource(
  105. new BevelBorder(BevelBorder.RAISED,
  106. table.getColor("controlHighlight"),
  107. table.getColor("controlLtHighlight"),
  108. table.getColor("controlDkShadow"),
  109. table.getColor("controlShadow")),
  110. BorderFactory.createLineBorder(
  111. table.getColor("control"), 1));
  112. return internalFrameBorder;
  113. }
  114. public static class ButtonBorder extends AbstractBorder implements UIResource {
  115. protected Color shadow;
  116. protected Color darkShadow;
  117. protected Color highlight;
  118. protected Color lightHighlight;
  119. public ButtonBorder(Color shadow, Color darkShadow,
  120. Color highlight, Color lightHighlight) {
  121. this.shadow = shadow;
  122. this.darkShadow = darkShadow;
  123. this.highlight = highlight;
  124. this.lightHighlight = lightHighlight;
  125. }
  126. public void paintBorder(Component c, Graphics g, int x, int y,
  127. int width, int height) {
  128. boolean isPressed = false;
  129. boolean isDefault = false;
  130. if (c instanceof AbstractButton) {
  131. AbstractButton b = (AbstractButton)c;
  132. ButtonModel model = b.getModel();
  133. isPressed = model.isPressed() && model.isArmed();
  134. if (c instanceof JButton) {
  135. isDefault = ((JButton)c).isDefaultButton();
  136. }
  137. }
  138. BasicGraphicsUtils.drawBezel(g, x, y, width, height,
  139. isPressed, isDefault, shadow,
  140. darkShadow, highlight, lightHighlight);
  141. }
  142. public Insets getBorderInsets(Component c) {
  143. // leave room for default visual
  144. return new Insets(3,3,3,3);
  145. }
  146. }
  147. public static class ToggleButtonBorder extends ButtonBorder {
  148. public ToggleButtonBorder(Color shadow, Color darkShadow,
  149. Color highlight, Color lightHighlight) {
  150. super(shadow, darkShadow, highlight, lightHighlight);
  151. }
  152. public void paintBorder(Component c, Graphics g, int x, int y,
  153. int width, int height) {
  154. BasicGraphicsUtils.drawBezel(g, x, y, width, height,
  155. false, false,
  156. shadow, darkShadow,
  157. highlight, lightHighlight);
  158. }
  159. public Insets getBorderInsets(Component c) {
  160. return new Insets(2, 2, 2, 2);
  161. }
  162. }
  163. public static class RadioButtonBorder extends ButtonBorder {
  164. public RadioButtonBorder(Color shadow, Color darkShadow,
  165. Color highlight, Color lightHighlight) {
  166. super(shadow, darkShadow, highlight, lightHighlight);
  167. }
  168. public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
  169. if (c instanceof AbstractButton) {
  170. AbstractButton b = (AbstractButton)c;
  171. ButtonModel model = b.getModel();
  172. if (model.isArmed() && model.isPressed() || model.isSelected()) {
  173. BasicGraphicsUtils.drawLoweredBezel(g, x, y, width, height,
  174. shadow, darkShadow,
  175. highlight, lightHighlight);
  176. } else {
  177. BasicGraphicsUtils.drawBezel(g, x, y, width, height,
  178. false, b.isFocusPainted() && b.hasFocus(),
  179. shadow, darkShadow,
  180. highlight, lightHighlight);
  181. }
  182. } else {
  183. BasicGraphicsUtils.drawBezel(g, x, y, width, height, false, false,
  184. shadow, darkShadow, highlight, lightHighlight);
  185. }
  186. }
  187. public Insets getBorderInsets(Component c) {
  188. return new Insets(2, 2, 2, 2);
  189. }
  190. }
  191. public static class MenuBarBorder extends AbstractBorder implements UIResource {
  192. private Color shadow;
  193. private Color highlight;
  194. public MenuBarBorder(Color shadow, Color highlight) {
  195. this.shadow = shadow;
  196. this.highlight = highlight;
  197. }
  198. public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
  199. BasicGraphicsUtils.drawGroove(g, 0, height-2,
  200. width, height,
  201. shadow, highlight);
  202. }
  203. public Insets getBorderInsets(Component c) {
  204. return new Insets(0, 0, 2, 0);
  205. }
  206. }
  207. public static class MarginBorder extends AbstractBorder implements UIResource {
  208. public Insets getBorderInsets(Component c) {
  209. Insets margin = null;
  210. //
  211. // Ideally we'd have an interface defined for classes which
  212. // support margins (to avoid this hackery), but we've
  213. // decided against it for simplicity
  214. //
  215. if (c instanceof AbstractButton) {
  216. AbstractButton b = (AbstractButton)c;
  217. margin = b.getMargin();
  218. } else if (c instanceof JToolBar) {
  219. JToolBar t = (JToolBar)c;
  220. margin = t.getMargin();
  221. } else if (c instanceof JTextComponent) {
  222. JTextComponent t = (JTextComponent)c;
  223. margin = t.getMargin();
  224. }
  225. return (margin != null? margin : new Insets(0, 0, 0, 0));
  226. }
  227. }
  228. public static class FieldBorder extends AbstractBorder implements UIResource {
  229. protected Color shadow;
  230. protected Color darkShadow;
  231. protected Color highlight;
  232. protected Color lightHighlight;
  233. public FieldBorder(Color shadow, Color darkShadow,
  234. Color highlight, Color lightHighlight) {
  235. this.shadow = shadow;
  236. this.highlight = highlight;
  237. this.darkShadow = darkShadow;
  238. this.lightHighlight = lightHighlight;
  239. }
  240. public void paintBorder(Component c, Graphics g, int x, int y,
  241. int width, int height) {
  242. BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height,
  243. shadow, darkShadow,
  244. highlight, lightHighlight);
  245. }
  246. public Insets getBorderInsets(Component c) {
  247. Insets margin = null;
  248. if (c instanceof JTextComponent) {
  249. margin = ((JTextComponent)c).getMargin();
  250. }
  251. if (margin != null) {
  252. return new Insets(2+margin.top, 2+margin.left,
  253. 2+margin.bottom, 2+margin.right);
  254. }
  255. return new Insets(2, 2, 2, 2);
  256. }
  257. }
  258. /**
  259. * Draws the border around the divider in a splitpane
  260. * (when BasicSplitPaneUI is used). To get the appropriate effect, this
  261. * needs to be used with a SplitPaneBorder.
  262. */
  263. static class SplitPaneDividerBorder implements Border, UIResource {
  264. Color highlight;
  265. Color shadow;
  266. SplitPaneDividerBorder(Color highlight, Color shadow) {
  267. this.highlight = highlight;
  268. this.shadow = shadow;
  269. }
  270. public void paintBorder(Component c, Graphics g, int x, int y,
  271. int width, int height) {
  272. Component child;
  273. Rectangle cBounds;
  274. JSplitPane splitPane = ((BasicSplitPaneDivider)c).
  275. getBasicSplitPaneUI().getSplitPane();
  276. Dimension size = c.getSize();
  277. child = splitPane.getLeftComponent();
  278. // This is needed for the space between the divider and end of
  279. // splitpane.
  280. g.setColor(c.getBackground());
  281. g.drawRect(x, y, width - 1, height - 1);
  282. if(splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
  283. if(child != null) {
  284. g.setColor(highlight);
  285. g.drawLine(0, 0, 0, size.height);
  286. }
  287. child = splitPane.getRightComponent();
  288. if(child != null) {
  289. g.setColor(shadow);
  290. g.drawLine(size.width - 1, 0, size.width - 1, size.height);
  291. }
  292. } else {
  293. if(child != null) {
  294. g.setColor(highlight);
  295. g.drawLine(0, 0, size.width, 0);
  296. }
  297. child = splitPane.getRightComponent();
  298. if(child != null) {
  299. g.setColor(shadow);
  300. g.drawLine(0, size.height - 1, size.width,
  301. size.height - 1);
  302. }
  303. }
  304. }
  305. public Insets getBorderInsets(Component c) {
  306. if (c instanceof BasicSplitPaneDivider) {
  307. BasicSplitPaneUI bspui = ((BasicSplitPaneDivider)c).
  308. getBasicSplitPaneUI();
  309. if (bspui != null) {
  310. JSplitPane splitPane = bspui.getSplitPane();
  311. if (splitPane != null) {
  312. if (splitPane.getOrientation() ==
  313. JSplitPane.HORIZONTAL_SPLIT) {
  314. return new Insets(0, 1, 0, 1);
  315. }
  316. // VERTICAL_SPLIT
  317. return new Insets(1, 0, 1, 0);
  318. }
  319. }
  320. }
  321. return new Insets(1, 1, 1, 1);
  322. }
  323. public boolean isBorderOpaque() { return true; }
  324. }
  325. /**
  326. * Draws the border around the splitpane. To work correctly you shoudl
  327. * also install a border on the divider (property SplitPaneDivider.border).
  328. */
  329. public static class SplitPaneBorder implements Border, UIResource {
  330. protected Color highlight;
  331. protected Color shadow;
  332. public SplitPaneBorder(Color highlight, Color shadow) {
  333. this.highlight = highlight;
  334. this.shadow = shadow;
  335. }
  336. public void paintBorder(Component c, Graphics g, int x, int y,
  337. int width, int height) {
  338. // The only tricky part with this border is that the divider is
  339. // not positioned at the top (for horizontal) or left (for vert),
  340. // so this border draws to where the divider is:
  341. // -----------------
  342. // |xxxxxxx xxxxxxx|
  343. // |x --- x|
  344. // |x | | x|
  345. // |x |D| x|
  346. // |x | | x|
  347. // |x --- x|
  348. // |xxxxxxx xxxxxxx|
  349. // -----------------
  350. // The above shows (rather excessively) what this looks like for
  351. // a horizontal orientation. This border then draws the x's, with
  352. // the SplitPaneDividerBorder drawing its own border.
  353. Component child;
  354. Rectangle cBounds;
  355. JSplitPane splitPane = (JSplitPane)c;
  356. child = splitPane.getLeftComponent();
  357. // This is needed for the space between the divider and end of
  358. // splitpane.
  359. g.setColor(c.getBackground());
  360. g.drawRect(x, y, width - 1, height - 1);
  361. if(splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
  362. if(child != null) {
  363. cBounds = child.getBounds();
  364. g.setColor(shadow);
  365. g.drawLine(0, 0, cBounds.width + 1, 0);
  366. g.drawLine(0, 1, 0, cBounds.height + 2);
  367. g.setColor(highlight);
  368. g.drawLine(1, cBounds.height + 1, cBounds.width + 1,
  369. cBounds.height + 1);
  370. }
  371. child = splitPane.getRightComponent();
  372. if(child != null) {
  373. cBounds = child.getBounds();
  374. int maxX = cBounds.x + cBounds.width;
  375. int maxY = cBounds.y + cBounds.height;
  376. g.setColor(shadow);
  377. g.drawLine(cBounds.x - 1, 0, maxX, 0);
  378. g.drawLine(cBounds.x - 1, maxY, cBounds.x, maxY);
  379. g.setColor(highlight);
  380. g.drawLine(cBounds.x, maxY, maxX, maxY);
  381. g.drawLine(maxX, 0, maxX, maxY + 1);
  382. }
  383. } else {
  384. if(child != null) {
  385. cBounds = child.getBounds();
  386. g.setColor(shadow);
  387. g.drawLine(0, 0, cBounds.width + 1, 0);
  388. g.drawLine(0, 1, 0, cBounds.height);
  389. g.setColor(highlight);
  390. g.drawLine(1 + cBounds.width, 0, 1 + cBounds.width,
  391. cBounds.height + 1);
  392. g.drawLine(0, cBounds.height + 1, 0, cBounds.height + 1);
  393. }
  394. child = splitPane.getRightComponent();
  395. if(child != null) {
  396. cBounds = child.getBounds();
  397. int maxX = cBounds.x + cBounds.width;
  398. int maxY = cBounds.y + cBounds.height;
  399. g.setColor(shadow);
  400. g.drawLine(0, cBounds.y - 1, 0, maxY);
  401. g.drawLine(maxX, cBounds.y - 1, maxX, cBounds.y - 1);
  402. g.drawLine(0, cBounds.y - 1, cBounds.width, cBounds.y - 1);
  403. g.setColor(highlight);
  404. g.drawLine(0, maxY, cBounds.width + 1, maxY);
  405. g.drawLine(maxX, cBounds.y, maxX, maxY);
  406. }
  407. }
  408. }
  409. public Insets getBorderInsets(Component c) {
  410. return new Insets(1, 1, 1, 1);
  411. }
  412. public boolean isBorderOpaque() { return true; }
  413. }
  414. }