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 /**
|