| /* |
| * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.apple.laf; |
| |
| import java.awt.*; |
| import java.beans.*; |
| |
| import javax.swing.*; |
| import javax.swing.border.Border; |
| import javax.swing.plaf.*; |
| |
| import apple.laf.*; |
| import apple.laf.JRSUIConstants.*; |
| |
| import com.apple.laf.AquaUtils.RecyclableSingleton; |
| import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor; |
| import sun.security.action.GetPropertyAction; |
| |
| import static java.security.AccessController.*; |
| |
| public class AquaUtilControlSize { |
| protected static final String CLIENT_PROPERTY_KEY = "JComponent.sizeVariant"; |
| protected static final String SYSTEM_PROPERTY_KEY = "swing.component.sizevariant"; |
| |
| interface Sizeable { |
| void applySizeFor(final JComponent c, final Size size); |
| } |
| |
| protected static final RecyclableSingleton<PropertySizeListener> sizeListener |
| = new RecyclableSingletonFromDefaultConstructor<>(PropertySizeListener.class); |
| protected static PropertySizeListener getSizeListener() { |
| return sizeListener.get(); |
| } |
| |
| protected static void addSizePropertyListener(final JComponent c) { |
| c.addPropertyChangeListener(CLIENT_PROPERTY_KEY, getSizeListener()); |
| PropertySizeListener.applyComponentSize(c, c.getClientProperty(CLIENT_PROPERTY_KEY)); |
| } |
| |
| protected static void removeSizePropertyListener(final JComponent c) { |
| c.removePropertyChangeListener(CLIENT_PROPERTY_KEY, getSizeListener()); |
| } |
| |
| private static JRSUIConstants.Size getSizeFromString(final String name) { |
| if ("regular".equalsIgnoreCase(name)) return Size.REGULAR; |
| if ("small".equalsIgnoreCase(name)) return Size.SMALL; |
| if ("mini".equalsIgnoreCase(name)) return Size.MINI; |
| if ("large".equalsIgnoreCase(name)) return Size.LARGE; |
| return null; |
| } |
| |
| private static Size getDefaultSize() { |
| final String sizeProperty = doPrivileged(new GetPropertyAction(SYSTEM_PROPERTY_KEY)); |
| final JRSUIConstants.Size size = getSizeFromString(sizeProperty); |
| if (size != null) return size; |
| return JRSUIConstants.Size.REGULAR; |
| } |
| |
| protected static final JRSUIConstants.Size defaultSize = getDefaultSize(); |
| protected static JRSUIConstants.Size getUserSizeFrom(final JComponent c) { |
| final Object sizeProp = c.getClientProperty(CLIENT_PROPERTY_KEY); |
| if (sizeProp == null) return defaultSize; |
| final Size size = getSizeFromString(sizeProp.toString()); |
| if (size == null) return Size.REGULAR; |
| return size; |
| } |
| |
| protected static JRSUIConstants.Size applySizeForControl(final JComponent c, |
| final AquaPainter<? extends JRSUIState> painter) { |
| final JRSUIConstants.Size sizeFromUser = getUserSizeFrom(c); |
| final JRSUIConstants.Size size = sizeFromUser == null |
| ? JRSUIConstants.Size.REGULAR |
| : sizeFromUser; |
| painter.state.set(size); |
| return size; |
| } |
| |
| protected static Font getFontForSize(final Component c, |
| final JRSUIConstants.Size size) { |
| final Font initialFont = c.getFont(); |
| |
| if (size == null || !(initialFont instanceof UIResource)) { |
| return initialFont; |
| } |
| |
| if (size == JRSUIConstants.Size.MINI) { |
| return initialFont.deriveFont( |
| AquaFonts.getMiniControlTextFont().getSize2D()); |
| } |
| if (size == JRSUIConstants.Size.SMALL) { |
| return initialFont.deriveFont( |
| AquaFonts.getSmallControlTextFont().getSize2D()); |
| } |
| |
| return initialFont.deriveFont(AquaFonts.getControlTextFont().getSize2D()); |
| } |
| |
| private static void applyBorderForSize(final JComponent c, final Size size) { |
| final Border border = c.getBorder(); |
| if (!(border instanceof AquaBorder)) return; |
| final AquaBorder aquaBorder = (AquaBorder)border; |
| |
| if (aquaBorder.sizeVariant.size == size) return; |
| final AquaBorder derivedBorder = aquaBorder.deriveBorderForSize(size); |
| if (derivedBorder == null) return; |
| |
| c.setBorder(derivedBorder); |
| } |
| |
| protected static class PropertySizeListener implements PropertyChangeListener { |
| @Override |
| public void propertyChange(final PropertyChangeEvent evt) { |
| final String key = evt.getPropertyName(); |
| if (!CLIENT_PROPERTY_KEY.equalsIgnoreCase(key)) return; |
| |
| final Object source = evt.getSource(); |
| if (!(source instanceof JComponent)) return; |
| |
| final JComponent c = (JComponent)source; |
| applyComponentSize(c, evt.getNewValue()); |
| } |
| |
| protected static void applyComponentSize(final JComponent c, final Object value) { |
| Size size = getSizeFromString(value == null ? null : value.toString()); |
| if (size == null) { |
| size = getUserSizeFrom(c); |
| if (size == Size.REGULAR) return; |
| } |
| |
| applyBorderForSize(c, size); |
| |
| final Object ui = c.getUI(); |
| if (ui instanceof Sizeable) { |
| ((Sizeable) ui).applySizeFor(c, size); |
| } |
| |
| final Font priorFont = c.getFont(); |
| if (!(priorFont instanceof FontUIResource)) return; |
| c.setFont(getFontForSize(c, size)); |
| } |
| } |
| |
| public static class SizeDescriptor { |
| SizeVariant regular; |
| SizeVariant small; |
| SizeVariant mini; |
| |
| public SizeDescriptor(final SizeVariant variant) { |
| regular = deriveRegular(variant); |
| small = deriveSmall(new SizeVariant(regular)); |
| mini = deriveMini(new SizeVariant(small)); |
| } |
| |
| public SizeVariant deriveRegular(final SizeVariant v) { |
| v.size = Size.REGULAR; |
| return v; |
| } |
| |
| public SizeVariant deriveSmall(final SizeVariant v) { |
| v.size = Size.SMALL; |
| return v; |
| } |
| |
| public SizeVariant deriveMini(final SizeVariant v) { |
| v.size = Size.MINI; |
| return v; |
| } |
| |
| public SizeVariant get(final JComponent c) { |
| if (c == null) return regular; |
| return get(getUserSizeFrom(c)); |
| } |
| |
| public SizeVariant get(final Size size) { |
| if (size == Size.REGULAR) return regular; |
| if (size == Size.SMALL) return small; |
| if (size == Size.MINI) return mini; |
| return regular; |
| } |
| |
| @Override |
| public String toString() { |
| return "regular[" + regular + "] small[" + small + "] mini[" + mini + "]"; |
| } |
| } |
| |
| public static class SizeVariant { |
| Size size = Size.REGULAR; |
| Insets insets = new InsetsUIResource(0, 0, 0, 0); |
| Insets margins = new InsetsUIResource(0, 0, 0, 0); |
| Float fontSize; |
| int w = 0; |
| int h = 0; |
| // Integer textBaseline; |
| |
| public SizeVariant() { } |
| |
| public SizeVariant(final int minWidth, final int minHeight) { |
| this.w = minWidth; |
| this.h = minHeight; |
| } |
| |
| public SizeVariant(final SizeVariant desc){ |
| this.size = desc.size; |
| this.insets = new InsetsUIResource(desc.insets.top, |
| desc.insets.left, |
| desc.insets.bottom, |
| desc.insets.right); |
| this.margins = new InsetsUIResource(desc.margins.top, |
| desc.margins.left, |
| desc.margins.bottom, |
| desc.margins.right); |
| this.fontSize = desc.fontSize; |
| this.w = desc.w; |
| this.h = desc.h; |
| // this.textBaseline = desc.textBaseline; |
| } |
| |
| public SizeVariant replaceInsets(final String insetName) { |
| this.insets = UIManager.getInsets(insetName); |
| return this; |
| } |
| |
| public SizeVariant replaceInsets(final Insets i) { |
| this.insets = new InsetsUIResource(i.top, i.left, i.bottom, i.right); |
| return this; |
| } |
| |
| public SizeVariant alterInsets(final int top, final int left, |
| final int bottom, final int right) { |
| insets = generateInsets(insets, top, left, bottom, right); |
| return this; |
| } |
| |
| public SizeVariant replaceMargins(final String marginName) { |
| this.margins = UIManager.getInsets(marginName); |
| return this; |
| } |
| |
| public SizeVariant alterMargins(final int top, final int left, |
| final int bottom, final int right) { |
| margins = generateInsets(margins, top, left, bottom, right); |
| return this; |
| } |
| |
| public SizeVariant alterFontSize(final float newSize) { |
| final float oldSize = fontSize == null ? 0.0f : fontSize.floatValue(); |
| fontSize = newSize + oldSize; |
| return this; |
| } |
| |
| public SizeVariant alterMinSize(final int width, final int height) { |
| this.w += width; this.h += height; |
| return this; |
| } |
| |
| // public SizeVariant alterTextBaseline(final int baseline) { |
| // final int oldSize = textBaseline == null ? 0 : textBaseline.intValue(); |
| // textBaseline = new Integer(baseline + oldSize); |
| // return this; |
| // } |
| |
| static Insets generateInsets(final Insets i, final int top, |
| final int left, final int bottom, |
| final int right) { |
| if (i == null) { |
| return new InsetsUIResource(top, left, bottom, right); |
| } |
| i.top += top; |
| i.left += left; |
| i.bottom += bottom; |
| i.right += right; |
| return i; |
| } |
| |
| @Override |
| public String toString() { |
| return "insets:" + insets + ", margins:" + margins + ", fontSize:" |
| + fontSize;// + ", textBaseline:" + textBaseline; |
| } |
| } |
| } |