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);
+  }
+}

Reply via email to