diff options
Diffstat (limited to 'javax/swing/text/html/TableView.java')
-rw-r--r-- | javax/swing/text/html/TableView.java | 291 |
1 files changed, 216 insertions, 75 deletions
diff --git a/javax/swing/text/html/TableView.java b/javax/swing/text/html/TableView.java index 90b3ecc4f..f87d7b35f 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 @@ -80,8 +92,8 @@ class TableView public void replace(int offset, int len, View[] views) { - super.replace(offset, len, views); gridValid = false; + super.replace(offset, len, views); } /** @@ -137,26 +149,63 @@ 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++) + int colCount = getViewCount(); + for (int i = 0; i < numColumns;) { - View v = getView(i); - if (v instanceof CellView) + if (! overlap[i] && realColumn < colCount) { - 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 +224,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 +267,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 +324,11 @@ class TableView Length[] columnWidths; /** + * The total number of columns. + */ + int numColumns; + + /** * The table width. */ private Length width; @@ -263,7 +336,7 @@ class TableView /** * Indicates if the grid setup is ok. */ - boolean gridValid; + boolean gridValid = false; /** * Additional space that is added _between_ table cells. @@ -273,6 +346,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 +359,7 @@ class TableView { super(el, Y_AXIS); totalColumnRequirements = new SizeRequirements(); + tmpRect = new Rectangle(); } /** @@ -292,21 +371,20 @@ class TableView View view = null; AttributeSet atts = elem.getAttributes(); Object name = atts.getAttribute(StyleConstants.NameAttribute); - if (name instanceof HTML.Tag) - { - HTML.Tag tag = (HTML.Tag) name; - if (tag == HTML.Tag.TR) - view = new RowView(elem); - else if (tag == HTML.Tag.TD || tag == HTML.Tag.TH) - view = new CellView(elem); - else if (tag == HTML.Tag.CAPTION) - view = new ParagraphView(elem); - } - - // If we haven't mapped the element, then fall back to the standard - // view factory. - if (view == null) + AttributeSet pAtts = elem.getParentElement().getAttributes(); + Object pName = pAtts.getAttribute(StyleConstants.NameAttribute); + + if (name == HTML.Tag.TR && pName == HTML.Tag.TABLE) + view = new RowView(elem); + else if ((name == HTML.Tag.TD || name == HTML.Tag.TH) + && pName == HTML.Tag.TR) + view = new CellView(elem); + else if (name == HTML.Tag.CAPTION) + view = new ParagraphView(elem); + else { + // If we haven't mapped the element, then fall back to the standard + // view factory. View parent = getParent(); if (parent != null) { @@ -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,67 @@ 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; + int colCount = rowView.getViewCount(); + 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 if (colIndex < colCount) + { + 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++; + } + } + } + else { - columnWidths[colIndex]= (Length) o; - columnWidths[colIndex].setFontBases(emBase, exBase); + c++; } - colIndex += cv.colSpan; } } } @@ -752,8 +861,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 +905,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++) @@ -828,7 +949,27 @@ class TableView public void replace(int offset, int len, View[] views) { - super.replace(offset, len, views); gridValid = false; + super.replace(offset, len, views); } + + /** + * 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); + } + } + } |