1 /* 2 * Copyright (c) 2011, 2015, 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 com.apple.laf; 27 28 import java.awt.*; 29 import java.beans.*; 30 31 import javax.swing.*; 32 import javax.swing.border.Border; 33 import javax.swing.plaf.*; 34 35 import apple.laf.*; 36 import apple.laf.JRSUIConstants.*; 37 38 import com.apple.laf.AquaUtils.RecyclableSingleton; 39 import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; 40 import sun.security.action.GetPropertyAction; 41 42 import static java.security.AccessController.*; 43 44 public class AquaUtilControlSize { 45 protected static final String CLIENT_PROPERTY_KEY = "JComponent.sizeVariant"; 46 protected static final String SYSTEM_PROPERTY_KEY = "swing.component.sizevariant"; 47 48 interface Sizeable { applySizeFor(final JComponent c, final Size size)49 void applySizeFor(final JComponent c, final Size size); 50 } 51 52 private static final RecyclableSingleton<PropertySizeListener> sizeListener 53 = new RecyclableSingletonFromDefaultConstructor<>(PropertySizeListener.class); getSizeListener()54 protected static PropertySizeListener getSizeListener() { 55 return sizeListener.get(); 56 } 57 addSizePropertyListener(final JComponent c)58 protected static void addSizePropertyListener(final JComponent c) { 59 c.addPropertyChangeListener(CLIENT_PROPERTY_KEY, getSizeListener()); 60 PropertySizeListener.applyComponentSize(c, c.getClientProperty(CLIENT_PROPERTY_KEY)); 61 } 62 removeSizePropertyListener(final JComponent c)63 protected static void removeSizePropertyListener(final JComponent c) { 64 c.removePropertyChangeListener(CLIENT_PROPERTY_KEY, getSizeListener()); 65 } 66 getSizeFromString(final String name)67 private static JRSUIConstants.Size getSizeFromString(final String name) { 68 if ("regular".equalsIgnoreCase(name)) return Size.REGULAR; 69 if ("small".equalsIgnoreCase(name)) return Size.SMALL; 70 if ("mini".equalsIgnoreCase(name)) return Size.MINI; 71 if ("large".equalsIgnoreCase(name)) return Size.LARGE; 72 return null; 73 } 74 getDefaultSize()75 private static Size getDefaultSize() { 76 final String sizeProperty = doPrivileged(new GetPropertyAction(SYSTEM_PROPERTY_KEY)); 77 final JRSUIConstants.Size size = getSizeFromString(sizeProperty); 78 if (size != null) return size; 79 return JRSUIConstants.Size.REGULAR; 80 } 81 82 protected static final JRSUIConstants.Size defaultSize = getDefaultSize(); getUserSizeFrom(final JComponent c)83 protected static JRSUIConstants.Size getUserSizeFrom(final JComponent c) { 84 final Object sizeProp = c.getClientProperty(CLIENT_PROPERTY_KEY); 85 if (sizeProp == null) return defaultSize; 86 final Size size = getSizeFromString(sizeProp.toString()); 87 if (size == null) return Size.REGULAR; 88 return size; 89 } 90 applySizeForControl(final JComponent c, final AquaPainter<? extends JRSUIState> painter)91 protected static JRSUIConstants.Size applySizeForControl(final JComponent c, 92 final AquaPainter<? extends JRSUIState> painter) { 93 final JRSUIConstants.Size sizeFromUser = getUserSizeFrom(c); 94 final JRSUIConstants.Size size = sizeFromUser == null 95 ? JRSUIConstants.Size.REGULAR 96 : sizeFromUser; 97 painter.state.set(size); 98 return size; 99 } 100 getFontForSize(final Component c, final JRSUIConstants.Size size)101 protected static Font getFontForSize(final Component c, 102 final JRSUIConstants.Size size) { 103 final Font initialFont = c.getFont(); 104 105 if (size == null || !(initialFont instanceof UIResource)) { 106 return initialFont; 107 } 108 109 if (size == JRSUIConstants.Size.MINI) { 110 return initialFont.deriveFont( 111 AquaFonts.getMiniControlTextFont().getSize2D()); 112 } 113 if (size == JRSUIConstants.Size.SMALL) { 114 return initialFont.deriveFont( 115 AquaFonts.getSmallControlTextFont().getSize2D()); 116 } 117 118 return initialFont.deriveFont(AquaFonts.getControlTextFont().getSize2D()); 119 } 120 applyBorderForSize(final JComponent c, final Size size)121 private static void applyBorderForSize(final JComponent c, final Size size) { 122 final Border border = c.getBorder(); 123 if (!(border instanceof AquaBorder)) return; 124 final AquaBorder aquaBorder = (AquaBorder)border; 125 126 if (aquaBorder.sizeVariant.size == size) return; 127 final AquaBorder derivedBorder = aquaBorder.deriveBorderForSize(size); 128 if (derivedBorder == null) return; 129 130 c.setBorder(derivedBorder); 131 } 132 133 protected static class PropertySizeListener implements PropertyChangeListener { 134 @Override propertyChange(final PropertyChangeEvent evt)135 public void propertyChange(final PropertyChangeEvent evt) { 136 final String key = evt.getPropertyName(); 137 if (!CLIENT_PROPERTY_KEY.equalsIgnoreCase(key)) return; 138 139 final Object source = evt.getSource(); 140 if (!(source instanceof JComponent)) return; 141 142 final JComponent c = (JComponent)source; 143 applyComponentSize(c, evt.getNewValue()); 144 } 145 applyComponentSize(final JComponent c, final Object value)146 protected static void applyComponentSize(final JComponent c, final Object value) { 147 Size size = getSizeFromString(value == null ? null : value.toString()); 148 if (size == null) { 149 size = getUserSizeFrom(c); 150 if (size == Size.REGULAR) return; 151 } 152 153 applyBorderForSize(c, size); 154 155 final Object ui = c.getUI(); 156 if (ui instanceof Sizeable) { 157 ((Sizeable) ui).applySizeFor(c, size); 158 } 159 160 final Font priorFont = c.getFont(); 161 if (!(priorFont instanceof FontUIResource)) return; 162 c.setFont(getFontForSize(c, size)); 163 } 164 } 165 166 public static class SizeDescriptor { 167 SizeVariant regular; 168 SizeVariant small; 169 SizeVariant mini; 170 SizeDescriptor(final SizeVariant variant)171 public SizeDescriptor(final SizeVariant variant) { 172 regular = deriveRegular(variant); 173 small = deriveSmall(new SizeVariant(regular)); 174 mini = deriveMini(new SizeVariant(small)); 175 } 176 deriveRegular(final SizeVariant v)177 public SizeVariant deriveRegular(final SizeVariant v) { 178 v.size = Size.REGULAR; 179 return v; 180 } 181 deriveSmall(final SizeVariant v)182 public SizeVariant deriveSmall(final SizeVariant v) { 183 v.size = Size.SMALL; 184 return v; 185 } 186 deriveMini(final SizeVariant v)187 public SizeVariant deriveMini(final SizeVariant v) { 188 v.size = Size.MINI; 189 return v; 190 } 191 get(final JComponent c)192 public SizeVariant get(final JComponent c) { 193 if (c == null) return regular; 194 return get(getUserSizeFrom(c)); 195 } 196 get(final Size size)197 public SizeVariant get(final Size size) { 198 if (size == Size.REGULAR) return regular; 199 if (size == Size.SMALL) return small; 200 if (size == Size.MINI) return mini; 201 return regular; 202 } 203 204 @Override toString()205 public String toString() { 206 return "regular[" + regular + "] small[" + small + "] mini[" + mini + "]"; 207 } 208 } 209 210 public static class SizeVariant { 211 Size size = Size.REGULAR; 212 Insets insets = new InsetsUIResource(0, 0, 0, 0); 213 Insets margins = new InsetsUIResource(0, 0, 0, 0); 214 Float fontSize; 215 int w = 0; 216 int h = 0; 217 // Integer textBaseline; 218 SizeVariant()219 public SizeVariant() { } 220 SizeVariant(final int minWidth, final int minHeight)221 public SizeVariant(final int minWidth, final int minHeight) { 222 this.w = minWidth; 223 this.h = minHeight; 224 } 225 SizeVariant(final SizeVariant desc)226 public SizeVariant(final SizeVariant desc){ 227 this.size = desc.size; 228 this.insets = new InsetsUIResource(desc.insets.top, 229 desc.insets.left, 230 desc.insets.bottom, 231 desc.insets.right); 232 this.margins = new InsetsUIResource(desc.margins.top, 233 desc.margins.left, 234 desc.margins.bottom, 235 desc.margins.right); 236 this.fontSize = desc.fontSize; 237 this.w = desc.w; 238 this.h = desc.h; 239 // this.textBaseline = desc.textBaseline; 240 } 241 replaceInsets(final String insetName)242 public SizeVariant replaceInsets(final String insetName) { 243 this.insets = UIManager.getInsets(insetName); 244 return this; 245 } 246 replaceInsets(final Insets i)247 public SizeVariant replaceInsets(final Insets i) { 248 this.insets = new InsetsUIResource(i.top, i.left, i.bottom, i.right); 249 return this; 250 } 251 alterInsets(final int top, final int left, final int bottom, final int right)252 public SizeVariant alterInsets(final int top, final int left, 253 final int bottom, final int right) { 254 insets = generateInsets(insets, top, left, bottom, right); 255 return this; 256 } 257 replaceMargins(final String marginName)258 public SizeVariant replaceMargins(final String marginName) { 259 this.margins = UIManager.getInsets(marginName); 260 return this; 261 } 262 alterMargins(final int top, final int left, final int bottom, final int right)263 public SizeVariant alterMargins(final int top, final int left, 264 final int bottom, final int right) { 265 margins = generateInsets(margins, top, left, bottom, right); 266 return this; 267 } 268 alterFontSize(final float newSize)269 public SizeVariant alterFontSize(final float newSize) { 270 final float oldSize = fontSize == null ? 0.0f : fontSize.floatValue(); 271 fontSize = newSize + oldSize; 272 return this; 273 } 274 alterMinSize(final int width, final int height)275 public SizeVariant alterMinSize(final int width, final int height) { 276 this.w += width; this.h += height; 277 return this; 278 } 279 280 // public SizeVariant alterTextBaseline(final int baseline) { 281 // final int oldSize = textBaseline == null ? 0 : textBaseline.intValue(); 282 // textBaseline = new Integer(baseline + oldSize); 283 // return this; 284 // } 285 generateInsets(final Insets i, final int top, final int left, final int bottom, final int right)286 static Insets generateInsets(final Insets i, final int top, 287 final int left, final int bottom, 288 final int right) { 289 if (i == null) { 290 return new InsetsUIResource(top, left, bottom, right); 291 } 292 i.top += top; 293 i.left += left; 294 i.bottom += bottom; 295 i.right += right; 296 return i; 297 } 298 299 @Override toString()300 public String toString() { 301 return "insets:" + insets + ", margins:" + margins + ", fontSize:" 302 + fontSize;// + ", textBaseline:" + textBaseline; 303 } 304 } 305 } 306