001 /*
002 * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.swing.plaf.basic;
027
028 import java.awt.*;
029 import java.awt.event.*;
030 import javax.swing.*;
031 import javax.swing.border.*;
032 import javax.swing.plaf.*;
033 import javax.swing.text.View;
034 import sun.swing.SwingUtilities2;
035
036 /**
037 * RadioButtonUI implementation for BasicRadioButtonUI
038 *
039 * @version 1.77 05/05/07
040 * @author Jeff Dinkins
041 */
042 public class BasicRadioButtonUI extends BasicToggleButtonUI {
043 private final static BasicRadioButtonUI radioButtonUI = new BasicRadioButtonUI();
044
045 protected Icon icon;
046
047 private boolean defaults_initialized = false;
048
049 private final static String propertyPrefix = "RadioButton" + ".";
050
051 // ********************************
052 // Create PLAF
053 // ********************************
054 public static ComponentUI createUI(JComponent b) {
055 return radioButtonUI;
056 }
057
058 protected String getPropertyPrefix() {
059 return propertyPrefix;
060 }
061
062 // ********************************
063 // Install PLAF
064 // ********************************
065 protected void installDefaults(AbstractButton b) {
066 super .installDefaults(b);
067 if (!defaults_initialized) {
068 icon = UIManager.getIcon(getPropertyPrefix() + "icon");
069 defaults_initialized = true;
070 }
071 }
072
073 // ********************************
074 // Uninstall PLAF
075 // ********************************
076 protected void uninstallDefaults(AbstractButton b) {
077 super .uninstallDefaults(b);
078 defaults_initialized = false;
079 }
080
081 public Icon getDefaultIcon() {
082 return icon;
083 }
084
085 /* These Dimensions/Rectangles are allocated once for all
086 * RadioButtonUI.paint() calls. Re-using rectangles
087 * rather than allocating them in each paint call substantially
088 * reduced the time it took paint to run. Obviously, this
089 * method can't be re-entered.
090 */
091 private static Dimension size = new Dimension();
092 private static Rectangle viewRect = new Rectangle();
093 private static Rectangle iconRect = new Rectangle();
094 private static Rectangle textRect = new Rectangle();
095
096 /**
097 * paint the radio button
098 */
099 public synchronized void paint(Graphics g, JComponent c) {
100 AbstractButton b = (AbstractButton) c;
101 ButtonModel model = b.getModel();
102
103 Font f = c.getFont();
104 g.setFont(f);
105 FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
106
107 Insets i = c.getInsets();
108 size = b.getSize(size);
109 viewRect.x = i.left;
110 viewRect.y = i.top;
111 viewRect.width = size.width - (i.right + viewRect.x);
112 viewRect.height = size.height - (i.bottom + viewRect.y);
113 iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
114 textRect.x = textRect.y = textRect.width = textRect.height = 0;
115
116 Icon altIcon = b.getIcon();
117 Icon selectedIcon = null;
118 Icon disabledIcon = null;
119
120 String text = SwingUtilities.layoutCompoundLabel(c, fm, b
121 .getText(), altIcon != null ? altIcon
122 : getDefaultIcon(), b.getVerticalAlignment(), b
123 .getHorizontalAlignment(), b.getVerticalTextPosition(),
124 b.getHorizontalTextPosition(), viewRect, iconRect,
125 textRect, b.getText() == null ? 0 : b.getIconTextGap());
126
127 // fill background
128 if (c.isOpaque()) {
129 g.setColor(b.getBackground());
130 g.fillRect(0, 0, size.width, size.height);
131 }
132
133 // Paint the radio button
134 if (altIcon != null) {
135
136 if (!model.isEnabled()) {
137 if (model.isSelected()) {
138 altIcon = b.getDisabledSelectedIcon();
139 } else {
140 altIcon = b.getDisabledIcon();
141 }
142 } else if (model.isPressed() && model.isArmed()) {
143 altIcon = b.getPressedIcon();
144 if (altIcon == null) {
145 // Use selected icon
146 altIcon = b.getSelectedIcon();
147 }
148 } else if (model.isSelected()) {
149 if (b.isRolloverEnabled() && model.isRollover()) {
150 altIcon = (Icon) b.getRolloverSelectedIcon();
151 if (altIcon == null) {
152 altIcon = (Icon) b.getSelectedIcon();
153 }
154 } else {
155 altIcon = (Icon) b.getSelectedIcon();
156 }
157 } else if (b.isRolloverEnabled() && model.isRollover()) {
158 altIcon = (Icon) b.getRolloverIcon();
159 }
160
161 if (altIcon == null) {
162 altIcon = b.getIcon();
163 }
164
165 altIcon.paintIcon(c, g, iconRect.x, iconRect.y);
166
167 } else {
168 getDefaultIcon().paintIcon(c, g, iconRect.x, iconRect.y);
169 }
170
171 // Draw the Text
172 if (text != null) {
173 View v = (View) c.getClientProperty(BasicHTML.propertyKey);
174 if (v != null) {
175 v.paint(g, textRect);
176 } else {
177 paintText(g, b, textRect, text);
178 }
179 if (b.hasFocus() && b.isFocusPainted()
180 && textRect.width > 0 && textRect.height > 0) {
181 paintFocus(g, textRect, size);
182 }
183 }
184 }
185
186 protected void paintFocus(Graphics g, Rectangle textRect,
187 Dimension size) {
188 }
189
190 /* These Insets/Rectangles are allocated once for all
191 * RadioButtonUI.getPreferredSize() calls. Re-using rectangles
192 * rather than allocating them in each call substantially
193 * reduced the time it took getPreferredSize() to run. Obviously,
194 * this method can't be re-entered.
195 */
196 private static Rectangle prefViewRect = new Rectangle();
197 private static Rectangle prefIconRect = new Rectangle();
198 private static Rectangle prefTextRect = new Rectangle();
199 private static Insets prefInsets = new Insets(0, 0, 0, 0);
200
201 /**
202 * The preferred size of the radio button
203 */
204 public Dimension getPreferredSize(JComponent c) {
205 if (c.getComponentCount() > 0) {
206 return null;
207 }
208
209 AbstractButton b = (AbstractButton) c;
210
211 String text = b.getText();
212
213 Icon buttonIcon = (Icon) b.getIcon();
214 if (buttonIcon == null) {
215 buttonIcon = getDefaultIcon();
216 }
217
218 Font font = b.getFont();
219 FontMetrics fm = b.getFontMetrics(font);
220
221 prefViewRect.x = prefViewRect.y = 0;
222 prefViewRect.width = Short.MAX_VALUE;
223 prefViewRect.height = Short.MAX_VALUE;
224 prefIconRect.x = prefIconRect.y = prefIconRect.width = prefIconRect.height = 0;
225 prefTextRect.x = prefTextRect.y = prefTextRect.width = prefTextRect.height = 0;
226
227 SwingUtilities.layoutCompoundLabel(c, fm, text, buttonIcon, b
228 .getVerticalAlignment(), b.getHorizontalAlignment(), b
229 .getVerticalTextPosition(), b
230 .getHorizontalTextPosition(), prefViewRect,
231 prefIconRect, prefTextRect, text == null ? 0 : b
232 .getIconTextGap());
233
234 // find the union of the icon and text rects (from Rectangle.java)
235 int x1 = Math.min(prefIconRect.x, prefTextRect.x);
236 int x2 = Math.max(prefIconRect.x + prefIconRect.width,
237 prefTextRect.x + prefTextRect.width);
238 int y1 = Math.min(prefIconRect.y, prefTextRect.y);
239 int y2 = Math.max(prefIconRect.y + prefIconRect.height,
240 prefTextRect.y + prefTextRect.height);
241 int width = x2 - x1;
242 int height = y2 - y1;
243
244 prefInsets = b.getInsets(prefInsets);
245 width += prefInsets.left + prefInsets.right;
246 height += prefInsets.top + prefInsets.bottom;
247 return new Dimension(width, height);
248 }
249 }
|