I improved our HTML support a little, so that we now can render primitive
tables:
http://kennke.org/~roman/htmltable.png
Also, this fixes some minor bugs in the javax.swing.text package.
2006-03-03 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/text/DefaultStyledDocument.java
(ElementBuffer.inserUpdate): Added check for zero-length
element.
* javax/swing/text/DefaultStyledDocument.java
(setIndex): Improved exception message.
* javax/swing/text/TableView.java
Made class abstract.
(TableRow.replace): Probably extend columnRequirements
arrays.
(TableRow.layoutMinorAxis): Call super.layoutMinorAxis instead
of super.layoutMajorAxis.
(columnRequirements): Made field package private.
(TableView): Do not load any child views here.
(layoutColumns): Implemented this method.
(updateColumnRequirements): New helper method.
* javax/swing/text/Utilities.java
(getBreakLocation): Also take offset into account when
finding end location.
* javax/swing/text/html/HTMLDocument.java
(HTMLReader.parseStack): New field.
(HTMLReader.blockOpen): Properly handle p-implied tags.
(HTMLReader.blockClose): Properly handle p-implied and empty tags.
(HTMLReader.addContent): Insert p-implied when adding content to
a block element.
* javax/swing/text/html/HTMLEditorKit.java
(HTMLFactory.create): Create HTMLTableView for <table> tags and
ParagraphView for TD tags. Print out warning for tags that don't
have
matching view yet and create NullView for them.
(read): Only set document base when document != null.
* javax/swing/text/html/HTMLTableView.java:
New class
/Roman
Index: javax/swing/text/DefaultStyledDocument.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/DefaultStyledDocument.java,v
retrieving revision 1.64
diff -u -r1.64 DefaultStyledDocument.java
--- javax/swing/text/DefaultStyledDocument.java 1 Mar 2006 20:39:49 -0000 1.64
+++ javax/swing/text/DefaultStyledDocument.java 3 Mar 2006 10:46:19 -0000
@@ -814,7 +814,9 @@
if (data.length > i + 1)
{
// leaves will be added to paragraph later
- int x = paragraph.getElementIndex(pos) + 1;
+ int x = 0;
+ if (paragraph.getElementCount() > 0)
+ x = paragraph.getElementIndex(pos) + 1;
Edit e = getEditForParagraphAndIndex(paragraph, x);
br = (BranchElement) createBranchElement(paragraph,
data[i].getAttributes());
Index: javax/swing/text/Segment.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/Segment.java,v
retrieving revision 1.9
diff -u -r1.9 Segment.java
--- javax/swing/text/Segment.java 23 Jan 2006 16:59:45 -0000 1.9
+++ javax/swing/text/Segment.java 3 Mar 2006 10:46:19 -0000
@@ -243,7 +243,9 @@
{
if (position < getBeginIndex()
|| position > getEndIndex())
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("position: " + position
+ + ", beginIndex: " + getBeginIndex()
+ + ", endIndex: " + getEndIndex());
current = position;
Index: javax/swing/text/TableView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/TableView.java,v
retrieving revision 1.1
diff -u -r1.1 TableView.java
--- javax/swing/text/TableView.java 7 Jan 2006 17:52:37 -0000 1.1
+++ javax/swing/text/TableView.java 3 Mar 2006 10:46:19 -0000
@@ -54,7 +54,7 @@
*
* @author Roman Kennke ([EMAIL PROTECTED])
*/
-public class TableView
+public abstract class TableView
extends BoxView
{
@@ -90,6 +90,18 @@
public void replace(int offset, int length, View[] views)
{
super.replace(offset, length, views);
+ int viewCount = getViewCount();
+ if (columnRequirements == null
+ || viewCount > columnRequirements.length)
+ {
+ columnRequirements = new SizeRequirements[viewCount];
+ for (int i = 0; i < columnRequirements.length; i++)
+ columnRequirements[i] = new SizeRequirements();
+ }
+ if (columnOffsets == null || columnOffsets.length < viewCount)
+ columnOffsets = new int[viewCount];
+ if (columnSpans == null || columnSpans.length < viewCount)
+ columnSpans = new int[viewCount];
layoutChanged(X_AXIS);
}
@@ -108,8 +120,6 @@
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
int[] spans)
{
- // TODO: Maybe prepare columnSpans and columnOffsets.
-
// Some sanity checks. If these preconditions are not met, then the
// following code will not work. Also, there must be something
// seriously wrong then.
@@ -140,7 +150,7 @@
{
// FIXME: Figure out how to fetch the row heights from the TableView's
// element.
- super.layoutMajorAxis(targetSpan, axis, offsets, spans);
+ super.layoutMinorAxis(targetSpan, axis, offsets, spans);
}
/**
@@ -303,7 +313,7 @@
/**
* The size requirements of the columns.
*/
- private SizeRequirements[] columnRequirements;
+ SizeRequirements[] columnRequirements = new SizeRequirements[0];
/**
* Creates a new instance of <code>TableView</code>.
@@ -313,15 +323,6 @@
public TableView(Element el)
{
super(el, Y_AXIS);
- int numChildren = el.getElementCount();
- View[] rows = new View[numChildren];
- for (int i = 0; i < numChildren; ++i)
- {
- Element rowEl = el.getElement(i);
- TableRow rowView = createTableRow(rowEl);
- rows[i] = rowView;
- }
- replace(0, 0, rows);
}
/**
@@ -385,7 +386,10 @@
protected void layoutColumns(int targetSpan, int[] offsets, int spans[],
SizeRequirements[] reqs)
{
- // TODO: Figure out what exactly to do here.
+ updateColumnRequirements();
+ SizeRequirements r = calculateMinorAxisRequirements(X_AXIS, null);
+ SizeRequirements.calculateTiledPositions(targetSpan, r, columnRequirements,
+ offsets, spans);
}
/**
@@ -462,4 +466,26 @@
// and look for a range that contains the given position.
return super.getViewAtPosition(pos, a);
}
+
+ /**
+ * Updates the column requirements.
+ */
+ private void updateColumnRequirements()
+ {
+ int rowCount = getViewCount();
+ for (int r = 0; r < rowCount; ++r)
+ {
+ TableRow row = (TableRow) getView(r);
+ int columnCount = row.getViewCount();
+ for (int c = 0; c < columnCount; ++c)
+ {
+ View cell = row.getView(c);
+ SizeRequirements cr = columnRequirements[c];
+ cr.minimum = Math.max(cr.minimum, (int) cell.getMinimumSpan(X_AXIS));
+ cr.preferred = Math.max(cr.preferred,
+ (int) cell.getPreferredSpan(X_AXIS));
+ cr.maximum = Math.max(cr.maximum, (int) cell.getMaximumSpan(X_AXIS));
+ }
+ }
+ }
}
Index: javax/swing/text/Utilities.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/Utilities.java,v
retrieving revision 1.23
diff -u -r1.23 Utilities.java
--- javax/swing/text/Utilities.java 22 Feb 2006 11:17:52 -0000 1.23
+++ javax/swing/text/Utilities.java 3 Mar 2006 10:46:19 -0000
@@ -515,7 +515,7 @@
breaker.setText(s);
// If mark is equal to the end of the string, just use that position
- if (mark == s.count)
+ if (mark == s.count + s.offset)
return mark;
// Try to find a word boundary previous to the mark at which we
Index: javax/swing/text/html/HTMLDocument.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLDocument.java,v
retrieving revision 1.25
diff -u -r1.25 HTMLDocument.java
--- javax/swing/text/html/HTMLDocument.java 22 Feb 2006 08:34:07 -0000 1.25
+++ javax/swing/text/html/HTMLDocument.java 3 Mar 2006 10:46:19 -0000
@@ -563,7 +563,13 @@
/** A stack for character attribute sets **/
Stack charAttrStack = new Stack();
-
+
+ /**
+ * The parse stack. This stack holds HTML.Tag objects that reflect the
+ * current position in the parsing process.
+ */
+ private Stack parseStack = new Stack();
+
/** A mapping between HTML.Tag objects and the actions that handle them **/
HashMap tagToAction;
@@ -1286,6 +1292,18 @@
{
printBuffer();
DefaultStyledDocument.ElementSpec element;
+
+ // If the previous tag is content and the parent is p-implied, then
+ // we must also close the p-implied.
+ if (parseStack.size() > 0 && parseStack.peek() == HTML.Tag.IMPLIED)
+ {
+ element = new ElementSpec(null,
+ DefaultStyledDocument.ElementSpec.EndTagType);
+ parseBuffer.addElement(element);
+ parseStack.pop();
+ }
+
+ parseStack.push(t);
AbstractDocument.AttributeContext ctx = getAttributeContext();
AttributeSet copy = attr.copyAttributes();
copy = ctx.addAttribute(copy, StyleConstants.NameAttribute, t);
@@ -1305,10 +1323,37 @@
{
printBuffer();
DefaultStyledDocument.ElementSpec element;
+
+ // If the previous tag is a start tag then we insert a synthetic
+ // content tag.
+ ElementSpec prev = (ElementSpec) parseBuffer.get(parseBuffer.size() - 1);
+ if (prev.getType() == ElementSpec.StartTagType)
+ {
+ AbstractDocument.AttributeContext ctx = getAttributeContext();
+ AttributeSet attributes = ctx.getEmptySet();
+ attributes = ctx.addAttribute(attributes, StyleConstants.NameAttribute,
+ HTML.Tag.CONTENT);
+ element = new ElementSpec(attributes, ElementSpec.ContentType,
+ new char[0], 0, 0);
+ parseBuffer.add(element);
+ }
+ // If the previous tag is content and the parent is p-implied, then
+ // we must also close the p-implied.
+ else if (parseStack.peek() == HTML.Tag.IMPLIED)
+ {
+ element = new ElementSpec(null,
+ DefaultStyledDocument.ElementSpec.EndTagType);
+ parseBuffer.addElement(element);
+ if (parseStack.size() > 0)
+ parseStack.pop();
+ }
+
element = new DefaultStyledDocument.ElementSpec(null,
DefaultStyledDocument.ElementSpec.EndTagType);
parseBuffer.addElement(element);
printBuffer();
+ if (parseStack.size() > 0)
+ parseStack.pop();
}
/**
@@ -1337,17 +1382,38 @@
protected void addContent(char[] data, int offs, int length,
boolean generateImpliedPIfNecessary)
{
- // Copy the attribute set, don't use the same object because
- // it may change
AbstractDocument.AttributeContext ctx = getAttributeContext();
+ DefaultStyledDocument.ElementSpec element;
AttributeSet attributes = null;
+
+ // Content must always be embedded inside a paragraph element,
+ // so we create this if the previous element is not one of
+ // <p>, <h1> .. <h6>.
+ boolean createImpliedParagraph = false;
+ HTML.Tag parent = (HTML.Tag) parseStack.peek();
+ if (parent != HTML.Tag.P && parent != HTML.Tag.H1
+ && parent != HTML.Tag.H2
+ && parent != HTML.Tag.H3 && parent != HTML.Tag.H4
+ && parent != HTML.Tag.H5 && parent != HTML.Tag.H6
+ && parent != HTML.Tag.TD)
+ {
+ attributes = ctx.getEmptySet();
+ attributes = ctx.addAttribute(attributes,
+ StyleConstants.NameAttribute,
+ HTML.Tag.IMPLIED);
+ element = new ElementSpec(attributes, ElementSpec.StartTagType);
+ parseBuffer.add(element);
+ parseStack.push(HTML.Tag.IMPLIED);
+ }
+
+ // Copy the attribute set, don't use the same object because
+ // it may change
if (charAttr != null)
attributes = charAttr.copyAttributes();
else
attributes = ctx.getEmptySet();
attributes = ctx.addAttribute(attributes, StyleConstants.NameAttribute,
HTML.Tag.CONTENT);
- DefaultStyledDocument.ElementSpec element;
element = new DefaultStyledDocument.ElementSpec(attributes,
DefaultStyledDocument.ElementSpec.ContentType,
data, offs, length);
Index: javax/swing/text/html/HTMLEditorKit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLEditorKit.java,v
retrieving revision 1.25
diff -u -r1.25 HTMLEditorKit.java
--- javax/swing/text/html/HTMLEditorKit.java 21 Feb 2006 13:56:15 -0000 1.25
+++ javax/swing/text/html/HTMLEditorKit.java 3 Mar 2006 10:46:19 -0000
@@ -551,6 +551,10 @@
view = new InlineView(element);
else if (tag == HTML.Tag.HEAD)
view = new NullView(element);
+ else if (tag.equals(HTML.Tag.TABLE))
+ view = new HTMLTableView(element);
+ else if (tag.equals(HTML.Tag.TD))
+ view = new ParagraphView(element);
/*
else if (tag.equals(HTML.Tag.MENU) || tag.equals(HTML.Tag.DIR)
@@ -562,8 +566,6 @@
view = new HRuleView(element);
else if (tag.equals(HTML.Tag.BR))
view = new BRView(element);
- else if (tag.equals(HTML.Tag.TABLE))
- view = new TableView(element);
else if (tag.equals(HTML.Tag.INPUT) || tag.equals(HTML.Tag.SELECT)
|| tag.equals(HTML.Tag.TEXTAREA))
view = new FormView(element);
@@ -573,7 +575,12 @@
view = new FrameSetView(element);
else if (tag.equals(HTML.Tag.FRAME))
view = new FrameView(element); */
- }
+ }
+ if (view == null)
+ {
+ System.err.println("missing tag->view mapping for: " + element);
+ view = new NullView(element);
+ }
return view;
}
}
@@ -941,7 +948,8 @@
throw new IOException("Parser is null.");
HTMLDocument hd = ((HTMLDocument) doc);
- hd.setBase(editorPane.getPage());
+ if (editorPane != null)
+ hd.setBase(editorPane.getPage());
ParserCallback pc = hd.getReader(pos);
// FIXME: What should ignoreCharSet be set to?
Index: javax/swing/text/html/HTMLTableView.java
===================================================================
RCS file: javax/swing/text/html/HTMLTableView.java
diff -N javax/swing/text/html/HTMLTableView.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ javax/swing/text/html/HTMLTableView.java 3 Mar 2006 10:46:19 -0000
@@ -0,0 +1,82 @@
+/* HTMLTableView.java -- A table view for HTML tables
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text.html;
+
+import javax.swing.text.Element;
+import javax.swing.text.TableView;
+import javax.swing.text.View;
+import javax.swing.text.ViewFactory;
+
+/**
+ * A conrete implementation of TableView that renders HTML tables.
+ *
+ * @author Roman Kennke ([EMAIL PROTECTED])
+ */
+class HTMLTableView
+ extends TableView
+{
+
+ /**
+ * Creates a new HTMLTableView for the specified element.
+ *
+ * @param el the element for the table view
+ */
+ public HTMLTableView(Element el)
+ {
+ super(el);
+ }
+
+ /**
+ * Loads the children of the Table. This completely bypasses the ViewFactory
+ * and creates instances of TableRow instead.
+ *
+ * @param vf ignored
+ */
+ protected void loadChildren(ViewFactory vf)
+ {
+ Element el = getElement();
+ int numChildren = el.getElementCount();
+ View[] rows = new View[numChildren];
+ for (int i = 0; i < numChildren; ++i)
+ {
+ rows[i] = createTableRow(el.getElement(i));
+ }
+ replace(0, getViewCount(), rows);
+ }
+}