1. /*
  2. * @(#)BasicButtonUI.java 1.98 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.basic;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.io.Serializable;
  11. import javax.swing.*;
  12. import javax.swing.border.*;
  13. import java.awt.*;
  14. import java.awt.event.*;
  15. import javax.swing.plaf.ButtonUI;
  16. import javax.swing.plaf.UIResource;
  17. import javax.swing.plaf.ComponentUI;
  18. import javax.swing.text.View;
  19. /**
  20. * BasicButton implementation
  21. *
  22. * @version 1.98 11/29/01
  23. * @author Jeff Dinkins
  24. */
  25. public class BasicButtonUI extends ButtonUI{
  26. // Shared UI object
  27. private final static BasicButtonUI buttonUI = new BasicButtonUI();
  28. // Visual constants
  29. protected int defaultTextIconGap;
  30. // Offset controlled by set method
  31. private int shiftOffset = 0;
  32. protected int defaultTextShiftOffset;
  33. // Has the shared instance defaults been initialized?
  34. private boolean defaults_initialized = false;
  35. private final static String propertyPrefix = "Button" + ".";
  36. // ********************************
  37. // Create PLAF
  38. // ********************************
  39. public static ComponentUI createUI(JComponent c) {
  40. return buttonUI;
  41. }
  42. protected String getPropertyPrefix() {
  43. return propertyPrefix;
  44. }
  45. // ********************************
  46. // Install PLAF
  47. // ********************************
  48. public void installUI(JComponent c) {
  49. installDefaults((AbstractButton) c);
  50. installListeners((AbstractButton) c);
  51. installKeyboardActions((AbstractButton) c);
  52. BasicHTML.updateRenderer(c, ((AbstractButton) c).getText());
  53. }
  54. private Color defaultForeground = null;
  55. private Color defaultBackground = null;
  56. private Font defaultFont = null;
  57. private Border defaultBorder = null;
  58. protected void installDefaults(AbstractButton b) {
  59. // load shared instance defaults
  60. String pp = getPropertyPrefix();
  61. if(!defaults_initialized) {
  62. defaultTextIconGap = ((Integer)UIManager.get(pp + "textIconGap")).intValue();
  63. defaultTextShiftOffset = ((Integer)UIManager.get(pp + "textShiftOffset")).intValue();
  64. // next four lines part of optimized component defaults installation
  65. /* defaultForeground = UIManager.getColor(pp + "foreground");
  66. defaultBackground = UIManager.getColor(pp + "background");
  67. defaultFont = UIManager.getFont(pp + "font");
  68. defaultBorder = UIManager.getBorder(pp + "border");*/
  69. defaults_initialized = true;
  70. }
  71. // set the following defaults on the button
  72. if (b.isContentAreaFilled()) {
  73. b.setOpaque(true);
  74. } else {
  75. b.setOpaque(false);
  76. }
  77. if(b.getMargin() == null || (b.getMargin() instanceof UIResource)) {
  78. b.setMargin(UIManager.getInsets(pp + "margin"));
  79. }
  80. // *** begin optimized defaults install ***
  81. /* Color currentForeground = b.getForeground();
  82. Color currentBackground = b.getBackground();
  83. Font currentFont = b.getFont();
  84. Border currentBorder = b.getBorder();
  85. if (currentForeground == null || currentForeground instanceof UIResource) {
  86. b.setForeground(defaultForeground);
  87. }
  88. if (currentBackground == null || currentBackground instanceof UIResource) {
  89. b.setBackground(defaultBackground);
  90. }
  91. if (currentFont == null || currentFont instanceof UIResource) {
  92. b.setFont(defaultFont);
  93. }
  94. if (currentBorder == null || currentBorder instanceof UIResource) {
  95. b.setBorder(defaultBorder);
  96. } */
  97. // *** end optimized defaults install ***
  98. // old code below works for component defaults installation, but it is slow
  99. LookAndFeel.installColorsAndFont(b, pp + "background", pp + "foreground", pp + "font");
  100. LookAndFeel.installBorder(b, pp + "border");
  101. }
  102. protected void installListeners(AbstractButton b) {
  103. BasicButtonListener listener = createButtonListener(b);
  104. if(listener != null) {
  105. // put the listener in the button's client properties so that
  106. // we can get at it later
  107. b.putClientProperty(this, listener);
  108. b.addMouseListener(listener);
  109. b.addMouseMotionListener(listener);
  110. b.addFocusListener(listener);
  111. b.addPropertyChangeListener(listener);
  112. b.addChangeListener(listener);
  113. }
  114. }
  115. protected void installKeyboardActions(AbstractButton b){
  116. BasicButtonListener listener = (BasicButtonListener) b.getClientProperty(this);
  117. if(listener != null) {
  118. listener.installKeyboardActions(b);
  119. }
  120. }
  121. // ********************************
  122. // Uninstall PLAF
  123. // ********************************
  124. public void uninstallUI(JComponent c) {
  125. uninstallKeyboardActions((AbstractButton) c);
  126. uninstallListeners((AbstractButton) c);
  127. uninstallDefaults((AbstractButton) c);
  128. BasicHTML.updateRenderer(c, "");
  129. }
  130. protected void uninstallKeyboardActions(AbstractButton b) {
  131. BasicButtonListener listener = (BasicButtonListener) b.getClientProperty(this);
  132. if(listener != null) {
  133. listener.uninstallKeyboardActions(b);
  134. }
  135. }
  136. protected void uninstallListeners(AbstractButton b) {
  137. BasicButtonListener listener = (BasicButtonListener) b.getClientProperty(this);
  138. b.putClientProperty(this, null);
  139. if(listener != null) {
  140. b.removeMouseListener(listener);
  141. b.removeMouseListener(listener);
  142. b.removeMouseMotionListener(listener);
  143. b.removeFocusListener(listener);
  144. b.removeChangeListener(listener);
  145. b.removePropertyChangeListener(listener);
  146. }
  147. }
  148. protected void uninstallDefaults(AbstractButton b) {
  149. LookAndFeel.uninstallBorder(b);
  150. defaults_initialized = false;
  151. }
  152. // ********************************
  153. // Create Listeners
  154. // ********************************
  155. protected BasicButtonListener createButtonListener(AbstractButton b) {
  156. return new BasicButtonListener(b);
  157. }
  158. public int getDefaultTextIconGap(AbstractButton b) {
  159. return defaultTextIconGap;
  160. }
  161. /* These rectangles/insets are allocated once for all
  162. * ButtonUI.paint() calls. Re-using rectangles rather than
  163. * allocating them in each paint call substantially reduced the time
  164. * it took paint to run. Obviously, this method can't be re-entered.
  165. */
  166. private static Rectangle viewRect = new Rectangle();
  167. private static Rectangle textRect = new Rectangle();
  168. private static Rectangle iconRect = new Rectangle();
  169. // ********************************
  170. // Paint Methods
  171. // ********************************
  172. public void paint(Graphics g, JComponent c)
  173. {
  174. AbstractButton b = (AbstractButton) c;
  175. ButtonModel model = b.getModel();
  176. FontMetrics fm = g.getFontMetrics();
  177. Insets i = c.getInsets();
  178. viewRect.x = i.left;
  179. viewRect.y = i.top;
  180. viewRect.width = b.getWidth() - (i.right + viewRect.x);
  181. viewRect.height = b.getHeight() - (i.bottom + viewRect.y);
  182. textRect.x = textRect.y = textRect.width = textRect.height = 0;
  183. iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
  184. Font f = c.getFont();
  185. g.setFont(f);
  186. // layout the text and icon
  187. String text = SwingUtilities.layoutCompoundLabel(
  188. c, fm, b.getText(), b.getIcon(),
  189. b.getVerticalAlignment(), b.getHorizontalAlignment(),
  190. b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
  191. viewRect, iconRect, textRect,
  192. b.getText() == null ? 0 : defaultTextIconGap
  193. );
  194. clearTextShiftOffset();
  195. // perform UI specific press action, e.g. Windows L&F shifts text
  196. if (model.isArmed() && model.isPressed()) {
  197. paintButtonPressed(g,b);
  198. }
  199. // Paint the Icon
  200. if(b.getIcon() != null) {
  201. paintIcon(g,c,iconRect);
  202. }
  203. if (text != null && !text.equals("")){
  204. View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  205. if (v != null) {
  206. v.paint(g, textRect);
  207. } else {
  208. paintText(g, c,textRect, text);
  209. }
  210. }
  211. if (b.isFocusPainted() && b.hasFocus()) {
  212. // paint UI specific focus
  213. paintFocus(g,b,viewRect,textRect,iconRect);
  214. }
  215. }
  216. protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect){
  217. AbstractButton b = (AbstractButton) c;
  218. ButtonModel model = b.getModel();
  219. Icon icon = null;
  220. if(!model.isEnabled()) {
  221. icon = (Icon) b.getDisabledIcon();
  222. } else if(model.isPressed() && model.isArmed()) {
  223. icon = (Icon) b.getPressedIcon();
  224. if(icon == null) {
  225. // Use default icon
  226. icon = (Icon) b.getIcon();
  227. } else {
  228. // revert back to 0 offset
  229. clearTextShiftOffset();
  230. }
  231. } else if(b.isRolloverEnabled() && model.isRollover()) {
  232. icon = (Icon) b.getRolloverIcon();
  233. }
  234. if (icon == null) {
  235. icon = (Icon) b.getIcon();
  236. }
  237. if(model.isPressed() && model.isArmed()) {
  238. icon.paintIcon(c, g, iconRect.x + getTextShiftOffset(),
  239. iconRect.y + getTextShiftOffset());
  240. } else {
  241. icon.paintIcon(c, g, iconRect.x, iconRect.y);
  242. }
  243. }
  244. protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) {
  245. AbstractButton b = (AbstractButton) c;
  246. ButtonModel model = b.getModel();
  247. FontMetrics fm = g.getFontMetrics();
  248. /* Draw the Text */
  249. if(model.isEnabled()) {
  250. /*** paint the text normally */
  251. g.setColor(b.getForeground());
  252. BasicGraphicsUtils.drawString(g,text, model.getMnemonic(),
  253. textRect.x + getTextShiftOffset(),
  254. textRect.y + fm.getAscent() + getTextShiftOffset());
  255. }
  256. else {
  257. /*** paint the text disabled ***/
  258. g.setColor(b.getBackground().brighter());
  259. BasicGraphicsUtils.drawString(g,text,model.getMnemonic(),
  260. textRect.x, textRect.y + fm.getAscent());
  261. g.setColor(b.getBackground().darker());
  262. BasicGraphicsUtils.drawString(g,text,model.getMnemonic(),
  263. textRect.x - 1, textRect.y + fm.getAscent() - 1);
  264. }
  265. }
  266. protected void paintFocus(Graphics g, AbstractButton b,
  267. Rectangle viewRect, Rectangle textRect, Rectangle iconRect){
  268. }
  269. protected void paintButtonPressed(Graphics g, AbstractButton b){
  270. }
  271. protected void clearTextShiftOffset(){
  272. this.shiftOffset = 0;
  273. }
  274. protected void setTextShiftOffset(){
  275. this.shiftOffset = defaultTextShiftOffset;
  276. }
  277. protected int getTextShiftOffset() {
  278. return shiftOffset;
  279. }
  280. // ********************************
  281. // Layout Methods
  282. // ********************************
  283. public Dimension getMinimumSize(JComponent c) {
  284. Dimension d = getPreferredSize(c);
  285. View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  286. if (v != null) {
  287. d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
  288. }
  289. return d;
  290. }
  291. public Dimension getPreferredSize(JComponent c) {
  292. AbstractButton b = (AbstractButton)c;
  293. return BasicGraphicsUtils.getPreferredButtonSize(b, defaultTextIconGap);
  294. }
  295. public Dimension getMaximumSize(JComponent c) {
  296. Dimension d = getPreferredSize(c);
  297. View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  298. if (v != null) {
  299. d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
  300. }
  301. return d;
  302. }
  303. }