This fills out a hole in the HTMLEditorKit. Dunno really if that works,
only a naive basic implementation based on stuff that I made up in my
mind ;-) Gotta write a HTML _editor_ to actually try it out...

2006-11-15  Roman Kennke  <[EMAIL PROTECTED]>

        * javax/swing/text/html/HTMLEditorKit.java
        (InsertHTMLTextAction.actionPerformed): Also try inserting
        the alternate tag. Adjust the selection accordingly.
        (InsertHTMLTextAction.adjustSelection): New helper method.
        Adjusts the selection after an insertion.
        (insertAtBoundary): Delegate to deprecated method.
        (insertAtBoundry): Implemented missing method.
        (tryInsert): New helper method.
        (defaultActions): Implemented to fill the array with
        a couple of InsertHTMLTextActions.

/Roman
Index: javax/swing/text/html/HTMLEditorKit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLEditorKit.java,v
retrieving revision 1.40
diff -u -1 -5 -r1.40 HTMLEditorKit.java
--- javax/swing/text/html/HTMLEditorKit.java	8 Nov 2006 11:21:57 -0000	1.40
+++ javax/swing/text/html/HTMLEditorKit.java	15 Nov 2006 23:09:22 -0000
@@ -27,32 +27,30 @@
 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 gnu.classpath.NotImplementedException;
-
 import java.awt.event.ActionEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseMotionListener;
 import java.awt.Cursor;
 import java.awt.Point;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.Serializable;
 import java.io.StringReader;
 import java.io.Writer;
 import java.net.MalformedURLException;
@@ -278,31 +276,31 @@
       
       /**
        * Alternate tag to check if parentTag is not found.
        */
       protected HTML.Tag alternateParentTag;
       
       /**
        * HTML to insert.
        */
       protected String html;
       
       /**
        * Tag to check for in the document.
        */
       protected HTML.Tag parentTag;
-      
+
       /**
        * Initializes all fields.
        * 
        * @param name - the name of the document.
        * @param html - the html to insert
        * @param parentTag - the parent tag to check for
        * @param addTag - the tag to start adding from
        */
       public InsertHTMLTextAction(String name, String html, 
                                   HTML.Tag parentTag, HTML.Tag addTag)
       {
         this(name, html, parentTag, addTag, null, null);
       }
       
       /**
@@ -382,90 +380,202 @@
        *          where to begin inserting the HTML.
        * @param insertElement -
        *          the element to insert
        * @param html -
        *          the html to insert
        * @param parentTag -
        *          the parent tag
        * @param addTag -
        *          the first tag
        */
       protected void insertAtBoundary(JEditorPane editor,
                                       HTMLDocument doc, int offset,
                                       Element insertElement,
                                       String html, HTML.Tag parentTag,
                                       HTML.Tag addTag)
