src/share/classes/javax/swing/text/html/StyleSheet.java

Print this page




 110  * Therefore, in the previous example the background would have a
 111  * red color as the body element defines the background color to be red.
 112  * <p>
 113  * As already mentioned this supports CSS. We don't support the full CSS
 114  * spec. Refer to the javadoc of the CSS class to see what properties
 115  * we support. The two major CSS parsing related
 116  * concepts we do not currently
 117  * support are pseudo selectors, such as <code>A:link { color: red }</code>,
 118  * and the <code>important</code> modifier.
 119  * <p>
 120  * @implNote This implementation is currently
 121  * incomplete.  It can be replaced with alternative implementations
 122  * that are complete.  Future versions of this class will provide
 123  * better CSS support.
 124  *
 125  * @author  Timothy Prinzing
 126  * @author  Sunita Mani
 127  * @author  Sara Swanson
 128  * @author  Jill Nakata
 129  */

 130 public class StyleSheet extends StyleContext {
 131     // As the javadoc states, this class maintains a mapping between
 132     // a CSS selector (such as p.bar) and a Style.
 133     // This consists of a number of parts:
 134     // . Each selector is broken down into its constituent simple selectors,
 135     //   and stored in an inverted graph, for example:
 136     //     p { color: red } ol p { font-size: 10pt } ul p { font-size: 12pt }
 137     //   results in the graph:
 138     //          root
 139     //           |
 140     //           p
 141     //          / \
 142     //         ol ul
 143     //   each node (an instance of SelectorMapping) has an associated
 144     //   specificity and potentially a Style.
 145     // . Every rule that is asked for (either by way of getRule(String) or
 146     //   getRule(HTML.Tag, Element)) results in a unique instance of
 147     //   ResolvedStyle. ResolvedStyles contain the AttributeSets from the
 148     //   SelectorMapping.
 149     // . When a new rule is created it is inserted into the graph, and


 746                                            ((StyleConstants)key, value);
 747                             if (cssValue != null) {
 748                                 converted.addAttribute(cssKey, cssValue);
 749                             }
 750                         }
 751                     }
 752                     if (cssValue == null) {
 753                         converted.addAttribute(key, a.getAttribute(key));
 754                     }
 755                 }
 756                 return converted;
 757             }
 758         }
 759         return a;
 760     }
 761 
 762     /**
 763      * Large set of attributes that does conversion of requests
 764      * for attributes of type StyleConstants.
 765      */

 766     class LargeConversionSet extends SimpleAttributeSet {
 767 
 768         /**
 769          * Creates a new attribute set based on a supplied set of attributes.
 770          *
 771          * @param source the set of attributes
 772          */
 773         public LargeConversionSet(AttributeSet source) {
 774             super(source);
 775         }
 776 
 777         public LargeConversionSet() {
 778             super();
 779         }
 780 
 781         /**
 782          * Checks whether a given attribute is defined.
 783          *
 784          * @param key the attribute key
 785          * @return true if the attribute is defined


1743             if (hashtable != null) {
1744                 hashtable.clear();
1745             }
1746         }
1747     }
1748 
1749 
1750     static final Border noBorder = new EmptyBorder(0,0,0,0);
1751 
1752     /**
1753      * Class to carry out some of the duties of
1754      * CSS formatting.  Implementations of this
1755      * class enable views to present the CSS formatting
1756      * while not knowing anything about how the CSS values
1757      * are being cached.
1758      * <p>
1759      * As a delegate of Views, this object is responsible for
1760      * the insets of a View and making sure the background
1761      * is maintained according to the CSS attributes.
1762      */

1763     public static class BoxPainter implements Serializable {
1764 
1765         BoxPainter(AttributeSet a, CSS css, StyleSheet ss) {
1766             this.ss = ss;
1767             this.css = css;
1768             border = getBorder(a);
1769             binsets = border.getBorderInsets(null);
1770             topMargin = getLength(CSS.Attribute.MARGIN_TOP, a);
1771             bottomMargin = getLength(CSS.Attribute.MARGIN_BOTTOM, a);
1772             leftMargin = getLength(CSS.Attribute.MARGIN_LEFT, a);
1773             rightMargin = getLength(CSS.Attribute.MARGIN_RIGHT, a);
1774             bg = ss.getBackground(a);
1775             if (ss.getBackgroundImage(a) != null) {
1776                 bgPainter = new BackgroundImagePainter(a, css, ss);
1777             }
1778         }
1779 
1780         /**
1781          * Fetches a border to render for the given attributes.
1782          * PENDING(prinz) This is pretty badly hacked at the


2002         float leftMargin;
2003         float rightMargin;
2004         // Bitmask, used to indicate what margins are relative:
2005         // bit 0 for top, 1 for bottom, 2 for left and 3 for right.
2006         short marginFlags;
2007         Border border;
2008         Insets binsets;
2009         CSS css;
2010         StyleSheet ss;
2011         Color bg;
2012         BackgroundImagePainter bgPainter;
2013     }
2014 
2015     /**
2016      * Class to carry out some of the duties of CSS list
2017      * formatting.  Implementations of this
2018      * class enable views to present the CSS formatting
2019      * while not knowing anything about how the CSS values
2020      * are being cached.
2021      */

2022     public static class ListPainter implements Serializable {
2023 
2024         ListPainter(AttributeSet attr, StyleSheet ss) {
2025             this.ss = ss;
2026             /* Get the image to use as a list bullet */
2027             String imgstr = (String)attr.getAttribute(CSS.Attribute.
2028                                                       LIST_STYLE_IMAGE);
2029             type = null;
2030             if (imgstr != null && !imgstr.equals("none")) {
2031                 String tmpstr = null;
2032                 try {
2033                     StringTokenizer st = new StringTokenizer(imgstr, "()");
2034                     if (st.hasMoreTokens())
2035                         tmpstr = st.nextToken();
2036                     if (st.hasMoreTokens())
2037                         tmpstr = st.nextToken();
2038                     URL u = new URL(tmpstr);
2039                     img = new ImageIcon(u);
2040                 } catch (MalformedURLException e) {
2041                     if (tmpstr != null && ss != null && ss.getBase() != null) {


2431             }
2432 
2433             return result;
2434         }
2435 
2436         private Rectangle paintRect;
2437         private boolean checkedForStart;
2438         private int start;
2439         private CSS.Value type;
2440         URL imageurl;
2441         private StyleSheet ss = null;
2442         Icon img = null;
2443         private int bulletgap = 5;
2444         private boolean isLeftToRight;
2445     }
2446 
2447 
2448     /**
2449      * Paints the background image.
2450      */

2451     static class BackgroundImagePainter implements Serializable {
2452         ImageIcon   backgroundImage;
2453         float       hPosition;
2454         float       vPosition;
2455         // bit mask: 0 for repeat x, 1 for repeat y, 2 for horiz relative,
2456         // 3 for vert relative
2457         short       flags;
2458         // These are used when painting, updatePaintCoordinates updates them.
2459         private int paintX;
2460         private int paintY;
2461         private int paintMaxX;
2462         private int paintMaxY;
2463 
2464         BackgroundImagePainter(AttributeSet a, CSS css, StyleSheet ss) {
2465             backgroundImage = ss.getBackgroundImage(a);
2466             // Determine the position.
2467             CSS.BackgroundPosition pos = (CSS.BackgroundPosition)a.getAttribute
2468                                            (CSS.Attribute.BACKGROUND_POSITION);
2469             if (pos != null) {
2470                 hPosition = pos.getHorizontalPosition();


2598                             paintMaxY = ((clip.y + clip.height - paintY) /
2599                                          height + 1) * height + paintY;
2600                         }
2601                     }
2602                     if (clip.y > paintY) {
2603                         paintY = (clip.y - paintY) / height * height + paintY;
2604                     }
2605                 }
2606             }
2607             // Valid
2608             return true;
2609         }
2610     }
2611 
2612 
2613     /**
2614      * A subclass of MuxingAttributeSet that translates between
2615      * CSS and HTML and StyleConstants. The AttributeSets used are
2616      * the CSS rules that match the Views Elements.
2617      */

2618     class ViewAttributeSet extends MuxingAttributeSet {
2619         ViewAttributeSet(View v) {
2620             host = v;
2621 
2622             // PENDING(prinz) fix this up to be a more realistic
2623             // implementation.
2624             Document doc = v.getDocument();
2625             SearchBuffer sb = SearchBuffer.obtainSearchBuffer();
2626             Vector<AttributeSet> muxList = sb.getVector();
2627             try {
2628                 if (doc instanceof HTMLDocument) {
2629                     StyleSheet styles = StyleSheet.this;
2630                     Element elem = v.getElement();
2631                     AttributeSet a = elem.getAttributes();
2632                     AttributeSet htmlAttr = styles.translateHTMLToCSS(a);
2633 
2634                     if (htmlAttr.getAttributeCount() != 0) {
2635                         muxList.addElement(htmlAttr);
2636                     }
2637                     if (elem.isLeaf()) {


2762                 return null;
2763             }
2764             View parent = host.getParent();
2765             return (parent != null) ? parent.getAttributes() : null;
2766         }
2767 
2768         /** View created for. */
2769         View host;
2770     }
2771 
2772 
2773     /**
2774      * A subclass of MuxingAttributeSet that implements Style. Currently
2775      * the MutableAttributeSet methods are unimplemented, that is they
2776      * do nothing.
2777      */
2778     // PENDING(sky): Decide what to do with this. Either make it
2779     // contain a SimpleAttributeSet that modify methods are delegated to,
2780     // or change getRule to return an AttributeSet and then don't make this
2781     // implement Style.

2782     static class ResolvedStyle extends MuxingAttributeSet implements
2783                   Serializable, Style {
2784         ResolvedStyle(String name, AttributeSet[] attrs, int extendedIndex) {
2785             super(attrs);
2786             this.name = name;
2787             this.extendedIndex = extendedIndex;
2788         }
2789 
2790         /**
2791          * Inserts a Style into the receiver so that the styles the
2792          * receiver represents are still ordered by specificity.
2793          * <code>style</code> will be added before any extended styles, that
2794          * is before extendedIndex.
2795          */
2796         synchronized void insertStyle(Style style, int specificity) {
2797             AttributeSet[] attrs = getAttributes();
2798             int maxCounter = attrs.length;
2799             int counter = 0;
2800             for (;counter < extendedIndex; counter++) {
2801                 if (specificity > getSpecificity(((Style)attrs[counter]).


3003             return new ChangeListener[0];
3004         }
3005 
3006         /** The name of the Style, which is the selector.
3007          * This will NEVER change!
3008          */
3009         String name;
3010         /** Start index of styles coming from other StyleSheets. */
3011         private int extendedIndex;
3012     }
3013 
3014 
3015     /**
3016      * SelectorMapping contains a specifitiy, as an integer, and an associated
3017      * Style. It can also reference children <code>SelectorMapping</code>s,
3018      * so that it behaves like a tree.
3019      * <p>
3020      * This is not thread safe, it is assumed the caller will take the
3021      * necessary precations if this is to be used in a threaded environment.
3022      */

3023     static class SelectorMapping implements Serializable {
3024         public SelectorMapping(int specificity) {
3025             this.specificity = specificity;
3026         }
3027 
3028         /**
3029          * Returns the specificity this mapping represents.
3030          */
3031         public int getSpecificity() {
3032             return specificity;
3033         }
3034 
3035         /**
3036          * Sets the Style associated with this mapping.
3037          */
3038         public void setStyle(Style style) {
3039             this.style = style;
3040         }
3041 
3042         /**




 110  * Therefore, in the previous example the background would have a
 111  * red color as the body element defines the background color to be red.
 112  * <p>
 113  * As already mentioned this supports CSS. We don't support the full CSS
 114  * spec. Refer to the javadoc of the CSS class to see what properties
 115  * we support. The two major CSS parsing related
 116  * concepts we do not currently
 117  * support are pseudo selectors, such as <code>A:link { color: red }</code>,
 118  * and the <code>important</code> modifier.
 119  * <p>
 120  * @implNote This implementation is currently
 121  * incomplete.  It can be replaced with alternative implementations
 122  * that are complete.  Future versions of this class will provide
 123  * better CSS support.
 124  *
 125  * @author  Timothy Prinzing
 126  * @author  Sunita Mani
 127  * @author  Sara Swanson
 128  * @author  Jill Nakata
 129  */
 130 @SuppressWarnings("serial") // Superclass is not serializable across versions
 131 public class StyleSheet extends StyleContext {
 132     // As the javadoc states, this class maintains a mapping between
 133     // a CSS selector (such as p.bar) and a Style.
 134     // This consists of a number of parts:
 135     // . Each selector is broken down into its constituent simple selectors,
 136     //   and stored in an inverted graph, for example:
 137     //     p { color: red } ol p { font-size: 10pt } ul p { font-size: 12pt }
 138     //   results in the graph:
 139     //          root
 140     //           |
 141     //           p
 142     //          / \
 143     //         ol ul
 144     //   each node (an instance of SelectorMapping) has an associated
 145     //   specificity and potentially a Style.
 146     // . Every rule that is asked for (either by way of getRule(String) or
 147     //   getRule(HTML.Tag, Element)) results in a unique instance of
 148     //   ResolvedStyle. ResolvedStyles contain the AttributeSets from the
 149     //   SelectorMapping.
 150     // . When a new rule is created it is inserted into the graph, and


 747                                            ((StyleConstants)key, value);
 748                             if (cssValue != null) {
 749                                 converted.addAttribute(cssKey, cssValue);
 750                             }
 751                         }
 752                     }
 753                     if (cssValue == null) {
 754                         converted.addAttribute(key, a.getAttribute(key));
 755                     }
 756                 }
 757                 return converted;
 758             }
 759         }
 760         return a;
 761     }
 762 
 763     /**
 764      * Large set of attributes that does conversion of requests
 765      * for attributes of type StyleConstants.
 766      */
 767     @SuppressWarnings("serial") // Superclass is not serializable across versions
 768     class LargeConversionSet extends SimpleAttributeSet {
 769 
 770         /**
 771          * Creates a new attribute set based on a supplied set of attributes.
 772          *
 773          * @param source the set of attributes
 774          */
 775         public LargeConversionSet(AttributeSet source) {
 776             super(source);
 777         }
 778 
 779         public LargeConversionSet() {
 780             super();
 781         }
 782 
 783         /**
 784          * Checks whether a given attribute is defined.
 785          *
 786          * @param key the attribute key
 787          * @return true if the attribute is defined


1745             if (hashtable != null) {
1746                 hashtable.clear();
1747             }
1748         }
1749     }
1750 
1751 
1752     static final Border noBorder = new EmptyBorder(0,0,0,0);
1753 
1754     /**
1755      * Class to carry out some of the duties of
1756      * CSS formatting.  Implementations of this
1757      * class enable views to present the CSS formatting
1758      * while not knowing anything about how the CSS values
1759      * are being cached.
1760      * <p>
1761      * As a delegate of Views, this object is responsible for
1762      * the insets of a View and making sure the background
1763      * is maintained according to the CSS attributes.
1764      */
1765     @SuppressWarnings("serial") // Same-version serialization only
1766     public static class BoxPainter implements Serializable {
1767 
1768         BoxPainter(AttributeSet a, CSS css, StyleSheet ss) {
1769             this.ss = ss;
1770             this.css = css;
1771             border = getBorder(a);
1772             binsets = border.getBorderInsets(null);
1773             topMargin = getLength(CSS.Attribute.MARGIN_TOP, a);
1774             bottomMargin = getLength(CSS.Attribute.MARGIN_BOTTOM, a);
1775             leftMargin = getLength(CSS.Attribute.MARGIN_LEFT, a);
1776             rightMargin = getLength(CSS.Attribute.MARGIN_RIGHT, a);
1777             bg = ss.getBackground(a);
1778             if (ss.getBackgroundImage(a) != null) {
1779                 bgPainter = new BackgroundImagePainter(a, css, ss);
1780             }
1781         }
1782 
1783         /**
1784          * Fetches a border to render for the given attributes.
1785          * PENDING(prinz) This is pretty badly hacked at the


2005         float leftMargin;
2006         float rightMargin;
2007         // Bitmask, used to indicate what margins are relative:
2008         // bit 0 for top, 1 for bottom, 2 for left and 3 for right.
2009         short marginFlags;
2010         Border border;
2011         Insets binsets;
2012         CSS css;
2013         StyleSheet ss;
2014         Color bg;
2015         BackgroundImagePainter bgPainter;
2016     }
2017 
2018     /**
2019      * Class to carry out some of the duties of CSS list
2020      * formatting.  Implementations of this
2021      * class enable views to present the CSS formatting
2022      * while not knowing anything about how the CSS values
2023      * are being cached.
2024      */
2025     @SuppressWarnings("serial") // Same-version serialization only
2026     public static class ListPainter implements Serializable {
2027 
2028         ListPainter(AttributeSet attr, StyleSheet ss) {
2029             this.ss = ss;
2030             /* Get the image to use as a list bullet */
2031             String imgstr = (String)attr.getAttribute(CSS.Attribute.
2032                                                       LIST_STYLE_IMAGE);
2033             type = null;
2034             if (imgstr != null && !imgstr.equals("none")) {
2035                 String tmpstr = null;
2036                 try {
2037                     StringTokenizer st = new StringTokenizer(imgstr, "()");
2038                     if (st.hasMoreTokens())
2039                         tmpstr = st.nextToken();
2040                     if (st.hasMoreTokens())
2041                         tmpstr = st.nextToken();
2042                     URL u = new URL(tmpstr);
2043                     img = new ImageIcon(u);
2044                 } catch (MalformedURLException e) {
2045                     if (tmpstr != null && ss != null && ss.getBase() != null) {


2435             }
2436 
2437             return result;
2438         }
2439 
2440         private Rectangle paintRect;
2441         private boolean checkedForStart;
2442         private int start;
2443         private CSS.Value type;
2444         URL imageurl;
2445         private StyleSheet ss = null;
2446         Icon img = null;
2447         private int bulletgap = 5;
2448         private boolean isLeftToRight;
2449     }
2450 
2451 
2452     /**
2453      * Paints the background image.
2454      */
2455     @SuppressWarnings("serial") // Same-version serialization only
2456     static class BackgroundImagePainter implements Serializable {
2457         ImageIcon   backgroundImage;
2458         float       hPosition;
2459         float       vPosition;
2460         // bit mask: 0 for repeat x, 1 for repeat y, 2 for horiz relative,
2461         // 3 for vert relative
2462         short       flags;
2463         // These are used when painting, updatePaintCoordinates updates them.
2464         private int paintX;
2465         private int paintY;
2466         private int paintMaxX;
2467         private int paintMaxY;
2468 
2469         BackgroundImagePainter(AttributeSet a, CSS css, StyleSheet ss) {
2470             backgroundImage = ss.getBackgroundImage(a);
2471             // Determine the position.
2472             CSS.BackgroundPosition pos = (CSS.BackgroundPosition)a.getAttribute
2473                                            (CSS.Attribute.BACKGROUND_POSITION);
2474             if (pos != null) {
2475                 hPosition = pos.getHorizontalPosition();


2603                             paintMaxY = ((clip.y + clip.height - paintY) /
2604                                          height + 1) * height + paintY;
2605                         }
2606                     }
2607                     if (clip.y > paintY) {
2608                         paintY = (clip.y - paintY) / height * height + paintY;
2609                     }
2610                 }
2611             }
2612             // Valid
2613             return true;
2614         }
2615     }
2616 
2617 
2618     /**
2619      * A subclass of MuxingAttributeSet that translates between
2620      * CSS and HTML and StyleConstants. The AttributeSets used are
2621      * the CSS rules that match the Views Elements.
2622      */
2623     @SuppressWarnings("serial") // Same-version serialization only
2624     class ViewAttributeSet extends MuxingAttributeSet {
2625         ViewAttributeSet(View v) {
2626             host = v;
2627 
2628             // PENDING(prinz) fix this up to be a more realistic
2629             // implementation.
2630             Document doc = v.getDocument();
2631             SearchBuffer sb = SearchBuffer.obtainSearchBuffer();
2632             Vector<AttributeSet> muxList = sb.getVector();
2633             try {
2634                 if (doc instanceof HTMLDocument) {
2635                     StyleSheet styles = StyleSheet.this;
2636                     Element elem = v.getElement();
2637                     AttributeSet a = elem.getAttributes();
2638                     AttributeSet htmlAttr = styles.translateHTMLToCSS(a);
2639 
2640                     if (htmlAttr.getAttributeCount() != 0) {
2641                         muxList.addElement(htmlAttr);
2642                     }
2643                     if (elem.isLeaf()) {


2768                 return null;
2769             }
2770             View parent = host.getParent();
2771             return (parent != null) ? parent.getAttributes() : null;
2772         }
2773 
2774         /** View created for. */
2775         View host;
2776     }
2777 
2778 
2779     /**
2780      * A subclass of MuxingAttributeSet that implements Style. Currently
2781      * the MutableAttributeSet methods are unimplemented, that is they
2782      * do nothing.
2783      */
2784     // PENDING(sky): Decide what to do with this. Either make it
2785     // contain a SimpleAttributeSet that modify methods are delegated to,
2786     // or change getRule to return an AttributeSet and then don't make this
2787     // implement Style.
2788     @SuppressWarnings("serial") // Same-version serialization only
2789     static class ResolvedStyle extends MuxingAttributeSet implements
2790                   Serializable, Style {
2791         ResolvedStyle(String name, AttributeSet[] attrs, int extendedIndex) {
2792             super(attrs);
2793             this.name = name;
2794             this.extendedIndex = extendedIndex;
2795         }
2796 
2797         /**
2798          * Inserts a Style into the receiver so that the styles the
2799          * receiver represents are still ordered by specificity.
2800          * <code>style</code> will be added before any extended styles, that
2801          * is before extendedIndex.
2802          */
2803         synchronized void insertStyle(Style style, int specificity) {
2804             AttributeSet[] attrs = getAttributes();
2805             int maxCounter = attrs.length;
2806             int counter = 0;
2807             for (;counter < extendedIndex; counter++) {
2808                 if (specificity > getSpecificity(((Style)attrs[counter]).


3010             return new ChangeListener[0];
3011         }
3012 
3013         /** The name of the Style, which is the selector.
3014          * This will NEVER change!
3015          */
3016         String name;
3017         /** Start index of styles coming from other StyleSheets. */
3018         private int extendedIndex;
3019     }
3020 
3021 
3022     /**
3023      * SelectorMapping contains a specifitiy, as an integer, and an associated
3024      * Style. It can also reference children <code>SelectorMapping</code>s,
3025      * so that it behaves like a tree.
3026      * <p>
3027      * This is not thread safe, it is assumed the caller will take the
3028      * necessary precations if this is to be used in a threaded environment.
3029      */
3030     @SuppressWarnings("serial") // Same-version serialization only
3031     static class SelectorMapping implements Serializable {
3032         public SelectorMapping(int specificity) {
3033             this.specificity = specificity;
3034         }
3035 
3036         /**
3037          * Returns the specificity this mapping represents.
3038          */
3039         public int getSpecificity() {
3040             return specificity;
3041         }
3042 
3043         /**
3044          * Sets the Style associated with this mapping.
3045          */
3046         public void setStyle(Style style) {
3047             this.style = style;
3048         }
3049 
3050         /**