package com.apple.laf;
import java.awt.*;
import java.beans.*;
import java.lang.reflect.Method;
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;
public class AquaUtilControlSize {
protected final static String CLIENT_PROPERTY_KEY = "JComponent.sizeVariant";
protected final static 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>(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 = java.security.AccessController.doPrivileged(new sun.security.action.GetPropertyAction(SYSTEM_PROPERTY_KEY));
final JRSUIConstants.Size size = getSizeFromString(sizeProperty);
if (size != null) return size;
return JRSUIConstants.Size.REGULAR;
}
protected final static 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);
}
private static void applyUISizing(final JComponent c, final Size size) {
try {
final Class<? extends JComponent> clazz = c.getClass();
final Method getUIMethod = clazz.getMethod("getUI", new Class[0]);
final Object ui = getUIMethod.invoke(c, new Object[0]);
if (!(ui instanceof Sizeable)) return;
final Sizeable sizeable = (Sizeable)ui;
sizeable.applySizeFor(c, size);
} catch (final Throwable e) { return; }
}
protected static class PropertySizeListener implements PropertyChangeListener {
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);
applyUISizing(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;
}
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;
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;
}
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 = new Float(newSize + oldSize);
return this;
}
public SizeVariant alterMinSize(final int width, final int height) {
this.w += width; this.h += height;
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;
}
public String toString() {
return "insets:" + insets + ", margins:" + margins + ", fontSize:" + fontSize;
}
}
}