summaryrefslogtreecommitdiff
path: root/javax/swing/text/html/TableView.java
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2006-12-08 11:19:22 +0000
committerMark Wielaard <mark@klomp.org>2006-12-08 11:19:22 +0000
commitb77f88df258fa3ee1833555426a75a612b4fa9b4 (patch)
treebfe98f4fa2f33220577b9c4201629869c84a7398 /javax/swing/text/html/TableView.java
parent9ebb135b531c52db2ef1c254372a506b12e22a04 (diff)
downloadclasspath-b77f88df258fa3ee1833555426a75a612b4fa9b4.tar.gz
2006-12-05 Roman Kennke <kennke@aicas.com>
* javax/swing/text/html/ImageView.java (imageUpdate): Use spans field to determine if the CSS width/height are set. Call safePreferenceChanged to protect view structure from threading issues. (spans): Made package private. (ImageView): Initialize loadOnDemand with false. (loadImage): Call Toolkit.prepareImage() to make sure we have our Observer registered. (safePreferenceChanged): New helper method. Calls preferenceChanged in a thread safe environment. 2006-12-05 Roman Kennke <kennke@aicas.com> * NEWS: Add entry about improved HTML support. 2006-12-05 Roman Kennke <kennke@aicas.com> * javax/swing/text/html/ImageView.java (ImageView): Initialize spans array here. (setPropertiesFromAttributes): Moved init of spans array to constructor. 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> * javax/swing/text/html/HTMLEditorKit.java (HTMLFactory.create): Removed debug output. * javax/swing/text/html/InlineView.java (getBreakWeight): Likewise. * javax/swing/text/html/StyleSheet.java (addRule): Likewise. (ListPainter.paint): Removed debug output. 2006-12-06 Roman Kennke <kennke@aicas.com> * javax/swing/text/html/BlockView.java (getAlignment): Align blocks horizontally by the superclass. * javax/swing/text/html/HTMLEditorKit.java (HTMLFactory.create): Replace equals comparison by == for efficiency. Add mapping for misplaced tr, td and th tags. Include object mapping. * javax/swing/text/html/TableView.java (RowView.replace): Invalidate grid early. (gridValid): Initialize with false. (create): Only create RowView and CellView for correctly placed tags. Avoid unnecessary casts. (getAlignment): Removed. (replace): Invalidate grid early. 2006-12-06 Roman Kennke <kennke@aicas.com> * javax/swing/text/html/TableView.java (RowView.layoutMajorAxis): Check column index for invalid value. (updateGrid): Check column index for invalid value. 2006-12-06 Roman Kennke <kennke@aicas.com> * javax/swing/JEditorPane.java (getStream): Buffer the stream for efficiency. (setPage): Don't scroll the view at this point. * javax/swing/plaf/basic/BasicTextUI.java (RootView.paint): Call RootView's setSize to get synchronization. (RootView.setSize): Synchronize to prevent race in layout code. * javax/swing/text/AbstractDocument.java (notifyListeners): New field. (fireChangedUpdate): Track notifyListener field. (fireRemoveUpdate): Track notifyListener field. (fireIndertUpdate): Track notifyListener field. (writeLock): Check notifyListener and throw IllegalStateException. * javax/swing/text/View.java (preferenceChanged): Create local var for better thread safety and more efficiency. 2006-12-06 Roman Kennke <kennke@aicas.com> * examples/gnu/classpath/examples/icons/back.png, * examples/gnu/classpath/examples/icons/reload.png: New icons for the HTML browser. * examples/gnu/classpath/examples/swing/HtmlDemo.java (history): New field. Manages the browsing history. (HtmlDemo): Initialize history. (createContent): Set location and add history. Add toolbar. (createToolBar): New helper method. (main): Make default size bigger. * examples/gnu/classpath/examples/swing/frame1.html, * examples/gnu/classpath/examples/swing/frame2.html, * examples/gnu/classpath/examples/swing/frame3.html, * examples/gnu/classpath/examples/swing/frame4.html, * examples/gnu/classpath/examples/swing/frames.html, * examples/gnu/classpath/examples/swing/tables.html: New example pages. * examples/gnu/classpath/examples/swing/welcome.html Add a couple of links and new test pages. 2006-12-06 Roman Kennke <kennke@aicas.com> * examples/gnu/classpath/examples/swing/Demo.java (getIcon): Made package private. * examples/gnu/classpath/examples/swing/HtmlDemo.java (hyperlinkUpdate): Convert URL to string. 2006-12-06 Roman Kennke <kennke@aicas.com> * javax/swing/text/DefaultCaret.java (appear): Adjust visibility here. (setDotImpl): Don't adjust visibility here. (moveDotImpl): Don't adjust visibility here. 2006-12-06 Roman Kennke <kennke@aicas.com> * javax/swing/text/html/FormView.java (SubmitThread.postData): Implemented. (SubmitThread.run): Pass data to postData(). (actionPerformed): Reset form when reset button is activated. (createComponent): Add support for select lists and comboboxes. Don't set value of text and password fields here, this is done now in HTMLDocument for consistency. (getElementFormData): Add support for fetching form data from select lists and comboboxes as well as textareas. (getSelectData): New helper method. Fetches form data from select boxes. (getTextAreaData): New helper method. Fetches form data from textareas. (resetForm): New helper method. Resets the entire form. * javax/swing/text/html/HTMLDocument.java (HTMLReader.FormAction.end): Handle SELECT and OPTION tags. (HTMLReader.FormAction.start): Handle SELECT and OPTION tags. (HTMLReader.FormAction.setModel): Initialize text and password values here. Also, use the resetable special models. Group radio buttons into ButtonGroup for exclusive selection. (HTMLReader.FormTagAction): New class. Handles FORM tags. (HTMLReader.buttonGroups): New field. (HTMLReader.numOptions): New field. (HTMLReader.option): New field. (HTMLReader.selectModel): New field. (HTMLReader.textAreaDocument): Make ResetablePlainDocument. (HTMLReader.handleText): Handle OPTION text. (HTMLReader.initTags): Map FORM tags to FormTagAction. (HTMLReader.textAreaContent): Set initial content. * javax/swing/text/html/Option.java (Option): Make copy of attribute set. Initialize selected state. (getValue): Fetch value from attribute set. * javax/swing/text/html/ResetableModel.java: New interface. * javax/swing/text/html/ResetablePlainDocument.java: New class. Supports resetting the state. * javax/swing/text/html/ResetableToggleButtonModel.java: Likewise. * javax/swing/text/html/SelectComboBoxModel.java: Likewise. * javax/swing/text/html/SelectListModel.java: Likewise. 2006-12-06 Roman Kennke <kennke@aicas.com> * examples/gnu/classpath/examples/swing/BrowserEditorKit.java: New class. * examples/gnu/classpath/examples/swing/HtmlDemo.java (LoadActionListener): Call setPage() helper method. (createContent): Register tweaked editor kit. For FormSubmitEvents call submitForm(), otherwise setPage(). (postData): Helper method for posting form data. (setPage): Helper method for navigating to a new URL. (submitForm): Helper method for submitting a form. * examples/gnu/classpath/examples/swing/forms.html: Added text/password fields and select boxes. * examples/gnu/classpath/examples/swing/welcome.html: Fixed typo. 2006-12-07 Mark Wielaard <mark@klomp.org> * java/net/URL.java (URL(URL,String,URLStreamHandler,boolean)): New private constructor. (URL(URL,String,URLStreamHandler)): Call new constructor. (URL(URL,String)): Likewise. (URL(String)): Likewise. 2006-12-07 Mark Wielaard <mark@klomp.org> * javax/swing/JEditorPane.java (createEditorKitForContentType): Always load from system class loader.
Diffstat (limited to 'javax/swing/text/html/TableView.java')
-rw-r--r--javax/swing/text/html/TableView.java291
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);
+ }
+ }
+
}