The attached patch does:
- Implement bullet painting and formatting for HTML lists.
- Fix the CSS parser/resolver to correctly resolve CSS selectors, that
was completely borked before. This should improve HTML rendering
significantly.
2006-11-07 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/text/html/HTMLEditorKit.java
(HTMLFactory.create): Include ListView.
* javax/swing/text/html/ListView.java
(paint): Removed comment.
* javax/swing/text/html/StyleSheet.java
(CSSStyle.priority): New field.
(CSSStyle.CSSStyle(int)): New constructor with priority.
(CSSStyle.compareTo): New method. Used for sorting the styles.
(CSSStyleSheetParserCallback.declaration): Store the style
with the complete selector.
(ListPainter.attributes): Renamed as field.
(ListPainter.styleSheet): New field.
(ListPainter.type): New field.
(ListPainter.ListPainter): Pass StyleSheet to constructor.
(ListPainter.paint): Provide simplistic implementation.
(getListPainter): Pass StyleSheet to constructor.
(resolveStyle): Fixed CSS style resolving.
Index: javax/swing/text/html/HTMLEditorKit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLEditorKit.java,v
retrieving revision 1.37
diff -u -1 -5 -r1.37 HTMLEditorKit.java
--- javax/swing/text/html/HTMLEditorKit.java 2 Nov 2006 21:36:29 -0000 1.37
+++ javax/swing/text/html/HTMLEditorKit.java 7 Nov 2006 15:16:07 -0000
@@ -634,51 +634,51 @@
|| tag.equals(HTML.Tag.H3) || tag.equals(HTML.Tag.H4)
|| tag.equals(HTML.Tag.H5) || tag.equals(HTML.Tag.H6)
|| tag.equals(HTML.Tag.DT))
view = new ParagraphView(element);
else if (tag.equals(HTML.Tag.LI) || tag.equals(HTML.Tag.DL)
|| tag.equals(HTML.Tag.DD) || tag.equals(HTML.Tag.BODY)
|| tag.equals(HTML.Tag.HTML) || tag.equals(HTML.Tag.CENTER)
|| tag.equals(HTML.Tag.DIV)
|| tag.equals(HTML.Tag.BLOCKQUOTE)
|| tag.equals(HTML.Tag.PRE)
|| tag.equals(HTML.Tag.FORM))
view = new BlockView(element, View.Y_AXIS);
else if (tag.equals(HTML.Tag.IMG))
view = new ImageView(element);
- // FIXME: Uncomment when the views have been implemented
else if (tag.equals(HTML.Tag.CONTENT))
view = new InlineView(element);
else if (tag == HTML.Tag.HEAD)
view = new NullView(element);
else if (tag.equals(HTML.Tag.TABLE))
view = new javax.swing.text.html.TableView(element);
else if (tag.equals(HTML.Tag.TD))
view = new ParagraphView(element);
else if (tag.equals(HTML.Tag.HR))
view = new HRuleView(element);
else if (tag.equals(HTML.Tag.BR))
view = new BRView(element);
else if (tag.equals(HTML.Tag.INPUT) || tag.equals(HTML.Tag.SELECT)
|| tag.equals(HTML.Tag.TEXTAREA))
view = new FormView(element);
- /*
else if (tag.equals(HTML.Tag.MENU) || tag.equals(HTML.Tag.DIR)
|| tag.equals(HTML.Tag.UL) || tag.equals(HTML.Tag.OL))
view = new ListView(element);
+ // FIXME: Uncomment when the views have been implemented
+ /*
else if (tag.equals(HTML.Tag.OBJECT))
view = new ObjectView(element);
else if (tag.equals(HTML.Tag.FRAMESET))
view = new FrameSetView(element);
else if (tag.equals(HTML.Tag.FRAME))
view = new FrameView(element); */
}
if (view == null)
{
System.err.println("missing tag->view mapping for: " + element);
view = new NullView(element);
}
return view;
}
}
Index: javax/swing/text/html/ListView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/ListView.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 ListView.java
--- javax/swing/text/html/ListView.java 21 Mar 2006 21:31:56 -0000 1.1
+++ javax/swing/text/html/ListView.java 7 Nov 2006 15:16:07 -0000
@@ -82,33 +82,30 @@
if (axis != X_AXIS && axis != Y_AXIS)
throw new IllegalArgumentException("Illegal axis parameter: " + axis);
return 0.5F;
}
/**
* Paints the <code>ListView</code>.
*
* @param g the graphics context to use for painting
* @param allocation the allocation given to this view
*/
public void paint(Graphics g, Shape allocation)
{
super.paint(g, allocation);
- // FIXME: Why is this overridden? I think that painting would be done
- // by the superclass and the stylesheet... Maybe find out when this
- // stuff is implemented properly.
}
/**
* Paints the child with the specified index into the specified allocation.
*
* This implementation forwards to the list painter fetched from the
* [EMAIL PROTECTED] StyleSheet} and then calls
* <code>super.paintChild(g, a, index)</code>.
*
* @param g the graphics context to use
* @param a the allocation for the child
* @param index the child index
*/
protected void paintChild(Graphics g, Rectangle a, int index)
{
Index: javax/swing/text/html/StyleSheet.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/StyleSheet.java,v
retrieving revision 1.11
diff -u -1 -5 -r1.11 StyleSheet.java
--- javax/swing/text/html/StyleSheet.java 7 Nov 2006 12:57:13 -0000 1.11
+++ javax/swing/text/html/StyleSheet.java 7 Nov 2006 15:16:07 -0000
@@ -43,33 +43,36 @@
import gnu.javax.swing.text.html.css.CSSParserCallback;
import gnu.javax.swing.text.html.css.FontSize;
import gnu.javax.swing.text.html.css.FontStyle;
import gnu.javax.swing.text.html.css.FontWeight;
import gnu.javax.swing.text.html.css.Length;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import java.util.StringTokenizer;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.View;
@@ -77,31 +80,31 @@
/**
* This class adds support for defining the visual characteristics of HTML views
* being rendered. This enables views to be customized by a look-and-feel, mulitple
* views over the same model can be rendered differently. Each EditorPane has its
* own StyleSheet, but by default one sheet will be shared by all of the HTMLEditorKit
* instances. An HTMLDocument can also have a StyleSheet, which holds specific CSS
* specs.
*
* In order for Views to store less state and therefore be more lightweight,
* the StyleSheet can act as a factory for painters that handle some of the
* rendering tasks. Since the StyleSheet may be used by views over multiple
* documents the HTML attributes don't effect the selector being used.
*
* The rules are stored as named styles, and other information is stored to
* translate the context of an element to a rule.
- *
+ *
* @author Lillian Angel ([EMAIL PROTECTED])
*/
public class StyleSheet extends StyleContext
{
/**
* Parses CSS stylesheets using the parser in gnu/javax/swing/html/css.
*
* This is package private to avoid accessor methods.
*/
class CSSStyleSheetParserCallback
implements CSSParserCallback
{
/**
* The selector for which the rules are currently parsed.
@@ -125,72 +128,83 @@
* Called at the end of a statement.
*/
public void endStatement()
{
selector = null;
}
/**
* Called when a declaration is parsed.
*
* @param property the property
* @param value the value
*/
public void declaration(String property, String value)
{
- for (int i = 0; i < selector.length; i++)
+ CSSStyle style = (CSSStyle) css.get(selector);
+ if (style == null)
{
- CSSStyle style = (CSSStyle) css.get(selector[i]);
- if (style == null)
- {
- style = new CSSStyle();
- css.put(selector[i], style);
- }
- CSS.Attribute cssAtt = CSS.getAttribute(property);
- Object val = CSS.getValue(cssAtt, value);
- if (cssAtt != null)
- style.addAttribute(cssAtt, val);
- // else // For debugging only.
- // System.err.println("no mapping for: " + property);
+ style = new CSSStyle(selector.length);
+ css.put(selector, style);
}
+ CSS.Attribute cssAtt = CSS.getAttribute(property);
+ Object val = CSS.getValue(cssAtt, value);
+ if (cssAtt != null)
+ style.addAttribute(cssAtt, val);
}
}
/**
* Represents a style that is defined by a CSS rule.
*/
private class CSSStyle
extends SimpleAttributeSet
- implements Style
+ implements Style, Comparable
{
+ /**
+ * The priority of this style when matching CSS selectors.
+ */
+ int priority;
+
+ CSSStyle(int prio)
+ {
+ priority = prio;
+ }
+
public String getName()
{
// TODO: Implement this for correctness.
return null;
}
public void addChangeListener(ChangeListener listener)
{
// TODO: Implement this for correctness.
}
public void removeChangeListener(ChangeListener listener)
{
// TODO: Implement this for correctness.
}
+
+ public int compareTo(Object o)
+ {
+ CSSStyle other = (CSSStyle) o;
+ return other.priority - priority;
+ }
}
/** The base URL */
URL base;
/** Base font size (int) */
int baseFontSize;
/** The style sheets stored. */
StyleSheet[] styleSheet;
/**
* Maps element names (selectors) to AttributSet (the corresponding style
* information).
@@ -362,38 +376,52 @@
*
* @param selector the selector
* @param tags the tags
* @param ids the corresponding ID attributes
* @param classes the corresponding CLASS attributes
*
* @return the resolved style
*/
private Style resolveStyle(String selector, String[] tags, String[] ids,
String[] classes)
{
// FIXME: This style resolver is not correct. But it works good enough for
// the default.css.
int count = tags.length;
ArrayList styles = new ArrayList();
- for (int i = 0; i < count; i++)
+ Set selectors = css.keySet();
+ for (Iterator i = selectors.iterator(); i.hasNext();)
{
- Style style = (Style) css.get(tags[i]);
- if (style != null)
- styles.add(style);
- // FIXME: Handle ID and CLASS attributes.
+ String[] sel = (String[]) i.next();
+ // All parts of the selector must match.
+ if (sel.length <= tags.length)
+ {
+ boolean match = true;
+ for (int j = sel.length - 1; j >= 0 && match; j--)
+ {
+ if (! tags[sel.length - 1 - j].equals(sel[j]))
+ match = false;
+ }
+ if (match)
+ styles.add(css.get(sel));
+ }
}
+
+ // Sort selectors.
+ Collections.sort(styles);
Style[] styleArray = new Style[styles.size()];
+ styleArray = (Style[]) styles.toArray(styleArray);
Style resolved = new MultiStyle(selector,
(Style[]) styles.toArray(styleArray));
resolvedStyles.put(selector, resolved);
return resolved;
}
/**
* Gets the rule that best matches the selector. selector is a space
* separated String of element names. The attributes of the returned
* Style will change as rules are added and removed.
*
* @param selector - the element names separated by spaces
* @return the set of CSS attributes to use to render
*/
public Style getRule(String selector)
@@ -804,31 +832,31 @@
* @return the box formatter
*/
public BoxPainter getBoxPainter(AttributeSet a)
{
return new BoxPainter(a, this);
}
/**
* Gets the list formatter to use for the given set of CSS attributes.
*
* @param a - the given set
* @return the list formatter
*/
public ListPainter getListPainter(AttributeSet a)
{
- return new ListPainter(a);
+ return new ListPainter(a, this);
}
/**
* Sets the base font size between 1 and 7.
*
* @param sz - the new font size for the base.
*/
public void setBaseFontSize(int sz)
{
if (sz <= 7 && sz >= 1)
baseFontSize = sz;
}
/**
* Sets the base font size from the String. It can either identify
@@ -1051,46 +1079,70 @@
}
/**
* This class carries out some of the CSS list formatting duties. Implementations
* of this class enable views to present the CSS formatting while not knowing anything
* about how the CSS values are being cached.
*
* @author Lillian Angel ([EMAIL PROTECTED])
*/
public static class ListPainter implements Serializable
{
/**
* Attribute set for painter
*/
- AttributeSet as;
-
+ private AttributeSet attributes;
+
+ /**
+ * The associated style sheet.
+ */
+ private StyleSheet styleSheet;
+
+ /**
+ * The bullet type.
+ */
+ private String type;
+
/**
* Package-private constructor.
*
* @param as - AttributeSet for painter
*/
- ListPainter(AttributeSet as)
+ ListPainter(AttributeSet as, StyleSheet ss)
{
- this.as = as;
+ attributes = as;
+ styleSheet = ss;
+ type = (String) as.getAttribute(CSS.Attribute.LIST_STYLE_TYPE);
}
-
+
/**
* Paints the CSS list decoration according to the attributes given.
*
* @param g - the graphics configuration
* @param x - the x coordinate
* @param y - the y coordinate
* @param w - the width of the allocated area
* @param h - the height of the allocated area
* @param v - the view making the request
* @param item - the list item to be painted >=0.
*/
public void paint(Graphics g, float x, float y, float w, float h, View v,
int item)
{
- // FIXME: Not implemented.
+ // FIXME: This is a very simplistic list rendering. We still need
+ // to implement different bullet types (see type field) and custom
+ // bullets via images.
+ View itemView = v.getView(item);
+ AttributeSet viewAtts = itemView.getAttributes();
+ Object tag = viewAtts.getAttribute(StyleConstants.NameAttribute);
+ // Only paint something here when the child view is an LI tag
+ // and the calling view is some of the list tags then).
+ if (tag != null && tag == HTML.Tag.LI)
+ {
+ g.setColor(Color.BLACK);
+ g.fillOval((int) x - 15, (int) (h / 2 - 3 + y), 6, 6);
+ }
}
}
}