1 /*
2 * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package javax.swing.plaf.basic;
27
28 import java.awt;
29 import java.awt.event;
30 import javax.swing;
31 import javax.swing.border;
32 import javax.swing.plaf;
33 import javax.swing.text.View;
34 import sun.swing.SwingUtilities2;
35
36
37 /**
38 * RadioButtonUI implementation for BasicRadioButtonUI
39 *
40 * @author Jeff Dinkins
41 */
42 public class BasicRadioButtonUI extends BasicToggleButtonUI
43 {
44 private final static BasicRadioButtonUI radioButtonUI = new BasicRadioButtonUI();
45
46 protected Icon icon;
47
48 private boolean defaults_initialized = false;
49
50 private final static String propertyPrefix = "RadioButton" + ".";
51
52 // ********************************
53 // Create PLAF
54 // ********************************
55 public static ComponentUI createUI(JComponent b) {
56 return radioButtonUI;
57 }
58
59 protected String getPropertyPrefix() {
60 return propertyPrefix;
61 }
62
63 // ********************************
64 // Install PLAF
65 // ********************************
66 protected void installDefaults(AbstractButton b){
67 super.installDefaults(b);
68 if(!defaults_initialized) {
69 icon = UIManager.getIcon(getPropertyPrefix() + "icon");
70 defaults_initialized = true;
71 }
72 }
73
74 // ********************************
75 // Uninstall PLAF
76 // ********************************
77 protected void uninstallDefaults(AbstractButton b){
78 super.uninstallDefaults(b);
79 defaults_initialized = false;
80 }
81
82 public Icon getDefaultIcon() {
83 return icon;
84 }
85
86
87 /* These Dimensions/Rectangles are allocated once for all
88 * RadioButtonUI.paint() calls. Re-using rectangles
89 * rather than allocating them in each paint call substantially
90 * reduced the time it took paint to run. Obviously, this
91 * method can't be re-entered.
92 */
93 private static Dimension size = new Dimension();
94 private static Rectangle viewRect = new Rectangle();
95 private static Rectangle iconRect = new Rectangle();
96 private static Rectangle textRect = new Rectangle();
97
98 /**
99 * paint the radio button
100 */
101 public synchronized void paint(Graphics g, JComponent c) {
102 AbstractButton b = (AbstractButton) c;
103 ButtonModel model = b.getModel();
104
105 Font f = c.getFont();
106 g.setFont(f);
107 FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
108
109 Insets i = c.getInsets();
110 size = b.getSize(size);
111 viewRect.x = i.left;
112 viewRect.y = i.top;
113 viewRect.width = size.width - (i.right + viewRect.x);
114 viewRect.height = size.height - (i.bottom + viewRect.y);
115 iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
116 textRect.x = textRect.y = textRect.width = textRect.height = 0;
117
118 Icon altIcon = b.getIcon();
119 Icon selectedIcon = null;
120 Icon disabledIcon = null;
121
122 String text = SwingUtilities.layoutCompoundLabel(
123 c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(),
124 b.getVerticalAlignment(), b.getHorizontalAlignment(),
125 b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
126 viewRect, iconRect, textRect,
127 b.getText() == null ? 0 : b.getIconTextGap());
128
129 // fill background
130 if(c.isOpaque()) {
131 g.setColor(b.getBackground());
132 g.fillRect(0,0, size.width, size.height);
133 }
134
135
136 // Paint the radio button
137 if(altIcon != null) {
138
139 if(!model.isEnabled()) {
140 if(model.isSelected()) {
141 altIcon = b.getDisabledSelectedIcon();
142 } else {
143 altIcon = b.getDisabledIcon();
144 }
145 } else if(model.isPressed() && model.isArmed()) {
146 altIcon = b.getPressedIcon();
147 if(altIcon == null) {
148 // Use selected icon
149 altIcon = b.getSelectedIcon();
150 }
151 } else if(model.isSelected()) {
152 if(b.isRolloverEnabled() && model.isRollover()) {
153 altIcon = (Icon) b.getRolloverSelectedIcon();
154 if (altIcon == null) {
155 altIcon = (Icon) b.getSelectedIcon();
156 }
157 } else {
158 altIcon = (Icon) b.getSelectedIcon();
159 }
160 } else if(b.isRolloverEnabled() && model.isRollover()) {
161 altIcon = (Icon) b.getRolloverIcon();
162 }
163
164 if(altIcon == null) {
165 altIcon = b.getIcon();
166 }
167
168 altIcon.paintIcon(c, g, iconRect.x, iconRect.y);
169
170 } else {
171 getDefaultIcon().paintIcon(c, g, iconRect.x, iconRect.y);
172 }
173
174
175 // Draw the Text
176 if(text != null) {
177 View v = (View) c.getClientProperty(BasicHTML.propertyKey);
178 if (v != null) {
179 v.paint(g, textRect);
180 } else {
181 paintText(g, b, textRect, text);
182 }
183 if(b.hasFocus() && b.isFocusPainted() &&
184 textRect.width > 0 && textRect.height > 0 ) {
185 paintFocus(g, textRect, size);
186 }
187 }
188 }
189
190 protected void paintFocus(Graphics g, Rectangle textRect, Dimension size){
191 }
192
193
194 /* These Insets/Rectangles are allocated once for all
195 * RadioButtonUI.getPreferredSize() calls. Re-using rectangles
196 * rather than allocating them in each call substantially
197 * reduced the time it took getPreferredSize() to run. Obviously,
198 * this method can't be re-entered.
199 */
200 private static Rectangle prefViewRect = new Rectangle();
201 private static Rectangle prefIconRect = new Rectangle();
202 private static Rectangle prefTextRect = new Rectangle();
203 private static Insets prefInsets = new Insets(0, 0, 0, 0);
204
205 /**
206 * The preferred size of the radio button
207 */
208 public Dimension getPreferredSize(JComponent c) {
209 if(c.getComponentCount() > 0) {
210 return null;
211 }
212
213 AbstractButton b = (AbstractButton) c;
214
215 String text = b.getText();
216
217 Icon buttonIcon = (Icon) b.getIcon();
218 if(buttonIcon == null) {
219 buttonIcon = getDefaultIcon();
220 }
221
222 Font font = b.getFont();
223 FontMetrics fm = b.getFontMetrics(font);
224
225 prefViewRect.x = prefViewRect.y = 0;
226 prefViewRect.width = Short.MAX_VALUE;
227 prefViewRect.height = Short.MAX_VALUE;
228 prefIconRect.x = prefIconRect.y = prefIconRect.width = prefIconRect.height = 0;
229 prefTextRect.x = prefTextRect.y = prefTextRect.width = prefTextRect.height = 0;
230
231 SwingUtilities.layoutCompoundLabel(
232 c, fm, text, buttonIcon,
233 b.getVerticalAlignment(), b.getHorizontalAlignment(),
234 b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
235 prefViewRect, prefIconRect, prefTextRect,
236 text == null ? 0 : b.getIconTextGap());
237
238 // find the union of the icon and text rects (from Rectangle.java)
239 int x1 = Math.min(prefIconRect.x, prefTextRect.x);
240 int x2 = Math.max(prefIconRect.x + prefIconRect.width,
241 prefTextRect.x + prefTextRect.width);
242 int y1 = Math.min(prefIconRect.y, prefTextRect.y);
243 int y2 = Math.max(prefIconRect.y + prefIconRect.height,
244 prefTextRect.y + prefTextRect.height);
245 int width = x2 - x1;
246 int height = y2 - y1;
247
248 prefInsets = b.getInsets(prefInsets);
249 width += prefInsets.left + prefInsets.right;
250 height += prefInsets.top + prefInsets.bottom;
251 return new Dimension(width, height);
252 }
253 }