1. /*
  2. * @(#)BasicRadioButtonUI.java 1.66 03/01/23
  3. *
  4. * Copyright 2003 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 javax.swing.*;
  11. import javax.swing.border.*;
  12. import javax.swing.plaf.*;
  13. import javax.swing.text.View;
  14. /**
  15. * RadioButtonUI implementation for BasicRadioButtonUI
  16. *
  17. * @version 1.66 01/23/03
  18. * @author Jeff Dinkins
  19. */
  20. public class BasicRadioButtonUI extends BasicToggleButtonUI
  21. {
  22. private final static BasicRadioButtonUI radioButtonUI = new BasicRadioButtonUI();
  23. protected Icon icon;
  24. private boolean defaults_initialized = false;
  25. private final static String propertyPrefix = "RadioButton" + ".";
  26. // ********************************
  27. // Create PLAF
  28. // ********************************
  29. public static ComponentUI createUI(JComponent b) {
  30. return radioButtonUI;
  31. }
  32. protected String getPropertyPrefix() {
  33. return propertyPrefix;
  34. }
  35. // ********************************
  36. // Install PLAF
  37. // ********************************
  38. protected void installDefaults(AbstractButton b){
  39. super.installDefaults(b);
  40. if(!defaults_initialized) {
  41. icon = UIManager.getIcon(getPropertyPrefix() + "icon");
  42. defaults_initialized = true;
  43. }
  44. }
  45. // ********************************
  46. // Uninstall PLAF
  47. // ********************************
  48. protected void uninstallDefaults(AbstractButton b){
  49. super.uninstallDefaults(b);
  50. defaults_initialized = false;
  51. }
  52. public Icon getDefaultIcon() {
  53. return icon;
  54. }
  55. /* These Dimensions/Rectangles are allocated once for all
  56. * RadioButtonUI.paint() calls. Re-using rectangles
  57. * rather than allocating them in each paint call substantially
  58. * reduced the time it took paint to run. Obviously, this
  59. * method can't be re-entered.
  60. */
  61. private static Dimension size = new Dimension();
  62. private static Rectangle viewRect = new Rectangle();
  63. private static Rectangle iconRect = new Rectangle();
  64. private static Rectangle textRect = new Rectangle();
  65. /**
  66. * paint the radio button
  67. */
  68. public synchronized void paint(Graphics g, JComponent c) {
  69. AbstractButton b = (AbstractButton) c;
  70. ButtonModel model = b.getModel();
  71. Font f = c.getFont();
  72. g.setFont(f);
  73. FontMetrics fm = g.getFontMetrics();
  74. Insets i = c.getInsets();
  75. size = b.getSize(size);
  76. viewRect.x = i.left;
  77. viewRect.y = i.top;
  78. viewRect.width = size.width - (i.right + viewRect.x);
  79. viewRect.height = size.height - (i.bottom + viewRect.y);
  80. iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
  81. textRect.x = textRect.y = textRect.width = textRect.height = 0;
  82. Icon altIcon = b.getIcon();
  83. Icon selectedIcon = null;
  84. Icon disabledIcon = null;
  85. String text = SwingUtilities.layoutCompoundLabel(
  86. c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(),
  87. b.getVerticalAlignment(), b.getHorizontalAlignment(),
  88. b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
  89. viewRect, iconRect, textRect,
  90. b.getText() == null ? 0 : b.getIconTextGap());
  91. // fill background
  92. if(c.isOpaque()) {
  93. g.setColor(b.getBackground());
  94. g.fillRect(0,0, size.width, size.height);
  95. }
  96. // Paint the radio button
  97. if(altIcon != null) {
  98. if(!model.isEnabled()) {
  99. if(model.isSelected()) {
  100. altIcon = b.getDisabledSelectedIcon();
  101. } else {
  102. altIcon = b.getDisabledIcon();
  103. }
  104. } else if(model.isPressed() && model.isArmed()) {
  105. altIcon = b.getPressedIcon();
  106. if(altIcon == null) {
  107. // Use selected icon
  108. altIcon = b.getSelectedIcon();
  109. }
  110. } else if(model.isSelected()) {
  111. if(b.isRolloverEnabled() && model.isRollover()) {
  112. altIcon = (Icon) b.getRolloverSelectedIcon();
  113. if (altIcon == null) {
  114. altIcon = (Icon) b.getSelectedIcon();
  115. }
  116. } else {
  117. altIcon = (Icon) b.getSelectedIcon();
  118. }
  119. } else if(b.isRolloverEnabled() && model.isRollover()) {
  120. altIcon = (Icon) b.getRolloverIcon();
  121. }
  122. if(altIcon == null) {
  123. altIcon = b.getIcon();
  124. }
  125. altIcon.paintIcon(c, g, iconRect.x, iconRect.y);
  126. } else {
  127. getDefaultIcon().paintIcon(c, g, iconRect.x, iconRect.y);
  128. }
  129. // Draw the Text
  130. if(text != null) {
  131. View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  132. if (v != null) {
  133. v.paint(g, textRect);
  134. } else {
  135. paintText(g, b, textRect, text);
  136. if(b.hasFocus() && b.isFocusPainted() &&
  137. textRect.width > 0 && textRect.height > 0 ) {
  138. paintFocus(g, textRect, size);
  139. }
  140. }
  141. }
  142. }
  143. protected void paintFocus(Graphics g, Rectangle textRect, Dimension size){
  144. }
  145. /* These Insets/Rectangles are allocated once for all
  146. * RadioButtonUI.getPreferredSize() calls. Re-using rectangles
  147. * rather than allocating them in each call substantially
  148. * reduced the time it took getPreferredSize() to run. Obviously,
  149. * this method can't be re-entered.
  150. */
  151. private static Rectangle prefViewRect = new Rectangle();
  152. private static Rectangle prefIconRect = new Rectangle();
  153. private static Rectangle prefTextRect = new Rectangle();
  154. private static Insets prefInsets = new Insets(0, 0, 0, 0);
  155. /**
  156. * The preferred size of the radio button
  157. */
  158. public Dimension getPreferredSize(JComponent c) {
  159. if(c.getComponentCount() > 0) {
  160. return null;
  161. }
  162. AbstractButton b = (AbstractButton) c;
  163. String text = b.getText();
  164. Icon buttonIcon = (Icon) b.getIcon();
  165. if(buttonIcon == null) {
  166. buttonIcon = getDefaultIcon();
  167. }
  168. Font font = b.getFont();
  169. // XXX - getFontMetrics has been deprecated but there isn't a
  170. // suitable replacement
  171. FontMetrics fm = b.getToolkit().getFontMetrics(font);
  172. prefViewRect.x = prefViewRect.y = 0;
  173. prefViewRect.width = Short.MAX_VALUE;
  174. prefViewRect.height = Short.MAX_VALUE;
  175. prefIconRect.x = prefIconRect.y = prefIconRect.width = prefIconRect.height = 0;
  176. prefTextRect.x = prefTextRect.y = prefTextRect.width = prefTextRect.height = 0;
  177. SwingUtilities.layoutCompoundLabel(
  178. c, fm, text, buttonIcon,
  179. b.getVerticalAlignment(), b.getHorizontalAlignment(),
  180. b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
  181. prefViewRect, prefIconRect, prefTextRect,
  182. text == null ? 0 : b.getIconTextGap());
  183. // find the union of the icon and text rects (from Rectangle.java)
  184. int x1 = Math.min(prefIconRect.x, prefTextRect.x);
  185. int x2 = Math.max(prefIconRect.x + prefIconRect.width,
  186. prefTextRect.x + prefTextRect.width);
  187. int y1 = Math.min(prefIconRect.y, prefTextRect.y);
  188. int y2 = Math.max(prefIconRect.y + prefIconRect.height,
  189. prefTextRect.y + prefTextRect.height);
  190. int width = x2 - x1;
  191. int height = y2 - y1;
  192. prefInsets = b.getInsets(prefInsets);
  193. width += prefInsets.left + prefInsets.right;
  194. height += prefInsets.top + prefInsets.bottom;
  195. return new Dimension(width, height);
  196. }
  197. }