This adds support for the HTML table cellspacing and cellpadding
attribute. Nice sideeffect, since these attributes get mapped to the CSS
padding* and border-width attributes, and these are actually
implemented, this improves general CSS support for all HTML elements.
This allows you to render the following quite nicely:
http://kennke.org/~roman/japi.png
2006-11-15 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/text/html/CSS.java
(Attribute.BORDER_SPACING): New field for the CSS border-spacing
attribute.
* javax/swing/text/html/StyleSheet.java
(BoxPainter.bottomPadding): New field.
(BoxPainter.leftPadding): New field.
(BoxPainter.rightPadding): New field.
(BoxPainter.topPadding): New field.
(BoxPainter.BoxPainter): Fetch the MARGIN and PADDING* attributes
too.
(BoxPainter.getInset): Recognize and include the padding.
(translateHTMLToCSS): Added mapping for CELLPADDING and CELLSPACING.
javax/swing/text/html/TableView.java
(RowView.calculateMajorAxisRequirements): Adjust req's for
cellSpacing.
(RowView.layoutMajorAxis): Adjust multi-column span for cellSpacing.
(cellSpacing): New field.
(columnRequirements): Made package private to avoid accessor method.
(calculateMinorAxisRequirements): Include cellSpacing.
(calculateMajorAxisRequirements): Overridden to include cellSpacing.
(layoutMajorAxis): Likewise.
(layoutColumns): Respect cellSpacing.
(setParent): Overridden to fetch the CSS attributes when view gets
connected.
(setPropertiesFromAttributes): New method. Fetches the cell
spacing from the CSS attributes.
/Roman
Index: javax/swing/text/html/CSS.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/CSS.java,v
retrieving revision 1.9
diff -u -1 -5 -r1.9 CSS.java
--- javax/swing/text/html/CSS.java 11 Nov 2006 11:02:07 -0000 1.9
+++ javax/swing/text/html/CSS.java 15 Nov 2006 11:02:31 -0000
@@ -403,30 +403,32 @@
new Attribute("border-top-style", false, null);
static final Attribute BORDER_BOTTOM_STYLE =
new Attribute("border-bottom-style", false, null);
static final Attribute BORDER_LEFT_STYLE =
new Attribute("border-left-style", false, null);
static final Attribute BORDER_RIGHT_STYLE =
new Attribute("border-right-style", false, null);
static final Attribute BORDER_TOP_COLOR =
new Attribute("border-top-color", false, null);
static final Attribute BORDER_BOTTOM_COLOR =
new Attribute("border-bottom-color", false, null);
static final Attribute BORDER_LEFT_COLOR =
new Attribute("border-left-color", false, null);
static final Attribute BORDER_RIGHT_COLOR =
new Attribute("border-right-color", false, null);
+ static final Attribute BORDER_SPACING =
+ new Attribute("border-spacing", false, null);
/**
* The attribute string.
*/
String attStr;
/**
* Indicates if this attribute should be inherited from it's parent or
* not.
*/
boolean isInherited;
/**
* A default value for this attribute if one exists, otherwise null.
*/
@@ -504,31 +506,34 @@
o = new FontSize(v);
else if (att == Attribute.FONT_WEIGHT)
o = new FontWeight(v);
else if (att == Attribute.FONT_STYLE)
o = new FontStyle(v);
else if (att == Attribute.COLOR || att == Attribute.BACKGROUND_COLOR
|| att == Attribute.BORDER_COLOR
|| att == Attribute.BORDER_TOP_COLOR
|| att == Attribute.BORDER_BOTTOM_COLOR
|| att == Attribute.BORDER_LEFT_COLOR
|| att == Attribute.BORDER_RIGHT_COLOR)
o = new CSSColor(v);
else if (att == Attribute.MARGIN || att == Attribute.MARGIN_BOTTOM
|| att == Attribute.MARGIN_LEFT || att == Attribute.MARGIN_RIGHT
|| att == Attribute.MARGIN_TOP || att == Attribute.WIDTH
- || att == Attribute.HEIGHT)
+ || att == Attribute.HEIGHT
+ || att == Attribute.PADDING || att == Attribute.PADDING_BOTTOM
+ || att == Attribute.PADDING_LEFT || att == Attribute.PADDING_RIGHT
+ || att == Attribute.PADDING_TOP)
o = new Length(v);
else if (att == Attribute.BORDER_WIDTH || att == Attribute.BORDER_TOP_WIDTH
|| att == Attribute.BORDER_LEFT_WIDTH
|| att == Attribute.BORDER_RIGHT_WIDTH
|| att == Attribute.BORDER_BOTTOM_WIDTH)
o = new BorderWidth(v);
else
o = v;
return o;
}
static void addInternal(MutableAttributeSet atts, Attribute a, String v)
{
if (a == Attribute.BACKGROUND)
parseBackgroundShorthand(atts, v);
Index: javax/swing/text/html/StyleSheet.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/StyleSheet.java,v
retrieving revision 1.14
diff -u -1 -5 -r1.14 StyleSheet.java
--- javax/swing/text/html/StyleSheet.java 11 Nov 2006 11:02:07 -0000 1.14
+++ javax/swing/text/html/StyleSheet.java 15 Nov 2006 11:02:31 -0000
@@ -697,30 +697,51 @@
o = htmlAttrSet.getAttribute(HTML.Attribute.WIDTH);
if (o != null)
cssAttr = addAttribute(cssAttr, CSS.Attribute.WIDTH,
CSS.getValue(CSS.Attribute.WIDTH, o.toString()));
// The HTML height attribute maps directly to CSS height.
o = htmlAttrSet.getAttribute(HTML.Attribute.HEIGHT);
if (o != null)
cssAttr = addAttribute(cssAttr, CSS.Attribute.HEIGHT,
CSS.getValue(CSS.Attribute.HEIGHT, o.toString()));
o = htmlAttrSet.getAttribute(HTML.Attribute.NOWRAP);
if (o != null)
cssAttr = addAttribute(cssAttr, CSS.Attribute.WHITE_SPACE, "nowrap");
+ // Map cellspacing attr of tables to CSS border-spacing.
+ o = htmlAttrSet.getAttribute(HTML.Attribute.CELLSPACING);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.BORDER_SPACING,
+ new Length(o.toString()));
+
+ // For table cells and headers, fetch the cellpadding value from the
+ // parent table and set it as CSS padding attribute.
+ HTML.Tag tag = (HTML.Tag)
+ htmlAttrSet.getAttribute(StyleConstants.NameAttribute);
+ if ((tag == HTML.Tag.TD || tag == HTML.Tag.TH)
+ && htmlAttrSet instanceof Element)
+ {
+ Element el = (Element) htmlAttrSet;
+ AttributeSet tableAttrs = el.getParentElement().getParentElement()
+ .getAttributes();
+ o = tableAttrs.getAttribute(HTML.Attribute.CELLPADDING);
+ if (o != null)
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.PADDING,
+ new Length(o.toString()));
+ }
// TODO: Add more mappings.
return cssAttr;
}
/**
* Adds an attribute to the given set and returns a new set. This is implemented
* to convert StyleConstants attributes to CSS before forwarding them to the superclass.
* The StyleConstants attribute do not have corresponding CSS entry, the attribute
* is stored (but will likely not be used).
*
* @param old - the old set
* @param key - the non-null attribute key
* @param value - the attribute value
* @return the updated set
*/
@@ -1024,99 +1045,134 @@
/**
* The top inset.
*/
private float topInset;
/**
* The bottom inset.
*/
private float bottomInset;
/**
* The border of the box.
*/
private Border border;
+ private float leftPadding;
+ private float rightPadding;
+ private float topPadding;
+ private float bottomPadding;
+
/**
* The background color.
*/
private Color background;
/**
* Package-private constructor.
*
* @param as - AttributeSet for painter
*/
BoxPainter(AttributeSet as, StyleSheet ss)
{
- Length l = (Length) as.getAttribute(CSS.Attribute.MARGIN_LEFT);
+ // Fetch margins.
+ Length l = (Length) as.getAttribute(CSS.Attribute.MARGIN);
+ if (l != null)
+ {
+ topInset = bottomInset = leftInset = rightInset = l.getValue();
+ }
+ l = (Length) as.getAttribute(CSS.Attribute.MARGIN_LEFT);
if (l != null)
leftInset = l.getValue();
l = (Length) as.getAttribute(CSS.Attribute.MARGIN_RIGHT);
if (l != null)
rightInset = l.getValue();
l = (Length) as.getAttribute(CSS.Attribute.MARGIN_TOP);
if (l != null)
topInset = l.getValue();
l = (Length) as.getAttribute(CSS.Attribute.MARGIN_BOTTOM);
if (l != null)
bottomInset = l.getValue();
+ // Fetch padding.
+ l = (Length) as.getAttribute(CSS.Attribute.PADDING);
+ if (l != null)
+ {
+ leftPadding = rightPadding = topPadding = bottomPadding =
+ l.getValue();
+ }
+ l = (Length) as.getAttribute(CSS.Attribute.PADDING_LEFT);
+ if (l != null)
+ leftPadding = l.getValue();
+ l = (Length) as.getAttribute(CSS.Attribute.PADDING_RIGHT);
+ if (l != null)
+ rightPadding = l.getValue();
+ l = (Length) as.getAttribute(CSS.Attribute.PADDING_TOP);
+ if (l != null)
+ topPadding = l.getValue();
+ l = (Length) as.getAttribute(CSS.Attribute.PADDING_BOTTOM);
+ if (l != null)
+ bottomPadding = l.getValue();
+
// Determine border.
border = new CSSBorder(as);
// Determine background.
background = ss.getBackground(as);
}
/**
* Gets the inset needed on a given side to account for the margin, border
* and padding.
*
* @param size - the size of the box to get the inset for. View.TOP, View.LEFT,
* View.BOTTOM or View.RIGHT.
* @param v - the view making the request. This is used to get the AttributeSet,
* amd may be used to resolve percentage arguments.
* @return the inset
* @throws IllegalArgumentException - for an invalid direction.
*/
public float getInset(int size, View v)
{
float inset;
switch (size)
{
case View.TOP:
inset = topInset;
if (border != null)
inset += border.getBorderInsets(null).top;
+ inset += topPadding;
break;
case View.BOTTOM:
inset = bottomInset;
if (border != null)
inset += border.getBorderInsets(null).bottom;
+ inset += bottomPadding;
break;
case View.LEFT:
inset = leftInset;
if (border != null)
inset += border.getBorderInsets(null).left;
+ inset += leftPadding;
break;
case View.RIGHT:
inset = rightInset;
if (border != null)
inset += border.getBorderInsets(null).right;
+ inset += rightPadding;
break;
default:
inset = 0.0F;
}
return inset;
}
/**
* Paints the CSS box according to the attributes given. This should
* paint the border, padding and background.
*
* @param g - the graphics configuration
* @param x - the x coordinate
* @param y - the y coordinate
* @param w - the width of the allocated area
Index: javax/swing/text/html/TableView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/TableView.java,v
retrieving revision 1.6
diff -u -1 -5 -r1.6 TableView.java
--- javax/swing/text/html/TableView.java 14 Nov 2006 20:53:58 -0000 1.6
+++ javax/swing/text/html/TableView.java 15 Nov 2006 11:02:31 -0000
@@ -105,56 +105,59 @@
span = totalColumnRequirements.preferred;
else
span = super.getPreferredSpan(axis);
return span;
}
/**
* Calculates the overall size requirements for the row along the
* major axis. This will be the sum of the column requirements.
*/
protected SizeRequirements calculateMajorAxisRequirements(int axis,
SizeRequirements r)
{
if (r == null)
r = new SizeRequirements();
- r.minimum = totalColumnRequirements.minimum;
- r.preferred = totalColumnRequirements.preferred;
- r.maximum = totalColumnRequirements.maximum;
+ int adjust = (columnRequirements.length + 1) * cellSpacing;
+ r.minimum = totalColumnRequirements.minimum + adjust;
+ r.preferred = totalColumnRequirements.preferred + adjust;
+ r.maximum = totalColumnRequirements.maximum + adjust;
r.alignment = 0.0F;
return r;
}
/**
* Lays out the columns in this row.
*/
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
int spans[])
{
int numCols = offsets.length;
int realColumn = 0;
for (int i = 0; i < numCols; i++)
{
View v = getView(i);
if (v instanceof CellView)
{
CellView cv = (CellView) v;
offsets[i] = columnOffsets[realColumn];
spans[i] = 0;
for (int j = 0; j < cv.colSpan; j++, realColumn++)
{
spans[i] += columnSpans[realColumn];
+ if (j < cv.colSpan - 1)
+ spans[i] += cellSpacing;
}
}
}
}
}
/**
* A view that renders HTML table cells (TD and TH tags).
*/
class CellView
extends BlockView
{
/**
* The number of columns that this view spans.
@@ -199,32 +202,34 @@
// Couldn't parse the colspan, assume 1.
colSpan = 1;
}
}
}
}
/**
* The attributes of this view.
*/
private AttributeSet attributes;
/**
* The column requirements.
+ *
+ * Package private to avoid accessor methods.
*/
- private SizeRequirements[] columnRequirements;
+ SizeRequirements[] columnRequirements;
/**
* The overall requirements across all columns.
*
* Package private to avoid accessor methods.
*/
SizeRequirements totalColumnRequirements;
/**
* The column layout, offsets.
*
* Package private to avoid accessor methods.
*/
int[] columnOffsets;
@@ -234,30 +239,37 @@
* Package private to avoid accessor methods.
*/
int[] columnSpans;
/**
* The widths of the columns that have been explicitly specified.
*/
Length[] columnWidths;
/**
* Indicates if the grid setup is ok.
*/
private boolean gridValid;
/**
+ * Additional space that is added _between_ table cells.
+ *
+ * This is package private to avoid accessor methods.
+ */
+ int cellSpacing;
+
+ /**
* Creates a new HTML table view for the specified element.
*
* @param el the element for the table view
*/
public TableView(Element el)
{
super(el, Y_AXIS);
totalColumnRequirements = new SizeRequirements();
}
/**
* Implementation of the ViewFactory interface for creating the
* child views correctly.
*/
public View create(Element elem)
@@ -334,44 +346,51 @@
// Calculate the horizontal requirements according to the superclass.
// This will return the maximum of the row's widths.
r = super.calculateMinorAxisRequirements(axis, r);
// Try to set the CSS width if it fits.
AttributeSet atts = getAttributes();
Length l = (Length) atts.getAttribute(CSS.Attribute.WIDTH);
if (l != null)
{
int width = (int) l.getValue();
if (r.minimum < width)
r.minimum = width;
}
+ // Adjust requirements when we have cell spacing.
+ int adjust = (columnRequirements.length + 1) * cellSpacing;
+ r.minimum += adjust;
+ r.preferred += adjust;
+
// Apply the alignment.
Object o = atts.getAttribute(CSS.Attribute.TEXT_ALIGN);
r.alignment = 0.0F;
if (o != null)
{
String al = o.toString();
if (al.equals("left"))
r.alignment = 0.0F;
else if (al.equals("center"))
r.alignment = 0.5F;
else if (al.equals("right"))
r.alignment = 1.0F;
}
+ // Make it not resize in the horizontal direction.
+ r.maximum = r.preferred;
return r;
}
/**
* Overridden to perform the table layout before calling the super
* implementation.
*/
protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
int[] spans)
{
updateGrid();
layoutColumns(targetSpan);
super.layoutMinorAxis(targetSpan, axis, offsets, spans);
}
@@ -549,31 +568,33 @@
// Set the spans to the preferred sizes. Determine the space
// that we have to adjust the sizes afterwards.
long sumPref = 0;
int n = columnRequirements.length;
for (int i = 0; i < n; i++)
{
SizeRequirements col = columnRequirements[i];
if (columnWidths[i] != null)
columnSpans[i] = (int) columnWidths[i].getValue(targetSpan);
else
columnSpans[i] = col.preferred;
sumPref += columnSpans[i];
}
// Try to adjust the spans so that we fill the targetSpan.
- long diff = targetSpan - sumPref;
+ // For adjustments we have to use the targetSpan minus the cumulated
+ // cell spacings.
+ long diff = targetSpan - (n + 1) * cellSpacing - sumPref;
float factor = 0.0F;
int[] diffs = null;
if (diff != 0)
{
long total = 0;
diffs = new int[n];
for (int i = 0; i < n; i++)
{
// Only adjust the width if we haven't set a column width here.
if (columnWidths[i] == null)
{
SizeRequirements col = columnRequirements[i];
int span;
if (diff < 0)
{
@@ -586,42 +607,42 @@
diffs[i] = span - columnSpans[i];
}
total += span;
}
else
total += columnSpans[i];
}
float maxAdjust = Math.abs(total - sumPref);
factor = diff / maxAdjust;
factor = Math.min(factor, 1.0F);
factor = Math.max(factor, -1.0F);
}
// Actually perform adjustments.
- int totalOffs = 0;
+ int totalOffs = cellSpacing;
for (int i = 0; i < n; i++)
{
columnOffsets[i] = totalOffs;
if (diff != 0)
{
float adjust = factor * diffs[i];
columnSpans[i] += Math.round(adjust);
}
// Avoid overflow here.
- totalOffs = (int) Math.min((long) totalOffs + (long) columnSpans[i],
- Integer.MAX_VALUE);
+ totalOffs = (int) Math.min((long) totalOffs + (long) columnSpans[i]
+ + (long) cellSpacing, Integer.MAX_VALUE);
}
}
/**
* Updates the arrays that contain the row and column data in response
* to a change to the table structure.
*/
private void updateGrid()
{
if (! gridValid)
{
int maxColumns = 0;
int numRows = getViewCount();
for (int r = 0; r < numRows; r++)
{
@@ -660,16 +681,68 @@
}
}
/**
* Overridden to restrict the table width to the preferred size.
*/
public float getMaximumSpan(int axis)
{
float span;
if (axis == X_AXIS)
span = super.getPreferredSpan(axis);
else
span = super.getMaximumSpan(axis);
return span;
}
+
+ /**
+ * Overridden to fetch the CSS attributes when view gets connected.
+ */
+ public void setParent(View parent)
+ {
+ super.setParent(parent);
+ if (parent != null)
+ setPropertiesFromAttributes();
+ }
+
+ /**
+ * Fetches CSS and HTML layout attributes.
+ */
+ private void setPropertiesFromAttributes()
+ {
+ // Fetch and parse cell spacing.
+ Object o = getAttributes().getAttribute(CSS.Attribute.BORDER_SPACING);
+ if (o != null && o instanceof Length)
+ {
+ Length l = (Length) o;
+ cellSpacing = (int) l.getValue();
+ }
+ }
+
+ /**
+ * Overridden to adjust for cellSpacing.
+ */
+ protected SizeRequirements calculateMajorAxisRequirements(int axis,
+ SizeRequirements r)
+ {
+ r = super.calculateMajorAxisRequirements(axis, r);
+ int adjust = (getViewCount() + 1) * cellSpacing;
+ r.minimum += adjust;
+ r.preferred += adjust;
+ r.maximum += adjust;
+ return r;
+ }
+
+ /**
+ * Overridden to adjust for cellSpacing.
+ */
+ protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
+ int spans[])
+ {
+ int adjust = (getViewCount() + 1) * cellSpacing;
+ super.layoutMajorAxis(targetSpan - adjust, axis, offsets, spans);
+ for (int i = 0; i < offsets.length; i++)
+ {
+ offsets[i] += (i + 1) * cellSpacing;
+ }
+ }
}