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