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