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