< prev index next >

src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java

Print this page




  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 package javax.swing.plaf.synth;
  26 
  27 import java.awt.*;
  28 import javax.swing.*;
  29 import javax.swing.border.Border;
  30 import javax.swing.plaf.UIResource;
  31 import javax.swing.plaf.basic.BasicLookAndFeel;
  32 import javax.swing.text.DefaultEditorKit;
  33 import java.util.HashMap;
  34 import java.util.Map;
  35 import javax.swing.text.JTextComponent;
  36 import sun.swing.SwingUtilities2;
  37 
  38 /**
  39  * <code>SynthStyle</code> is a set of style properties.
  40  * Each <code>SynthUI</code> references at least one
  41  * <code>SynthStyle</code> that is obtained using a
  42  * <code>SynthStyleFactory</code>. You typically don't need to interact with
  43  * this class directly, rather you will load a
  44  * <a href="doc-files/synthFileFormat.html">Synth File Format file</a> into
  45  * <code>SynthLookAndFeel</code> that will create a set of SynthStyles.
  46  *
  47  * @see SynthLookAndFeel
  48  * @see SynthStyleFactory
  49  *
  50  * @since 1.5
  51  * @author Scott Violet
  52  */
  53 public abstract class SynthStyle {
  54     /**
  55      * Contains the default values for certain properties.
  56      */
  57     private static Map<Object, Object> DEFAULT_VALUES;
  58 
  59     /**
  60      * Shared SynthGraphics.
  61      */
  62     private static final SynthGraphicsUtils SYNTH_GRAPHICS =
  63                               new SynthGraphicsUtils();
  64 
  65     /**


 719             if (DEFAULT_VALUES == null) {
 720                 DEFAULT_VALUES = new HashMap<Object, Object>();
 721                 populateDefaultValues();
 722             }
 723             Object value = DEFAULT_VALUES.get(key);
 724             if (value instanceof UIDefaults.LazyValue) {
 725                 value = ((UIDefaults.LazyValue)value).createValue(null);
 726                 DEFAULT_VALUES.put(key, value);
 727             }
 728             return value;
 729         }
 730     }
 731 
 732     /**
 733      * Constructs a SynthStyle.
 734      */
 735     public SynthStyle() {
 736     }
 737 
 738     /**
 739      * Returns the <code>SynthGraphicUtils</code> for the specified context.
 740      *
 741      * @param context SynthContext identifying requester
 742      * @return SynthGraphicsUtils
 743      */
 744     public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
 745         return SYNTH_GRAPHICS;
 746     }
 747 
 748     /**
 749      * Returns the color for the specified state. This gives precedence to
 750      * foreground and background of the <code>JComponent</code>. If the
 751      * <code>Color</code> from the <code>JComponent</code> is not appropriate,
 752      * or not used, this will invoke <code>getColorForState</code>. Subclasses
 753      * should generally not have to override this, instead override
 754      * {@link #getColorForState}.
 755      *
 756      * @param context SynthContext identifying requester
 757      * @param type Type of color being requested.
 758      * @return Color
 759      */
 760     public Color getColor(SynthContext context, ColorType type) {
 761         JComponent c = context.getComponent();
 762         Region id = context.getRegion();
 763 
 764         if ((context.getComponentState() & SynthConstants.DISABLED) != 0) {
 765             //This component is disabled, so return the disabled color.
 766             //In some cases this means ignoring the color specified by the
 767             //developer on the component. In other cases it means using a
 768             //specified disabledTextColor, such as on JTextComponents.
 769             //For example, JLabel doesn't specify a disabled color that the
 770             //developer can set, yet it should have a disabled color to the
 771             //text when the label is disabled. This code allows for that.
 772             if (c instanceof JTextComponent) {


 801             // Then use what we've locally defined
 802             color = getColorForState(context, type);
 803         }
 804 
 805         if (color == null) {
 806             // No color, fallback to that of the widget.
 807             if (type == ColorType.BACKGROUND ||
 808                         type == ColorType.TEXT_BACKGROUND) {
 809                 return c.getBackground();
 810             }
 811             else if (type == ColorType.FOREGROUND ||
 812                      type == ColorType.TEXT_FOREGROUND) {
 813                 return c.getForeground();
 814             }
 815         }
 816         return color;
 817     }
 818 
 819     /**
 820      * Returns the color for the specified state. This should NOT call any
 821      * methods on the <code>JComponent</code>.
 822      *
 823      * @param context SynthContext identifying requester
 824      * @param type Type of color being requested.
 825      * @return Color to render with
 826      */
 827     protected abstract Color getColorForState(SynthContext context,
 828                                               ColorType type);
 829 
 830     /**
 831      * Returns the Font for the specified state. This redirects to the
 832      * <code>JComponent</code> from the <code>context</code> as necessary.
 833      * If this does not redirect
 834      * to the JComponent {@link #getFontForState} is invoked.
 835      *
 836      * @param context SynthContext identifying requester
 837      * @return Font to render with
 838      */
 839     public Font getFont(SynthContext context) {
 840         JComponent c = context.getComponent();
 841         if (context.getComponentState() == SynthConstants.ENABLED) {
 842             return c.getFont();
 843         }
 844         Font cFont = c.getFont();
 845         if (cFont != null && !(cFont instanceof UIResource)) {
 846             return cFont;
 847         }
 848         return getFontForState(context);
 849     }
 850 
 851     /**
 852      * Returns the font for the specified state. This should NOT call any
 853      * method on the <code>JComponent</code>.
 854      *
 855      * @param context SynthContext identifying requester
 856      * @return Font to render with
 857      */
 858     protected abstract Font getFontForState(SynthContext context);
 859 
 860     /**
 861      * Returns the Insets that are used to calculate sizing information.
 862      *
 863      * @param context SynthContext identifying requester
 864      * @param insets Insets to place return value in.
 865      * @return Sizing Insets.
 866      */
 867     public Insets getInsets(SynthContext context, Insets insets) {
 868         if (insets == null) {
 869             insets = new Insets(0, 0, 0, 0);
 870         }
 871         insets.top = insets.bottom = insets.left = insets.right = 0;
 872         return insets;
 873     }
 874 
 875     /**
 876      * Returns the <code>SynthPainter</code> that will be used for painting.
 877      * This may return null.
 878      *
 879      * @param context SynthContext identifying requester
 880      * @return SynthPainter to use
 881      */
 882     public SynthPainter getPainter(SynthContext context) {
 883         return null;
 884     }
 885 
 886     /**
 887      * Returns true if the region is opaque.
 888      *
 889      * @param context SynthContext identifying requester
 890      * @return true if region is opaque.
 891      */
 892     public boolean isOpaque(SynthContext context) {
 893         return true;
 894     }
 895 
 896     /**


 903     public Object get(SynthContext context, Object key) {
 904         return getDefaultValue(key);
 905     }
 906 
 907     void installDefaults(SynthContext context, SynthUI ui) {
 908         // Special case the Border as this will likely change when the LAF
 909         // can have more control over this.
 910         if (!context.isSubregion()) {
 911             JComponent c = context.getComponent();
 912             Border border = c.getBorder();
 913 
 914             if (border == null || border instanceof UIResource) {
 915                 c.setBorder(new SynthBorder(ui, getInsets(context, null)));
 916             }
 917         }
 918         installDefaults(context);
 919     }
 920 
 921     /**
 922      * Installs the necessary state from this Style on the
 923      * <code>JComponent</code> from <code>context</code>.
 924      *
 925      * @param context SynthContext identifying component to install properties
 926      *        to.
 927      */
 928     public void installDefaults(SynthContext context) {
 929         if (!context.isSubregion()) {
 930             JComponent c = context.getComponent();
 931             Region region = context.getRegion();
 932             Font font = c.getFont();
 933 
 934             if (font == null || (font instanceof UIResource)) {
 935                 c.setFont(getFontForState(context));
 936             }
 937             Color background = c.getBackground();
 938             if (background == null || (background instanceof UIResource)) {
 939                 c.setBackground(getColorForState(context,
 940                                                  ColorType.BACKGROUND));
 941             }
 942             Color foreground = c.getForeground();
 943             if (foreground == null || (foreground instanceof UIResource)) {
 944                 c.setForeground(getColorForState(context,
 945                          ColorType.FOREGROUND));
 946             }
 947             LookAndFeel.installProperty(c, "opaque", Boolean.valueOf(isOpaque(context)));
 948         }
 949     }
 950 
 951     /**
 952      * Uninstalls any state that this style installed on
 953      * the <code>JComponent</code> from <code>context</code>.
 954      * <p>
 955      * Styles should NOT depend upon this being called, in certain cases
 956      * it may never be called.
 957      *
 958      * @param context SynthContext identifying component to install properties
 959      *        to.
 960      */
 961     public void uninstallDefaults(SynthContext context) {
 962         if (!context.isSubregion()) {
 963             // NOTE: because getForeground, getBackground and getFont will look
 964             // at the parent Container, if we set them to null it may
 965             // mean we they return a non-null and non-UIResource value
 966             // preventing install from correctly settings its colors/font. For
 967             // this reason we do not uninstall the fg/bg/font.
 968 
 969             JComponent c = context.getComponent();
 970             Border border = c.getBorder();
 971 
 972             if (border instanceof UIResource) {
 973                 c.setBorder(null);
 974             }
 975         }
 976     }
 977 
 978     /**
 979      * Convenience method to get a specific style property whose value is
 980      * a <code>Number</code>. If the value is a <code>Number</code>,
 981      * <code>intValue</code> is returned, otherwise <code>defaultValue</code>
 982      * is returned.
 983      *
 984      * @param context SynthContext identifying requester
 985      * @param key Property being requested.
 986      * @param defaultValue Value to return if the property has not been
 987      *        specified, or is not a Number
 988      * @return Value of the named property
 989      */
 990     public int getInt(SynthContext context, Object key, int defaultValue) {
 991         Object value = get(context, key);
 992 
 993         if (value instanceof Number) {
 994             return ((Number)value).intValue();
 995         }
 996         return defaultValue;
 997     }
 998 
 999     /**
1000      * Convenience method to get a specific style property whose value is
1001      * an Boolean.




  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 package javax.swing.plaf.synth;
  26 
  27 import java.awt.*;
  28 import javax.swing.*;
  29 import javax.swing.border.Border;
  30 import javax.swing.plaf.UIResource;
  31 import javax.swing.plaf.basic.BasicLookAndFeel;
  32 import javax.swing.text.DefaultEditorKit;
  33 import java.util.HashMap;
  34 import java.util.Map;
  35 import javax.swing.text.JTextComponent;
  36 import sun.swing.SwingUtilities2;
  37 
  38 /**
  39  * {@code SynthStyle} is a set of style properties.
  40  * Each {@code SynthUI} references at least one
  41  * {@code SynthStyle} that is obtained using a
  42  * {@code SynthStyleFactory}. You typically don't need to interact with
  43  * this class directly, rather you will load a
  44  * <a href="doc-files/synthFileFormat.html">Synth File Format file</a> into
  45  * {@code SynthLookAndFeel} that will create a set of SynthStyles.
  46  *
  47  * @see SynthLookAndFeel
  48  * @see SynthStyleFactory
  49  *
  50  * @since 1.5
  51  * @author Scott Violet
  52  */
  53 public abstract class SynthStyle {
  54     /**
  55      * Contains the default values for certain properties.
  56      */
  57     private static Map<Object, Object> DEFAULT_VALUES;
  58 
  59     /**
  60      * Shared SynthGraphics.
  61      */
  62     private static final SynthGraphicsUtils SYNTH_GRAPHICS =
  63                               new SynthGraphicsUtils();
  64 
  65     /**


 719             if (DEFAULT_VALUES == null) {
 720                 DEFAULT_VALUES = new HashMap<Object, Object>();
 721                 populateDefaultValues();
 722             }
 723             Object value = DEFAULT_VALUES.get(key);
 724             if (value instanceof UIDefaults.LazyValue) {
 725                 value = ((UIDefaults.LazyValue)value).createValue(null);
 726                 DEFAULT_VALUES.put(key, value);
 727             }
 728             return value;
 729         }
 730     }
 731 
 732     /**
 733      * Constructs a SynthStyle.
 734      */
 735     public SynthStyle() {
 736     }
 737 
 738     /**
 739      * Returns the {@code SynthGraphicUtils} for the specified context.
 740      *
 741      * @param context SynthContext identifying requester
 742      * @return SynthGraphicsUtils
 743      */
 744     public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
 745         return SYNTH_GRAPHICS;
 746     }
 747 
 748     /**
 749      * Returns the color for the specified state. This gives precedence to
 750      * foreground and background of the {@code JComponent}. If the
 751      * {@code Color} from the {@code JComponent} is not appropriate,
 752      * or not used, this will invoke {@code getColorForState}. Subclasses
 753      * should generally not have to override this, instead override
 754      * {@link #getColorForState}.
 755      *
 756      * @param context SynthContext identifying requester
 757      * @param type Type of color being requested.
 758      * @return Color
 759      */
 760     public Color getColor(SynthContext context, ColorType type) {
 761         JComponent c = context.getComponent();
 762         Region id = context.getRegion();
 763 
 764         if ((context.getComponentState() & SynthConstants.DISABLED) != 0) {
 765             //This component is disabled, so return the disabled color.
 766             //In some cases this means ignoring the color specified by the
 767             //developer on the component. In other cases it means using a
 768             //specified disabledTextColor, such as on JTextComponents.
 769             //For example, JLabel doesn't specify a disabled color that the
 770             //developer can set, yet it should have a disabled color to the
 771             //text when the label is disabled. This code allows for that.
 772             if (c instanceof JTextComponent) {


 801             // Then use what we've locally defined
 802             color = getColorForState(context, type);
 803         }
 804 
 805         if (color == null) {
 806             // No color, fallback to that of the widget.
 807             if (type == ColorType.BACKGROUND ||
 808                         type == ColorType.TEXT_BACKGROUND) {
 809                 return c.getBackground();
 810             }
 811             else if (type == ColorType.FOREGROUND ||
 812                      type == ColorType.TEXT_FOREGROUND) {
 813                 return c.getForeground();
 814             }
 815         }
 816         return color;
 817     }
 818 
 819     /**
 820      * Returns the color for the specified state. This should NOT call any
 821      * methods on the {@code JComponent}.
 822      *
 823      * @param context SynthContext identifying requester
 824      * @param type Type of color being requested.
 825      * @return Color to render with
 826      */
 827     protected abstract Color getColorForState(SynthContext context,
 828                                               ColorType type);
 829 
 830     /**
 831      * Returns the Font for the specified state. This redirects to the
 832      * {@code JComponent} from the {@code context} as necessary.
 833      * If this does not redirect
 834      * to the JComponent {@link #getFontForState} is invoked.
 835      *
 836      * @param context SynthContext identifying requester
 837      * @return Font to render with
 838      */
 839     public Font getFont(SynthContext context) {
 840         JComponent c = context.getComponent();
 841         if (context.getComponentState() == SynthConstants.ENABLED) {
 842             return c.getFont();
 843         }
 844         Font cFont = c.getFont();
 845         if (cFont != null && !(cFont instanceof UIResource)) {
 846             return cFont;
 847         }
 848         return getFontForState(context);
 849     }
 850 
 851     /**
 852      * Returns the font for the specified state. This should NOT call any
 853      * method on the {@code JComponent}.
 854      *
 855      * @param context SynthContext identifying requester
 856      * @return Font to render with
 857      */
 858     protected abstract Font getFontForState(SynthContext context);
 859 
 860     /**
 861      * Returns the Insets that are used to calculate sizing information.
 862      *
 863      * @param context SynthContext identifying requester
 864      * @param insets Insets to place return value in.
 865      * @return Sizing Insets.
 866      */
 867     public Insets getInsets(SynthContext context, Insets insets) {
 868         if (insets == null) {
 869             insets = new Insets(0, 0, 0, 0);
 870         }
 871         insets.top = insets.bottom = insets.left = insets.right = 0;
 872         return insets;
 873     }
 874 
 875     /**
 876      * Returns the {@code SynthPainter} that will be used for painting.
 877      * This may return null.
 878      *
 879      * @param context SynthContext identifying requester
 880      * @return SynthPainter to use
 881      */
 882     public SynthPainter getPainter(SynthContext context) {
 883         return null;
 884     }
 885 
 886     /**
 887      * Returns true if the region is opaque.
 888      *
 889      * @param context SynthContext identifying requester
 890      * @return true if region is opaque.
 891      */
 892     public boolean isOpaque(SynthContext context) {
 893         return true;
 894     }
 895 
 896     /**


 903     public Object get(SynthContext context, Object key) {
 904         return getDefaultValue(key);
 905     }
 906 
 907     void installDefaults(SynthContext context, SynthUI ui) {
 908         // Special case the Border as this will likely change when the LAF
 909         // can have more control over this.
 910         if (!context.isSubregion()) {
 911             JComponent c = context.getComponent();
 912             Border border = c.getBorder();
 913 
 914             if (border == null || border instanceof UIResource) {
 915                 c.setBorder(new SynthBorder(ui, getInsets(context, null)));
 916             }
 917         }
 918         installDefaults(context);
 919     }
 920 
 921     /**
 922      * Installs the necessary state from this Style on the
 923      * {@code JComponent} from {@code context}.
 924      *
 925      * @param context SynthContext identifying component to install properties
 926      *        to.
 927      */
 928     public void installDefaults(SynthContext context) {
 929         if (!context.isSubregion()) {
 930             JComponent c = context.getComponent();
 931             Region region = context.getRegion();
 932             Font font = c.getFont();
 933 
 934             if (font == null || (font instanceof UIResource)) {
 935                 c.setFont(getFontForState(context));
 936             }
 937             Color background = c.getBackground();
 938             if (background == null || (background instanceof UIResource)) {
 939                 c.setBackground(getColorForState(context,
 940                                                  ColorType.BACKGROUND));
 941             }
 942             Color foreground = c.getForeground();
 943             if (foreground == null || (foreground instanceof UIResource)) {
 944                 c.setForeground(getColorForState(context,
 945                          ColorType.FOREGROUND));
 946             }
 947             LookAndFeel.installProperty(c, "opaque", Boolean.valueOf(isOpaque(context)));
 948         }
 949     }
 950 
 951     /**
 952      * Uninstalls any state that this style installed on
 953      * the {@code JComponent} from {@code context}.
 954      * <p>
 955      * Styles should NOT depend upon this being called, in certain cases
 956      * it may never be called.
 957      *
 958      * @param context SynthContext identifying component to install properties
 959      *        to.
 960      */
 961     public void uninstallDefaults(SynthContext context) {
 962         if (!context.isSubregion()) {
 963             // NOTE: because getForeground, getBackground and getFont will look
 964             // at the parent Container, if we set them to null it may
 965             // mean we they return a non-null and non-UIResource value
 966             // preventing install from correctly settings its colors/font. For
 967             // this reason we do not uninstall the fg/bg/font.
 968 
 969             JComponent c = context.getComponent();
 970             Border border = c.getBorder();
 971 
 972             if (border instanceof UIResource) {
 973                 c.setBorder(null);
 974             }
 975         }
 976     }
 977 
 978     /**
 979      * Convenience method to get a specific style property whose value is
 980      * a {@code Number}. If the value is a {@code Number},
 981      * {@code intValue} is returned, otherwise {@code defaultValue}
 982      * is returned.
 983      *
 984      * @param context SynthContext identifying requester
 985      * @param key Property being requested.
 986      * @param defaultValue Value to return if the property has not been
 987      *        specified, or is not a Number
 988      * @return Value of the named property
 989      */
 990     public int getInt(SynthContext context, Object key, int defaultValue) {
 991         Object value = get(context, key);
 992 
 993         if (value instanceof Number) {
 994             return ((Number)value).intValue();
 995         }
 996         return defaultValue;
 997     }
 998 
 999     /**
1000      * Convenience method to get a specific style property whose value is
1001      * an Boolean.


< prev index next >