-        throws NotImplementedException
       {
-        /*
-        As its name implies, this protected method is used when HTML is inserted at a
-        boundary. (A boundary in this case is an offset in doc that exactly matches the
-        beginning offset of the parentTag.) It performs the extra work required to keep
-        the tag stack in shape and then calls insertHTML(). The editor and doc argu-
-        ments are the editor pane and document where the HTML should go. The offset
-        argument represents the cursor location or selection start in doc. The insert-
-        Element and parentTag arguments are used to calculate the proper number of
-        tag pops and pushes before inserting the HTML (via html and addTag, which are
-        passed directly to insertHTML()).
-        */
-        // FIXME: not implemented
+        insertAtBoundry(editor, doc, offset, insertElement,
+                        html, parentTag, addTag);
       }
       
       /**
        * Invoked when inserting at a boundary. Determines the number of pops, 
        * and then the number of pushes that need to be performed. The it calls
        * insertHTML.
        * 
        * @param editor - the editor to use to get the editorkit
        * @param doc -
        *          the Document to insert the HTML into.
        * @param offset -
        *          where to begin inserting the HTML.
        * @param insertElement - the element to insert
        * @param html - the html to insert
        * @param parentTag - the parent tag
        * @param addTag - the first tag
        * 
        * @deprecated as of v1.3, use insertAtBoundary
        */
       protected void insertAtBoundry(JEditorPane editor,
                                      HTMLDocument doc,
                                      int offset, Element insertElement,
                                      String html, HTML.Tag parentTag,
                                      HTML.Tag addTag)
       {
-        insertAtBoundary(editor, doc, offset, insertElement,
-                         html, parentTag, addTag);
+        Element parent = insertElement;
+        Element el;
+        // Find common parent element.
+        if (offset > 0 || insertElement == null)
+          {
+            el = doc.getDefaultRootElement();
+            while (el != null && el.getStartOffset() != offset
+                   && ! el.isLeaf())
+              el = el.getElement(el.getElementIndex(offset));
+            parent = el != null ? el.getParentElement() : null;
+          }
+        if (parent != null)
+          {
+            int pops = 0;
+            int pushes = 0;
+            if (offset == 0 && insertElement != null)
+              {
+                el = parent;
+                while (el != null && ! el.isLeaf())
+                  {
+                    el = el.getElement(el.getElementIndex(offset));
+                    pops++;
+                  }
+              }
+            else
+              {
+                el = parent;
+                offset--;
+                while (el != null && ! el.isLeaf())
+                  {
+                    el = el.getElement(el.getElementIndex(offset));
+                    pops++;
+                  }
+                el = parent;
+                offset++;
+                while (el != null && el != insertElement)
+                  {
+                    el = el.getElement(el.getElementIndex(offset));
+                    pushes++;
+                  }
+              }
+            pops = Math.max(0, pops - 1);
+            insertHTML(editor, doc, offset, html, pops, pushes, addTag);
+          }
       }
       
       /**
        * Inserts the HTML.
        * 
        * @param ae - the action performed
        */
       public void actionPerformed(ActionEvent ae)
       {
-        Object source = ae.getSource();
-        if (source instanceof JEditorPane)
+        JEditorPane source = getEditor(ae);
+        if (source != null)
           {
-            JEditorPane pane = ((JEditorPane) source);
-            Document d = pane.getDocument();
-            if (d instanceof HTMLDocument)
-              insertHTML(pane, (HTMLDocument) d, 0, html, 0, 0, addTag);
-            // FIXME: is this correct parameters?
+            HTMLDocument d = getHTMLDocument(source);
+            int offset = source.getSelectionStart();
+            int length = d.getLength();
+            boolean inserted = true;
+            if (! tryInsert(source, d, offset, parentTag, addTag))
+              {
+                inserted = tryInsert(source, d, offset, alternateParentTag,
+                                     alternateAddTag);
+              }
+            if (inserted)
+              adjustSelection(source, d, offset, length);
+          }
+      }
+
+      /**
+       * Tries to insert the html chunk to the specified <code>addTag</code>.
+       *
+       * @param pane the editor
+       * @param doc the document
+       * @param offset the offset at which to insert
+       * @param tag the tag at which to insert
+       * @param addTag the add tag
+       *
+       * @return <code>true</code> when the html has been inserted successfully,
+       *         <code>false</code> otherwise
+       */
+      private boolean tryInsert(JEditorPane pane, HTMLDocument doc, int offset,
+                                HTML.Tag tag, HTML.Tag addTag)
+      {
+        boolean inserted = false;
+        Element el = findElementMatchingTag(doc, offset, tag);
+        if (el != null && el.getStartOffset() == offset)
+          {
+            insertAtBoundary(pane, doc, offset, el, html, tag, addTag);
+            inserted = true;
+          }
+        else if (offset > 0)
+          {
+            int depth = elementCountToTag(doc, offset - 1, tag);
+            if (depth != -1)
+              {
+                insertHTML(pane, doc, offset, html, depth, 0, addTag);
+                inserted = true;
+              }
+          }
+        return inserted;
+      }
+
+      /**
+       * Adjusts the selection after an insertion has been performed.
+       *
+       * @param pane the editor pane
+       * @param doc the document
+       * @param offset the insert offset
+       * @param oldLen the old document length
+       */
+      private void adjustSelection(JEditorPane pane, HTMLDocument doc,
+                                   int offset, int oldLen)
+      {
+        int newLen = doc.getLength();
+        if (newLen != oldLen && offset < newLen)
+          {
+            if (offset > 0)
+              {
+                String text;
+                try
+                  {
+                    text = doc.getText(offset - 1, 1);
+                  }
+                catch (BadLocationException ex)
+                  {
+                    text = null;
+                  }
+                if (text != null && text.length() > 0
+                    && text.charAt(0) == '\n')
+                  {
+                    pane.select(offset, offset);
+                  }
+                else
+                  {
+                    pane.select(offset + 1, offset + 1);
+                  }
+              }
+            else
+              {
+                pane.select(1, 1);
+              }
           }
-        // FIXME: else not implemented
       }
   }
   
   /**
    * Abstract Action class that helps inserting HTML into an existing document.
    */
   public abstract static class HTMLTextAction
     extends StyledEditorKit.StyledTextAction
     {
       
       /**
        * Constructor
        */
       public HTMLTextAction(String name) 
       {
@@ -873,32 +983,60 @@
   public static final String LOGICAL_STYLE_ACTION = "html-logical-style-action";
 
   /**
    * The "ident paragraph left" action.
    */
   public static final String PARA_INDENT_LEFT = "html-para-indent-left";
 
   /**
    * The "ident paragraph right" action.
    */
   public static final String PARA_INDENT_RIGHT = "html-para-indent-right";
   
   /**
    * Actions for HTML 
    */
-  private static final Action[] defaultActions = {
-    // FIXME: Add default actions for html
+  private static final Action[] defaultActions =
+  {
+    new InsertHTMLTextAction("InsertTable",
+                             "<table border=1><tr><td></td></tr></table>",
+                             HTML.Tag.BODY, HTML.Tag.TABLE),
+    new InsertHTMLTextAction("InsertTableRow",
+                             "<table border=1><tr><td></td></tr></table>",
+                             HTML.Tag.TABLE, HTML.Tag.TR,
+                             HTML.Tag.BODY, HTML.Tag.TABLE),
+    new InsertHTMLTextAction("InsertTableCell",
+                             "<table border=1><tr><td></td></tr></table>",
+                             HTML.Tag.TR, HTML.Tag.TD,
+                             HTML.Tag.BODY, HTML.Tag.TABLE),
+    new InsertHTMLTextAction("InsertUnorderedList",
+                             "<ul><li></li></ul>",
+                             HTML.Tag.BODY, HTML.Tag.UL),
+    new InsertHTMLTextAction("InsertUnorderedListItem",
+                             "<ul><li></li></ul>",
+                             HTML.Tag.UL, HTML.Tag.LI,
+                             HTML.Tag.BODY, HTML.Tag.UL),
+    new InsertHTMLTextAction("InsertOrderedList",
+                             "<ol><li></li></ol>",
+                             HTML.Tag.BODY, HTML.Tag.OL),
+    new InsertHTMLTextAction("InsertOrderedListItem",
+                             "<ol><li></li></ol>",
+                             HTML.Tag.OL, HTML.Tag.LI,
+                             HTML.Tag.BODY, HTML.Tag.OL),
+    new InsertHTMLTextAction("InsertPre",
+                             "<pre></pre>", HTML.Tag.BODY, HTML.Tag.PRE)
+    // TODO: The reference impl has an InsertHRAction too.
   };
   
   /**
    * The current style sheet.
    */
   private StyleSheet styleSheet;
   
   /**
    * The ViewFactory for HTMLFactory.
    */
   HTMLFactory viewFactory;
   
   /**
    * The Cursor for links.
    */

Reply via email to