();
populateDefaultValues();
}
Object value = DEFAULT_VALUES.get(key);
if (value instanceof UIDefaults.LazyValue) {
value = ((UIDefaults.LazyValue)value).createValue(null);
DEFAULT_VALUES.put(key, value);
}
return value;
}
}
/**
* Constructs a SynthStyle.
*/
public SynthStyle() {
}
/**
* Returns the SynthGraphicUtils
for the specified context.
*
* @param context SynthContext identifying requester
* @return SynthGraphicsUtils
*/
public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
return SYNTH_GRAPHICS;
}
/**
* Returns the color for the specified state. This gives precedence to
* foreground and background of the JComponent
. If the
* Color
from the JComponent
is not appropriate,
* or not used, this will invoke getColorForState
. Subclasses
* should generally not have to override this, instead override
* {@link #getColorForState}.
*
* @param context SynthContext identifying requester
* @param type Type of color being requested.
* @return Color
*/
public Color getColor(SynthContext context, ColorType type) {
JComponent c = context.getComponent();
Region id = context.getRegion();
if ((context.getComponentState() & SynthConstants.DISABLED) != 0) {
//This component is disabled, so return the disabled color.
//In some cases this means ignoring the color specified by the
//developer on the component. In other cases it means using a
//specified disabledTextColor, such as on JTextComponents.
//For example, JLabel doesn't specify a disabled color that the
//developer can set, yet it should have a disabled color to the
//text when the label is disabled. This code allows for that.
if (c instanceof JTextComponent) {
JTextComponent txt = (JTextComponent)c;
Color disabledColor = txt.getDisabledTextColor();
if (disabledColor == null || disabledColor instanceof UIResource) {
return getColorForState(context, type);
}
} else if (c instanceof JLabel &&
(type == ColorType.FOREGROUND ||
type == ColorType.TEXT_FOREGROUND)) {
return getColorForState(context, type);
}
}
// If the developer has specified a color, prefer it. Otherwise, get
// the color for the state.
Color color = null;
if (!id.isSubregion()) {
if (type == ColorType.BACKGROUND) {
color = c.getBackground();
}
else if (type == ColorType.FOREGROUND) {
color = c.getForeground();
}
else if (type == ColorType.TEXT_FOREGROUND) {
color = c.getForeground();
}
}
if (color == null || color instanceof UIResource) {
// Then use what we've locally defined
color = getColorForState(context, type);
}
if (color == null) {
// No color, fallback to that of the widget.
if (type == ColorType.BACKGROUND ||
type == ColorType.TEXT_BACKGROUND) {
return c.getBackground();
}
else if (type == ColorType.FOREGROUND ||
type == ColorType.TEXT_FOREGROUND) {
return c.getForeground();
}
}
return color;
}
/**
* Returns the color for the specified state. This should NOT call any
* methods on the JComponent
.
*
* @param context SynthContext identifying requester
* @param type Type of color being requested.
* @return Color to render with
*/
protected abstract Color getColorForState(SynthContext context,
ColorType type);
/**
* Returns the Font for the specified state. This redirects to the
* JComponent
from the context
as necessary.
* If this does not redirect
* to the JComponent {@link #getFontForState} is invoked.
*
* @param context SynthContext identifying requester
* @return Font to render with
*/
public Font getFont(SynthContext context) {
JComponent c = context.getComponent();
if (context.getComponentState() == SynthConstants.ENABLED) {
return c.getFont();
}
Font cFont = c.getFont();
if (cFont != null && !(cFont instanceof UIResource)) {
return cFont;
}
return getFontForState(context);
}
/**
* Returns the font for the specified state. This should NOT call any
* method on the JComponent
.
*
* @param context SynthContext identifying requester
* @return Font to render with
*/
protected abstract Font getFontForState(SynthContext context);
/**
* Returns the Insets that are used to calculate sizing information.
*
* @param context SynthContext identifying requester
* @param insets Insets to place return value in.
* @return Sizing Insets.
*/
public Insets getInsets(SynthContext context, Insets insets) {
if (insets == null) {
insets = new Insets(0, 0, 0, 0);
}
insets.top = insets.bottom = insets.left = insets.right = 0;
return insets;
}
/**
* Returns the SynthPainter
that will be used for painting.
* This may return null.
*
* @param context SynthContext identifying requester
* @return SynthPainter to use
*/
public SynthPainter getPainter(SynthContext context) {
return null;
}
/**
* Returns true if the region is opaque.
*
* @param context SynthContext identifying requester
* @return true if region is opaque.
*/
public boolean isOpaque(SynthContext context) {
return true;
}
/**
* Getter for a region specific style property.
*
* @param context SynthContext identifying requester
* @param key Property being requested.
* @return Value of the named property
*/
public Object get(SynthContext context, Object key) {
return getDefaultValue(key);
}
void installDefaults(SynthContext context, SynthUI ui) {
// Special case the Border as this will likely change when the LAF
// can have more control over this.
if (!context.isSubregion()) {
JComponent c = context.getComponent();
Border border = c.getBorder();
if (border == null || border instanceof UIResource) {
c.setBorder(new SynthBorder(ui, getInsets(context, null)));
}
}
installDefaults(context);
}
/**
* Installs the necessary state from this Style on the
* JComponent
from context
.
*
* @param context SynthContext identifying component to install properties
* to.
*/
public void installDefaults(SynthContext context) {
if (!context.isSubregion()) {
JComponent c = context.getComponent();
Region region = context.getRegion();
Font font = c.getFont();
if (font == null || (font instanceof UIResource)) {
c.setFont(getFontForState(context));
}
Color background = c.getBackground();
if (background == null || (background instanceof UIResource)) {
c.setBackground(getColorForState(context,
ColorType.BACKGROUND));
}
Color foreground = c.getForeground();
if (foreground == null || (foreground instanceof UIResource)) {
c.setForeground(getColorForState(context,
ColorType.FOREGROUND));
}
LookAndFeel.installProperty(c, "opaque", Boolean.valueOf(isOpaque(context)));
}
}
/**
* Uninstalls any state that this style installed on
* the JComponent
from context
.
*
* Styles should NOT depend upon this being called, in certain cases
* it may never be called.
*
* @param context SynthContext identifying component to install properties
* to.
*/
public void uninstallDefaults(SynthContext context) {
if (!context.isSubregion()) {
// NOTE: because getForeground, getBackground and getFont will look
// at the parent Container, if we set them to null it may
// mean we they return a non-null and non-UIResource value
// preventing install from correctly settings its colors/font. For
// this reason we do not uninstall the fg/bg/font.
JComponent c = context.getComponent();
Border border = c.getBorder();
if (border instanceof UIResource) {
c.setBorder(null);
}
}
}
/**
* Convenience method to get a specific style property whose value is
* a Number
. If the value is a Number
,
* intValue
is returned, otherwise defaultValue
* is returned.
*
* @param context SynthContext identifying requester
* @param key Property being requested.
* @param defaultValue Value to return if the property has not been
* specified, or is not a Number
* @return Value of the named property
*/
public int getInt(SynthContext context, Object key, int defaultValue) {
Object value = get(context, key);
if (value instanceof Number) {
return ((Number)value).intValue();
}
return defaultValue;
}
/**
* Convenience method to get a specific style property whose value is
* an Boolean.
*
* @param context SynthContext identifying requester
* @param key Property being requested.
* @param defaultValue Value to return if the property has not been
* specified, or is not a Boolean
* @return Value of the named property
*/
public boolean getBoolean(SynthContext context, Object key,
boolean defaultValue) {
Object value = get(context, key);
if (value instanceof Boolean) {
return ((Boolean)value).booleanValue();
}
return defaultValue;
}
/**
* Convenience method to get a specific style property whose value is
* an Icon.
*
* @param context SynthContext identifying requester
* @param key Property being requested.
* @return Value of the named property, or null if not specified
*/
public Icon getIcon(SynthContext context, Object key) {
Object value = get(context, key);
if (value instanceof Icon) {
return (Icon)value;
}
return null;
}
/**
* Convenience method to get a specific style property whose value is
* a String.
*
* @param context SynthContext identifying requester
* @param key Property being requested.
* @param defaultValue Value to return if the property has not been
* specified, or is not a String
* @return Value of the named property
*/
public String getString(SynthContext context, Object key,
String defaultValue) {
Object value = get(context, key);
if (value instanceof String) {
return (String)value;
}
return defaultValue;
}
}