1 /* 2 * Copyright (c) 1997, 2005, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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 import sun.awt.AppContext; 36 37 38 /** 39 * RadioButtonUI implementation for BasicRadioButtonUI 40 * 41 * @author Jeff Dinkins 42 */ 43 public class BasicRadioButtonUI extends BasicToggleButtonUI 44 { 45 private static final Object BASIC_RADIO_BUTTON_UI_KEY = new Object(); 46 47 protected Icon icon; 48 49 private boolean defaults_initialized = false; 50 51 private final static String propertyPrefix = "RadioButton" + "."; 52 53 // ******************************** 54 // Create PLAF 55 // ******************************** 56 public static ComponentUI createUI(JComponent b) { 57 AppContext appContext = AppContext.getAppContext(); 58 BasicRadioButtonUI radioButtonUI = 59 (BasicRadioButtonUI) appContext.get(BASIC_RADIO_BUTTON_UI_KEY); 60 if (radioButtonUI == null) { 61 radioButtonUI = new BasicRadioButtonUI(); 62 appContext.put(BASIC_RADIO_BUTTON_UI_KEY, radioButtonUI); 63 } 64 return radioButtonUI; 65 } 66 67 protected String getPropertyPrefix() { 68 return propertyPrefix; 69 } 70 71 // ******************************** 72 // Install PLAF 73 // ******************************** 74 protected void installDefaults(AbstractButton b){ 75 super.installDefaults(b); 76 if(!defaults_initialized) { 77 icon = UIManager.getIcon(getPropertyPrefix() + "icon"); 78 defaults_initialized = true; 79 } 80 } 81 82 // ******************************** 83 // Uninstall PLAF 84 // ******************************** 85 protected void uninstallDefaults(AbstractButton b){ 86 super.uninstallDefaults(b); 87 defaults_initialized = false; 88 } 89 90 public Icon getDefaultIcon() { 91 return icon; 92 } 93 94 95 /* These Dimensions/Rectangles are allocated once for all 96 * RadioButtonUI.paint() calls. Re-using rectangles 97 * rather than allocating them in each paint call substantially 98 * reduced the time it took paint to run. Obviously, this 99 * method can't be re-entered. 100 */ 101 private static Dimension size = new Dimension(); 102 private static Rectangle viewRect = new Rectangle(); 103 private static Rectangle iconRect = new Rectangle(); 104 private static Rectangle textRect = new Rectangle(); 105 106 /** 107 * paint the radio button 108 */ 109 public synchronized void paint(Graphics g, JComponent c) { 110 AbstractButton b = (AbstractButton) c; 111 ButtonModel model = b.getModel(); 112 113 Font f = c.getFont(); 114 g.setFont(f); 115 FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f); 116 117 Insets i = c.getInsets(); 118 size = b.getSize(size); 119 viewRect.x = i.left; 120 viewRect.y = i.top; 121 viewRect.width = size.width - (i.right + viewRect.x); 122 viewRect.height = size.height - (i.bottom + viewRect.y); 123 iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0; 124 textRect.x = textRect.y = textRect.width = textRect.height = 0; 125 126 Icon altIcon = b.getIcon(); 127 Icon selectedIcon = null; 128 Icon disabledIcon = null; 129 130 String text = SwingUtilities.layoutCompoundLabel( 131 c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(), 132 b.getVerticalAlignment(), b.getHorizontalAlignment(), 133 b.getVerticalTextPosition(), b.getHorizontalTextPosition(), 134 viewRect, iconRect, textRect, 135 b.getText() == null ? 0 : b.getIconTextGap()); 136 137 // fill background 138 if(c.isOpaque()) { 139 g.setColor(b.getBackground()); 140 g.fillRect(0,0, size.width, size.height); 141 } 142 143 144 // Paint the radio button 145 if(altIcon != null) { 146 147 if(!model.isEnabled()) { 148 if(model.isSelected()) { 149 altIcon = b.getDisabledSelectedIcon(); 150 } else { 151 altIcon = b.getDisabledIcon(); 152 } 153 } else if(model.isPressed() && model.isArmed()) { 154 altIcon = b.getPressedIcon(); 155 if(altIcon == null) { 156 // Use selected icon 157 altIcon = b.getSelectedIcon(); 158 } 159 } else if(model.isSelected()) { 160 if(b.isRolloverEnabled() && model.isRollover()) { 161 altIcon = (Icon) b.getRolloverSelectedIcon(); 162 if (altIcon == null) { 163 altIcon = (Icon) b.getSelectedIcon(); 164 } 165 } else { 166 altIcon = (Icon) b.getSelectedIcon(); 167 } 168 } else if(b.isRolloverEnabled() && model.isRollover()) { 169 altIcon = (Icon) b.getRolloverIcon(); 170 } 171 172 if(altIcon == null) { 173 altIcon = b.getIcon(); 174 } 175 176 altIcon.paintIcon(c, g, iconRect.x, iconRect.y); 177 178 } else { 179 getDefaultIcon().paintIcon(c, g, iconRect.x, iconRect.y); 180 } 181 182 183 // Draw the Text 184 if(text != null) { 185 View v = (View) c.getClientProperty(BasicHTML.propertyKey); 186 if (v != null) { 187 v.paint(g, textRect); 188 } else { 189 paintText(g, b, textRect, text); 190 } 191 if(b.hasFocus() && b.isFocusPainted() && 192 textRect.width > 0 && textRect.height > 0 ) { 193 paintFocus(g, textRect, size); 194 } 195 } 196 } 197 198 protected void paintFocus(Graphics g, Rectangle textRect, Dimension size){ 199 } 200 201 202 /* These Insets/Rectangles are allocated once for all 203 * RadioButtonUI.getPreferredSize() calls. Re-using rectangles 204 * rather than allocating them in each call substantially 205 * reduced the time it took getPreferredSize() to run. Obviously, 206 * this method can't be re-entered. 207 */ 208 private static Rectangle prefViewRect = new Rectangle(); 209 private static Rectangle prefIconRect = new Rectangle(); 210 private static Rectangle prefTextRect = new Rectangle(); 211 private static Insets prefInsets = new Insets(0, 0, 0, 0); 212 213 /** 214 * The preferred size of the radio button 215 */ 216 public Dimension getPreferredSize(JComponent c) { 217 if(c.getComponentCount() > 0) { 218 return null; 219 } 220 221 AbstractButton b = (AbstractButton) c; 222 223 String text = b.getText(); 224 225 Icon buttonIcon = (Icon) b.getIcon(); 226 if(buttonIcon == null) { 227 buttonIcon = getDefaultIcon(); 228 } 229 230 Font font = b.getFont(); 231 FontMetrics fm = b.getFontMetrics(font); 232 233 prefViewRect.x = prefViewRect.y = 0; 234 prefViewRect.width = Short.MAX_VALUE; 235 prefViewRect.height = Short.MAX_VALUE; 236 prefIconRect.x = prefIconRect.y = prefIconRect.width = prefIconRect.height = 0; 237 prefTextRect.x = prefTextRect.y = prefTextRect.width = prefTextRect.height = 0; 238 239 SwingUtilities.layoutCompoundLabel( 240 c, fm, text, buttonIcon, 241 b.getVerticalAlignment(), b.getHorizontalAlignment(), 242 b.getVerticalTextPosition(), b.getHorizontalTextPosition(), 243 prefViewRect, prefIconRect, prefTextRect, 244 text == null ? 0 : b.getIconTextGap()); 245 246 // find the union of the icon and text rects (from Rectangle.java) 247 int x1 = Math.min(prefIconRect.x, prefTextRect.x); 248 int x2 = Math.max(prefIconRect.x + prefIconRect.width, 249 prefTextRect.x + prefTextRect.width); 250 int y1 = Math.min(prefIconRect.y, prefTextRect.y); 251 int y2 = Math.max(prefIconRect.y + prefIconRect.height, 252 prefTextRect.y + prefTextRect.height); 253 int width = x2 - x1; 254 int height = y2 - y1; 255 256 prefInsets = b.getInsets(prefInsets); 257 width += prefInsets.left + prefInsets.right; 258 height += prefInsets.top + prefInsets.bottom; 259 return new Dimension(width, height); 260 } 261 }