diff options
author | Roman Kennke <roman@kennke.org> | 2006-12-05 21:52:51 +0000 |
---|---|---|
committer | Roman Kennke <roman@kennke.org> | 2006-12-05 21:52:51 +0000 |
commit | 04371cc4695e0e7d0eaba1a53ae4dc7afc4a4d9c (patch) | |
tree | 81cddcb5eb0ed69531a3cc65ca7d47977c9d1580 /javax | |
parent | 30a18f5e72b46f6d326367070426458473c244db (diff) | |
download | classpath-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.
Diffstat (limited to 'javax')
-rw-r--r-- | javax/swing/text/html/BlockView.java | 5 | ||||
-rw-r--r-- | javax/swing/text/html/StyleSheet.java | 34 | ||||
-rw-r--r-- | javax/swing/text/html/TableView.java | 262 |
3 files changed, 241 insertions, 60 deletions
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); + } } |