summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Kennke <roman@kennke.org>2006-12-05 21:52:51 +0000
committerRoman Kennke <roman@kennke.org>2006-12-05 21:52:51 +0000
commit04371cc4695e0e7d0eaba1a53ae4dc7afc4a4d9c (patch)
tree81cddcb5eb0ed69531a3cc65ca7d47977c9d1580
parent30a18f5e72b46f6d326367070426458473c244db (diff)
downloadclasspath-04371cc4695e0e7d0eaba1a53ae4dc7afc4a4d9c.tar.gz
2006-12-05 Roman Kennke <kennke@aicas.com>
* javax/swing/text/html/BlockView.java (painter): Made package visible. * javax/swing/text/html/StyleSheet.java (translateBorder): New helper method. (translateHTMLToCSS): Add mappings for border attributes. * javax/swing/text/html/TableView.java Made class subclass of BlockView to get CSS goodness. (CellView.rowSpan): New field. (CellView.setPropertiesFromAttributes): Fetch rowspan. (RowView.overlap): New field. (RowView.rowIndex): New field. (RowView.layoutMajorAxis): Skip overlapping cells. (RowView.layoutMinorAxis): Layout cells that span more than 1 row. (numColumns): New field. (tmpRect): New field. (TableView): Initialize tmpRect. (calculateColumnRequirements): Adjusted and fixed for multirows. (getAlignment): Overridden to center tables. (paint): Overridden to fix clipping. (getStyleSheet): Made protected. (layoutMajorAxis): Invalidate rows. (setPropertiesFromAttributes): Made protected and call super. (updateGrid): Update the overlapping information for multirows.
-rw-r--r--ChangeLog26
-rw-r--r--javax/swing/text/html/BlockView.java5
-rw-r--r--javax/swing/text/html/StyleSheet.java34
-rw-r--r--javax/swing/text/html/TableView.java262
4 files changed, 267 insertions, 60 deletions
diff --git a/ChangeLog b/ChangeLog
index 3a43653a5..c85c6c553 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,31 @@
2006-12-05 Roman Kennke <kennke@aicas.com>
+ * javax/swing/text/html/BlockView.java
+ (painter): Made package visible.
+ * javax/swing/text/html/StyleSheet.java
+ (translateBorder): New helper method.
+ (translateHTMLToCSS): Add mappings for border attributes.
+ * javax/swing/text/html/TableView.java
+ Made class subclass of BlockView to get CSS goodness.
+ (CellView.rowSpan): New field.
+ (CellView.setPropertiesFromAttributes): Fetch rowspan.
+ (RowView.overlap): New field.
+ (RowView.rowIndex): New field.
+ (RowView.layoutMajorAxis): Skip overlapping cells.
+ (RowView.layoutMinorAxis): Layout cells that span more than 1 row.
+ (numColumns): New field.
+ (tmpRect): New field.
+ (TableView): Initialize tmpRect.
+ (calculateColumnRequirements): Adjusted and fixed for multirows.
+ (getAlignment): Overridden to center tables.
+ (paint): Overridden to fix clipping.
+ (getStyleSheet): Made protected.
+ (layoutMajorAxis): Invalidate rows.
+ (setPropertiesFromAttributes): Made protected and call super.
+ (updateGrid): Update the overlapping information for multirows.
+
+2006-12-05 Roman Kennke <kennke@aicas.com>
+
* gnu/java/awt/peer/gtk/AsyncImage.java
(addObserver): Check for null and ignore null observers.
(getWidth): Check for null and ignore null observers.
diff --git a/javax/swing/text/html/BlockView.java b/javax/swing/text/html/BlockView.java
index 9e4d9310d..1fc29cd68 100644
--- a/javax/swing/text/html/BlockView.java
+++ b/javax/swing/text/html/BlockView.java
@@ -40,7 +40,6 @@ package javax.swing.text.html;
import gnu.javax.swing.text.html.css.Length;
-import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
@@ -142,8 +141,10 @@ public class BlockView extends BoxView
/**
* The box painter for this view.
+ *
+ * This is package private because the TableView needs access to it.
*/
- private StyleSheet.BoxPainter painter;
+ StyleSheet.BoxPainter painter;
/**
* The width and height as specified in the stylesheet, null if not
diff --git a/javax/swing/text/html/StyleSheet.java b/javax/swing/text/html/StyleSheet.java
index acc14e73e..450f31da1 100644
--- a/javax/swing/text/html/StyleSheet.java
+++ b/javax/swing/text/html/StyleSheet.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.swing.text.html;
+import gnu.javax.swing.text.html.css.BorderWidth;
import gnu.javax.swing.text.html.css.CSSColor;
import gnu.javax.swing.text.html.css.CSSParser;
import gnu.javax.swing.text.html.css.CSSParserCallback;
@@ -760,12 +761,45 @@ public class StyleSheet extends StyleContext
cssAttr = addAttribute(cssAttr, CSS.Attribute.PADDING_RIGHT, l);
cssAttr = addAttribute(cssAttr, CSS.Attribute.PADDING_TOP, l);
}
+ o = tableAttrs.getAttribute(HTML.Attribute.BORDER);
+ cssAttr = translateBorder(cssAttr, o);
}
+
+ // Translate border attribute.
+ o = cssAttr.getAttribute(HTML.Attribute.BORDER);
+ cssAttr = translateBorder(cssAttr, o);
+
// TODO: Add more mappings.
return cssAttr;
}
/**
+ * Translates a HTML border attribute to a corresponding set of CSS
+ * attributes.
+ *
+ * @param cssAttr the original set of CSS attributes to add to
+ * @param o the value of the border attribute
+ *
+ * @return the new set of CSS attributes
+ */
+ private AttributeSet translateBorder(AttributeSet cssAttr, Object o)
+ {
+ if (o != null)
+ {
+ BorderWidth l = new BorderWidth(o.toString());
+ if (l.getValue() > 0)
+ {
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.BORDER_WIDTH, l);
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.BORDER_STYLE,
+ "solid");
+ cssAttr = addAttribute(cssAttr, CSS.Attribute.BORDER_COLOR,
+ new CSSColor("black"));
+ }
+ }
+ 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
diff --git a/javax/swing/text/html/TableView.java b/javax/swing/text/html/TableView.java
index 90b3ecc4f..b4e9bad4f 100644
--- a/javax/swing/text/html/TableView.java
+++ b/javax/swing/text/html/TableView.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.text.html;
+import java.awt.Graphics;
+import java.awt.Rectangle;
import java.awt.Shape;
import gnu.javax.swing.text.html.css.Length;
@@ -45,7 +47,6 @@ import gnu.javax.swing.text.html.css.Length;
import javax.swing.SizeRequirements;
import javax.swing.event.DocumentEvent;
import javax.swing.text.AttributeSet;
-import javax.swing.text.BoxView;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;
import javax.swing.text.View;
@@ -58,7 +59,7 @@ import javax.swing.text.ViewFactory;
* and the rows are horizontal BoxViews that contain the actual columns.
*/
class TableView
- extends BoxView
+ extends BlockView
implements ViewFactory
{
@@ -69,6 +70,17 @@ class TableView
extends BlockView
{
/**
+ * Has true at column positions where an above row's cell overlaps into
+ * this row.
+ */
+ boolean[] overlap;
+
+ /**
+ * Stores the row index of this row.
+ */
+ int rowIndex;
+
+ /**
* Creates a new RowView.
*
* @param el the element for the row view
@@ -137,26 +149,62 @@ class TableView
/**
* Lays out the columns in this row.
*/
+ protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
+ int spans[])
+ {
+ super.layoutMinorAxis(targetSpan, axis, offsets, spans);
+
+ // Adjust columns that have rowSpan > 1.
+ int numCols = getViewCount();
+ for (int i = 0; i < numCols; i++)
+ {
+ View v = getView(i);
+ if (v instanceof CellView)
+ {
+ CellView cell = (CellView) v;
+ if (cell.rowSpan > 1)
+ {
+ for (int r = 1; r < cell.rowSpan; r++)
+ {
+ spans[i] += TableView.this.getSpan(axis, rowIndex + r);
+ spans[i] += cellSpacing;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Lays out the columns in this row.
+ */
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
int spans[])
{
updateGrid();
int numCols = offsets.length;
int realColumn = 0;
- for (int i = 0; i < numCols; i++)
+ for (int i = 0; i < numColumns;)
{
- View v = getView(i);
- if (v instanceof CellView)
+ if (! overlap[i])
{
- CellView cv = (CellView) v;
- offsets[i] = columnOffsets[realColumn];
- spans[i] = 0;
- for (int j = 0; j < cv.colSpan; j++, realColumn++)
+ View v = getView(realColumn);
+ if (v instanceof CellView)
{
- spans[i] += columnSpans[realColumn];
- if (j < cv.colSpan - 1)
- spans[i] += cellSpacing;
+ CellView cv = (CellView) v;
+ offsets[realColumn] = columnOffsets[i];
+ spans[realColumn] = 0;
+ for (int j = 0; j < cv.colSpan; j++, i++)
+ {
+ spans[realColumn] += columnSpans[i];
+ if (j < cv.colSpan - 1)
+ spans[realColumn] += cellSpacing;
+ }
}
+ realColumn++;
+ }
+ else
+ {
+ i++;
}
}
}
@@ -175,6 +223,11 @@ class TableView
int colSpan;
/**
+ * The number of rows that this cell spans.
+ */
+ int rowSpan;
+
+ /**
* Creates a new CellView for the specified element.
*
* @param el the element for which to create the colspan
@@ -213,6 +266,20 @@ class TableView
colSpan = 1;
}
}
+ rowSpan = 1;
+ o = atts.getAttribute(HTML.Attribute.ROWSPAN);
+ if (o != null)
+ {
+ try
+ {
+ rowSpan = Integer.parseInt(o.toString());
+ }
+ catch (NumberFormatException ex)
+ {
+ // Couldn't parse the colspan, assume 1.
+ rowSpan = 1;
+ }
+ }
}
}
@@ -256,6 +323,11 @@ class TableView
Length[] columnWidths;
/**
+ * The total number of columns.
+ */
+ int numColumns;
+
+ /**
* The table width.
*/
private Length width;
@@ -273,6 +345,11 @@ class TableView
int cellSpacing;
/**
+ * A cached Rectangle object for reuse in paint().
+ */
+ private Rectangle tmpRect;
+
+ /**
* Creates a new HTML table view for the specified element.
*
* @param el the element for the table view
@@ -281,6 +358,7 @@ class TableView
{
super(el, Y_AXIS);
totalColumnRequirements = new SizeRequirements();
+ tmpRect = new Rectangle();
}
/**
@@ -343,7 +421,7 @@ class TableView
*
* @return the stylesheet associated with this view
*/
- private StyleSheet getStyleSheet()
+ protected StyleSheet getStyleSheet()
{
HTMLDocument doc = (HTMLDocument) getDocument();
return doc.getStyleSheet();
@@ -405,7 +483,8 @@ class TableView
{
updateGrid();
- // Mark all rows as invalid.
+ // Mark all rows as invalid along their minor axis to force correct
+ // layout of multi-row cells.
int n = getViewCount();
for (int i = 0; i < n; i++)
{
@@ -446,7 +525,8 @@ class TableView
SizeRequirements total = new SizeRequirements();
SizeRequirements relTotal = new SizeRequirements();
float totalPercent = 0.F;
- for (int c = 0; c < numCols; )
+ int realCol = 0;
+ for (int c = 0; c < numCols; c++)
{
View v = rowView.getView(c);
if (v instanceof CellView)
@@ -463,7 +543,7 @@ class TableView
long currentMax = 0;
for (int i = 0; i < colSpan; i++)
{
- SizeRequirements req = columnRequirements[c + i];
+ SizeRequirements req = columnRequirements[realCol];
currentMin += req.minimum;
currentPref += req.preferred;
currentMax += req.maximum;
@@ -474,15 +554,15 @@ class TableView
// Distribute delta.
for (int i = 0; i < colSpan; i++)
{
- SizeRequirements req = columnRequirements[c + i];
+ SizeRequirements req = columnRequirements[realCol];
if (deltaMin > 0)
req.minimum += deltaMin / colSpan;
if (deltaPref > 0)
req.preferred += deltaPref / colSpan;
if (deltaMax > 0)
req.maximum += deltaMax / colSpan;
- if (columnWidths[c + i] == null
- || ! columnWidths[c + i].isPercentage())
+ if (columnWidths[realCol] == null
+ || ! columnWidths[realCol].isPercentage())
{
total.minimum += req.minimum;
total.preferred += req.preferred;
@@ -493,35 +573,37 @@ class TableView
relTotal.minimum =
Math.max(relTotal.minimum,
(int) (req.minimum
- * columnWidths[c + i].getValue()));
+ * columnWidths[realCol].getValue()));
relTotal.preferred =
Math.max(relTotal.preferred,
(int) (req.preferred
- * columnWidths[c + i].getValue()));
+ * columnWidths[realCol].getValue()));
relTotal.maximum =
Math.max(relTotal.maximum,
(int) (req.maximum
- * columnWidths[c + i].getValue()));
- totalPercent += columnWidths[c + i].getValue();
+ * columnWidths[realCol].getValue()));
+ totalPercent += columnWidths[realCol].getValue();
}
}
+ realCol += colSpan;
}
else
{
// Shortcut for colSpan == 1.
- SizeRequirements req = columnRequirements[c];
+ SizeRequirements req = columnRequirements[realCol];
req.minimum = Math.max(req.minimum,
- (int) cellView.getMinimumSpan(X_AXIS));
+ (int) cellView.getMinimumSpan(X_AXIS));
req.preferred = Math.max(req.preferred,
- (int) cellView.getPreferredSpan(X_AXIS));
+ (int) cellView.getPreferredSpan(X_AXIS));
req.maximum = Math.max(req.maximum,
- (int) cellView.getMaximumSpan(X_AXIS));
- if (columnWidths[c] == null
- || ! columnWidths[c].isPercentage())
+ (int) cellView.getMaximumSpan(X_AXIS));
+ if (columnWidths[realCol] == null
+ || ! columnWidths[realCol].isPercentage())
{
- total.minimum += columnRequirements[c].minimum;
- total.preferred += columnRequirements[c].preferred;
- total.maximum += columnRequirements[c].maximum;
+ total.minimum += columnRequirements[realCol].minimum;
+ total.preferred +=
+ columnRequirements[realCol].preferred;
+ total.maximum += columnRequirements[realCol].maximum;
}
else
{
@@ -539,11 +621,9 @@ class TableView
/ columnWidths[c].getValue()));
totalPercent += columnWidths[c].getValue();
}
+ realCol += 1;
}
- c += colSpan;
}
- else
- c++;
}
// Update the total requirements as follows:
@@ -681,38 +761,62 @@ class TableView
for (int r = 0; r < numRows; r++)
{
View rowView = getView(r);
- int numCols;
+ int numCols = 0;
if (rowView instanceof RowView)
- numCols = ((RowView) rowView).getViewCount();
- else
- numCols = 0;
+ {
+ int numCells = ((RowView) rowView).getViewCount();
+ for (int i = 0; i < numCells; i++)
+ {
+ View v = rowView.getView(i);
+ if (v instanceof CellView)
+ numCols += ((CellView) v).colSpan;
+ }
+ }
maxColumns = Math.max(numCols, maxColumns);
}
+ numColumns = maxColumns;
columnWidths = new Length[maxColumns];
+ int[] rowSpans = new int[maxColumns];
for (int r = 0; r < numRows; r++)
{
- View rowView = getView(r);
- int numCols;
- if (rowView instanceof RowView)
- numCols = ((RowView) rowView).getViewCount();
- else
- numCols = 0;
- int colIndex = 0;
- for (int c = 0; c < numCols; c++)
+ View view = getView(r);
+ if (view instanceof RowView)
{
- View v = rowView.getView(c);
- if (v instanceof CellView)
+ RowView rowView = (RowView) view;
+ rowView.rowIndex = r;
+ rowView.overlap = new boolean[maxColumns];
+ int colIndex = 0;
+ for (int c = 0; c < maxColumns;)
{
- CellView cv = (CellView) v;
- Object o =
- cv.getAttributes().getAttribute(CSS.Attribute.WIDTH);
- if (o != null && columnWidths[colIndex] == null
- && o instanceof Length)
+ if (rowSpans[c] > 0)
+ {
+ rowSpans[c]--;
+ rowView.overlap[c] = true;
+ c++;
+ }
+ else
{
- columnWidths[colIndex]= (Length) o;
- columnWidths[colIndex].setFontBases(emBase, exBase);
+ View v = rowView.getView(colIndex);
+ colIndex++;
+ if (v instanceof CellView)
+ {
+ CellView cv = (CellView) v;
+ Object o =
+ cv.getAttributes().getAttribute(CSS.Attribute.WIDTH);
+ if (o != null && columnWidths[c] == null
+ && o instanceof Length)
+ {
+ columnWidths[c]= (Length) o;
+ columnWidths[c].setFontBases(emBase, exBase);
+ }
+ int rs = cv.rowSpan - 1;
+ for (int col = cv.colSpan - 1; col >= 0; col--)
+ {
+ rowSpans[c] = rs;
+ c++;
+ }
+ }
}
- colIndex += cv.colSpan;
}
}
}
@@ -752,8 +856,10 @@ class TableView
/**
* Fetches CSS and HTML layout attributes.
*/
- private void setPropertiesFromAttributes()
+ protected void setPropertiesFromAttributes()
{
+ super.setPropertiesFromAttributes();
+
// Fetch and parse cell spacing.
AttributeSet atts = getAttributes();
StyleSheet ss = getStyleSheet();
@@ -794,6 +900,16 @@ class TableView
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
int spans[])
{
+ // Mark all rows as invalid along their minor axis to force correct
+ // layout of multi-row cells.
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View row = getView(i);
+ if (row instanceof RowView)
+ ((RowView) row).layoutChanged(axis);
+ }
+
int adjust = (getViewCount() + 1) * cellSpacing;
super.layoutMajorAxis(targetSpan - adjust, axis, offsets, spans);
for (int i = 0; i < offsets.length; i++)
@@ -831,4 +947,34 @@ class TableView
super.replace(offset, len, views);
gridValid = false;
}
+
+ /**
+ * We can't use the super class's paint() method because it might cut
+ * off multi-row children. Instead we trigger painting for all rows
+ * and let the rows sort out what to paint and what not.
+ */
+ public void paint(Graphics g, Shape a)
+ {
+ Rectangle rect = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
+ painter.paint(g, rect.x, rect.y, rect.width, rect.height, this);
+ int nRows = getViewCount();
+ Rectangle inside = getInsideAllocation(a);
+ for (int r = 0; r < nRows; r++)
+ {
+ tmpRect.setBounds(inside);
+ childAllocation(r, tmpRect);
+ paintChild(g, tmpRect, r);
+ }
+ }
+
+ /**
+ * Overridden to place a table centered in the horizontal direction.
+ */
+ public float getAlignment(int axis)
+ {
+ if (axis == X_AXIS)
+ return 0.5F;
+ else
+ return super.getAlignment(axis);
+ }
}