I hacked a little more on Swing text stuff and finally got my first little HTML application working:
http://kennke.org/~roman/html.png The sourcecode to this program is attached. I checked in the fixes as two commits: 2006-02-17 Roman Kennke <[EMAIL PROTECTED]> * javax/swing/text/html/HTMLEditorKit.java (HTMLFactory.create): Create InlineView for content tags. * javax/swing/text/html/HTMLDocument.java (HTMLReader.flush): Call create() on first flush and insert on subsequent flushes. 2006-02-17 Roman Kennke <[EMAIL PROTECTED]> * javax/swing/text/AbstractDocument.java (BranchElement.getStartOffset): Implemented workaround for wrong NPE. (BranchElement.getEndOffset): Implemented workaround for wrong NPE. (ElementBuffer.split): Use createBranchElement() instead of new BranchElement(). (ElementBuffer.insertFracture): Use createBranchElement() instead of new BranchElement(). (ElementBuffer.recreateAfterFracture): Use createBranchElement() instead of new BranchElement(). (createDefaultRoot): Use createBranchElement() and createLeafElement instead of the constructors. (create): Rewritten. /Roman
Index: javax/swing/text/html/HTMLDocument.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLDocument.java,v retrieving revision 1.21 diff -u -r1.21 HTMLDocument.java --- javax/swing/text/html/HTMLDocument.java 17 Feb 2006 10:36:34 -0000 1.21 +++ javax/swing/text/html/HTMLDocument.java 17 Feb 2006 14:58:20 -0000 @@ -1134,7 +1134,11 @@ elements = new DefaultStyledDocument.ElementSpec[parseBuffer.size()]; parseBuffer.copyInto(elements); parseBuffer.removeAllElements(); - insert(offset, elements); + if (offset == 0) + create(elements); + else + insert(offset, elements); + offset += HTMLDocument.this.getLength() - offset; } Index: javax/swing/text/html/HTMLEditorKit.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLEditorKit.java,v retrieving revision 1.23 diff -u -r1.23 HTMLEditorKit.java --- javax/swing/text/html/HTMLEditorKit.java 20 Dec 2005 15:59:45 -0000 1.23 +++ javax/swing/text/html/HTMLEditorKit.java 17 Feb 2006 14:58:20 -0000 @@ -553,8 +553,9 @@ view = new BlockView(element, View.Y_AXIS); // FIXME: Uncomment when the views have been implemented - /* else if (tag.equals(HTML.Tag.CONTENT)) - view = new InlineView(element); + else if (tag.equals(HTML.Tag.CONTENT)) + view = new InlineView(element); + /* else if (tag.equals(HTML.Tag.MENU) || tag.equals(HTML.Tag.DIR) || tag.equals(HTML.Tag.UL) || tag.equals(HTML.Tag.OL)) view = new ListView(element); Index: javax/swing/text/AbstractDocument.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/text/AbstractDocument.java,v retrieving revision 1.46 retrieving revision 1.47 diff -u -r1.46 -r1.47 --- javax/swing/text/AbstractDocument.java 13 Feb 2006 14:13:29 -0000 1.46 +++ javax/swing/text/AbstractDocument.java 17 Feb 2006 14:55:46 -0000 1.47 @@ -1707,9 +1707,12 @@ */ public int getEndOffset() { + int end = 0; if (getElementCount() == 0) - throw new NullPointerException("This BranchElement has no children."); - return children[children.length - 1].getEndOffset(); + end = getLength(); // FIXME: That ain't correct, fix it. + else + end = children[children.length - 1].getEndOffset(); + return end; } /** @@ -1734,9 +1737,12 @@ */ public int getStartOffset() { + int start = 0; if (getElementCount() == 0) - throw new NullPointerException("This BranchElement has no children."); - return children[0].getStartOffset(); + start = 0; // FIXME: That ain't correct, fix it. + else + start = children[0].getStartOffset(); + return start; } /** Index: javax/swing/text/DefaultStyledDocument.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/text/DefaultStyledDocument.java,v retrieving revision 1.61 retrieving revision 1.62 diff -u -r1.61 -r1.62 --- javax/swing/text/DefaultStyledDocument.java 13 Feb 2006 17:21:34 -0000 1.61 +++ javax/swing/text/DefaultStyledDocument.java 17 Feb 2006 14:55:46 -0000 1.62 @@ -1203,8 +1203,9 @@ edit.addRemovedElements(removed); edit.addAddedElements(added); - BranchElement newPar = (BranchElement) new BranchElement(el.getParentElement(), - el.getAttributes()); + BranchElement newPar = + (BranchElement) createBranchElement(el.getParentElement(), + el.getAttributes()); newPar.replace(0, 0, newAdded); res = new Element[] { null, newPar }; } @@ -1217,8 +1218,8 @@ Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex); edit.addRemovedElements(removed); - BranchElement newPar = (BranchElement) new BranchElement(el.getParentElement(), - el.getAttributes()); + BranchElement newPar = (BranchElement) createBranchElement(el.getParentElement(), + el.getAttributes()); newPar.replace(0, 0, removed); res = new Element[] { null, newPar }; @@ -1271,7 +1272,8 @@ { // recreate left-side of branch and all its children before offset // add the fractured leaves to the right branch - BranchElement rightBranch = new BranchElement(parent, parentAtts); + BranchElement rightBranch = + (BranchElement) createBranchElement(parent, parentAtts); // Check if left branch has already been edited. If so, we only // need to create the right branch. @@ -1286,7 +1288,8 @@ } else { - leftBranch = new BranchElement(parent, parentAtts); + leftBranch = + (BranchElement) createBranchElement(parent, parentAtts); added = new Element[] { leftBranch, rightBranch }; // add fracture to leftBranch @@ -1390,7 +1393,9 @@ startOffset, startOffset + len); else { - BranchElement br = new BranchElement(parent, curr.getAttributes()); + BranchElement br = + (BranchElement) createBranchElement(parent, + curr.getAttributes()); int bSize = curr.getElementCount(); for (int k = 0; k < bSize; k++) { @@ -1663,7 +1668,9 @@ */ private StyleChangeListener styleChangeListener; - /** Vector that contains all the edits. */ + /** + * Vector that contains all the edits. Maybe replace by a HashMap. + */ Vector edits = new Vector(); /** @@ -1741,12 +1748,13 @@ Element[] tmp; SectionElement section = new SectionElement(); - BranchElement paragraph = new BranchElement(section, null); + BranchElement paragraph = + (BranchElement) createBranchElement(section, null); tmp = new Element[1]; tmp[0] = paragraph; section.replace(0, 0, tmp); - LeafElement leaf = new LeafElement(paragraph, null, 0, 1); + Element leaf = createLeafElement(paragraph, null, 0, 1); tmp = new Element[1]; tmp[0] = leaf; paragraph.replace(0, 0, tmp); @@ -2342,14 +2350,59 @@ */ protected void create(ElementSpec[] data) { + writeLock(); try { - // Clear content. - content.remove(0, content.length()); - // Clear buffer and root element. - buffer = new ElementBuffer(createDefaultRoot()); - // Insert the data. - insert(0, data); + // Clear content if there is some. + int len = getLength(); + if (len > 0) + remove(0, len); + + // Now we insert the content. + StringBuilder b = new StringBuilder(); + for (int i = 0; i < data.length; ++i) + { + ElementSpec el = data[i]; + if (el.getArray() != null && el.getLength() > 0) + b.append(el.getArray(), el.getOffset(), el.getLength()); + } + Content content = getContent(); + UndoableEdit cEdit = content.insertString(0, b.toString()); + + DefaultDocumentEvent ev = + new DefaultDocumentEvent(0, b.length(), + DocumentEvent.EventType.INSERT); + ev.addEdit(cEdit); + + // We do a little trick here to get the new structure: We instantiate + // a new ElementBuffer with a new root element, insert into that root + // and then reparent the newly created elements to the old root + // element. + BranchElement createRoot = + (BranchElement) createBranchElement(null, null); + Element dummyLeaf = createLeafElement(createRoot, null, 0, 1); + createRoot.replace(0, 0, new Element[]{ dummyLeaf }); + ElementBuffer createBuffer = new ElementBuffer(createRoot); + createBuffer.insert(0, b.length(), data, new DefaultDocumentEvent(0, b.length(), DocumentEvent.EventType.INSERT)); + // Now the new root is the first child of the createRoot. + Element newRoot = createRoot.getElement(0); + BranchElement root = (BranchElement) getDefaultRootElement(); + Element[] added = new Element[newRoot.getElementCount()]; + for (int i = 0; i < added.length; ++i) + { + added[i] = newRoot.getElement(i); + ((AbstractElement) added[i]).element_parent = root; + } + Element[] removed = new Element[root.getElementCount()]; + for (int i = 0; i < removed.length; ++i) + removed[i] = root.getElement(i); + + // Replace the old elements in root with the new and update the event. + root.replace(0, removed.length, added); + ev.addEdit(new ElementEdit(root, 0, removed, added)); + + fireInsertUpdate(ev); + fireUndoableEditUpdate(new UndoableEditEvent(this, ev)); } catch (BadLocationException ex) { @@ -2357,5 +2410,9 @@ err.initCause(ex); throw err; } + finally + { + writeUnlock(); + } } }
import javax.swing.*; import javax.swing.text.html.*; public class HTMLTest extends JFrame { public HTMLTest() { super("HTMLTest"); JTextPane p = new JTextPane(); p.setEditorKit(new HTMLEditorKit()); p.setText("<html><body><h1>HTML Test</h1><p>Hello Classpath planet</p><p>This is the first working HTML program</p></body></html>"); getContentPane().add(p); } public static void main(String[] args) { HTMLTest t = new HTMLTest(); t.setSize(400, 300); t.setVisible(true); } }