This patch implements the following:

- Submit forms with POST method.
- Resetting of form data.
- Radio buttons are put in button groups for exclusive selection
support.

2006-12-06  Roman Kennke  <[EMAIL PROTECTED]>

        * 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.

/Roman

Index: javax/swing/text/html/FormView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/FormView.java,v
retrieving revision 1.6
diff -u -1 -5 -r1.6 FormView.java
--- javax/swing/text/html/FormView.java	30 Nov 2006 19:38:04 -0000	1.6
+++ javax/swing/text/html/FormView.java	7 Dec 2006 14:41:52 -0000
@@ -33,46 +33,50 @@
 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 java.awt.Component;
 import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLEncoder;
 
 import javax.swing.ButtonModel;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
 import javax.swing.JEditorPane;
+import javax.swing.JList;
 import javax.swing.JPasswordField;
 import javax.swing.JRadioButton;
 import javax.swing.JScrollPane;
 import javax.swing.JTextArea;
 import javax.swing.JTextField;
-import javax.swing.JToggleButton;
+import javax.swing.ListSelectionModel;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.BadLocationException;
 import javax.swing.text.ComponentView;
 import javax.swing.text.Document;
 import javax.swing.text.Element;
 import javax.swing.text.ElementIterator;
 import javax.swing.text.StyleConstants;
 
 /**
  * A View that renders HTML form elements like buttons and input fields.
  * This is implemented as a [EMAIL PROTECTED] ComponentView} that creates different Swing
  * component depending on the type and setting of the different form elements.
@@ -153,31 +157,31 @@
           final String target = getTarget();
           URLConnection conn;
           final JEditorPane editor = (JEditorPane) getContainer();
           final HTMLDocument doc = (HTMLDocument) editor.getDocument();
           HTMLEditorKit kit = (HTMLEditorKit) editor.getEditorKit();
           if (kit.isAutoFormSubmission())
             {
               try
                 {
                   final URL url;
                   if (method != null && method.equals("post"))
                     {
                       // Perform POST.
                       url = actionURL;
                       conn = url.openConnection();
-                      postData(conn);
+                      postData(conn, data);
                     }
                   else
                     {
                       // Default to GET.
                       url = new URL(actionURL + "?" + data);
                     }
                   Runnable loadDoc = new Runnable()
                   {
                     public void run()
                     {
                       if (doc.isFrameDocument())
                         {
                           editor.fireHyperlinkUpdate(createSubmitEvent(method,
                                                                      actionURL,
                                                                      target));
@@ -273,33 +277,50 @@
         {
           target = (String) formAtts.getAttribute(HTML.Attribute.TARGET);
           if (target != null)
             target = target.toLowerCase();
         }
       if (target == null)
         target = "_self";
       return target;
     }
 
     /**
      * Posts the form data over the specified connection.
      *
      * @param conn the connection
      */
-    private void postData(URLConnection conn)
+    private void postData(URLConnection conn, String data)
     {
-      // TODO: Implement.
+      conn.setDoOutput(true);
+      PrintWriter out = null;
+      try
+        {
+          out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream()));
+          out.print(data);
+          out.flush();
+        }
+      catch (IOException ex)
+        {
+          // Deal with this!
+          ex.printStackTrace();
+        }
+      finally
+        {
+          if (out != null)
+            out.close();
+        }
     }
 
     /**
      * Determines the attributes from the relevant form tag.
      *
      * @return the attributes from the relevant form tag, <code>null</code>
      *         when there is no form tag
      */
     private AttributeSet getFormAttributes()
     {
       AttributeSet atts = null;
       Element form = getFormElement();
       if (form != null)
         atts = form.getAttributes();
       return atts;
@@ -378,39 +399,39 @@
         String type = (String) atts.getAttribute(HTML.Attribute.TYPE);
         if (type.equals("button"))
           {
             String value = (String) atts.getAttribute(HTML.Attribute.VALUE);
             JButton b = new JButton(value);
             if (model != null)
               {
                 b.setModel((ButtonModel) model);
                 b.addActionListener(this);
               }
             comp = b;
             maxIsPreferred = true;
           }
         else if (type.equals("checkbox"))
           {
-            JCheckBox c = new JCheckBox();
-            if (model != null)
+            if (model instanceof ResetableToggleButtonModel)
               {
-                boolean sel = atts.getAttribute(HTML.Attribute.CHECKED) != null;
-                ((JToggleButton.ToggleButtonModel) model).setSelected(sel);
-                c.setModel((ButtonModel) model);
+                ResetableToggleButtonModel m =
+                  (ResetableToggleButtonModel) model;
+                JCheckBox c = new JCheckBox();
+                c.setModel(m);
+                comp = c;
+                maxIsPreferred = true;
               }
-            comp = c;
-            maxIsPreferred = true;
           }
         else if (type.equals("image"))
           {
             String src = (String) atts.getAttribute(HTML.Attribute.SRC);
             JButton b;
             try
               {
                 URL base = ((HTMLDocument) el.getDocument()).getBase();
                 URL srcURL = new URL(base, src);
                 ImageIcon icon = new ImageIcon(srcURL);
                 b = new JButton(icon);
               }
             catch (MalformedURLException ex)
               {
                 b = new JButton(src);
@@ -422,48 +443,45 @@
               }
             comp = b;
             maxIsPreferred = true;
           }
         else if (type.equals("password"))
           {
             int size = HTML.getIntegerAttributeValue(atts, HTML.Attribute.SIZE,
                                                      -1);
             JTextField tf = new JPasswordField();
             if (size > 0)
               tf.setColumns(size);
             else
               tf.setColumns(20);
             if (model != null)
               tf.setDocument((Document) model);
-            String value = (String) atts.getAttribute(HTML.Attribute.VALUE);
-            if (value != null)
-              tf.setText(value);
             tf.addActionListener(this);
             comp = tf;
             maxIsPreferred = true;
           }
         else if (type.equals("radio"))
           {
-            JRadioButton c = new JRadioButton();
-            if (model != null)
+            if (model instanceof ResetableToggleButtonModel)
               {
-                boolean sel = atts.getAttribute(HTML.Attribute.CHECKED) != null;
-                ((JToggleButton.ToggleButtonModel) model).setSelected(sel);
-                c.setModel((ButtonModel) model);
+                ResetableToggleButtonModel m =
+                  (ResetableToggleButtonModel) model;
+                JRadioButton c = new JRadioButton();
+                c.setModel(m);
+                comp = c;
+                maxIsPreferred = true;
               }
-            comp = c;
-            maxIsPreferred = true;
           }
         else if (type.equals("reset"))
           {
             String value = (String) atts.getAttribute(HTML.Attribute.VALUE);
             if (value == null)
               value = UIManager.getString("FormView.resetButtonText");
             JButton b = new JButton(value);
             if (model != null)
               {
                 b.setModel((ButtonModel) model);
                 b.addActionListener(this);
               }
             comp = b;
             maxIsPreferred = true;
           }
@@ -480,51 +498,66 @@
               }
             comp = b;
             maxIsPreferred = true;
           }
         else if (type.equals("text"))
           {
             int size = HTML.getIntegerAttributeValue(atts, HTML.Attribute.SIZE,
                                                      -1);
             JTextField tf = new JTextField();
             if (size > 0)
               tf.setColumns(size);
             else
               tf.setColumns(20);
             if (model != null)
               tf.setDocument((Document) model);
-            String value = (String) atts.getAttribute(HTML.Attribute.VALUE);
-            if (value != null)
-              tf.setText(value);
             tf.addActionListener(this);
             comp = tf;
             maxIsPreferred = true;
           }
       }
     else if (tag == HTML.Tag.TEXTAREA)
       {
         JTextArea textArea = new JTextArea((Document) model);
         int rows = HTML.getIntegerAttributeValue(atts, HTML.Attribute.ROWS, 1);
         textArea.setRows(rows);
         int cols = HTML.getIntegerAttributeValue(atts, HTML.Attribute.COLS, 20);
         textArea.setColumns(cols);
         maxIsPreferred = true;
         comp = new JScrollPane(textArea,
                                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
       }
-    // FIXME: Implement the remaining components.
+    else if (tag == HTML.Tag.SELECT)
+      {
+        if (model instanceof SelectListModel)
+          {
+            SelectListModel slModel = (SelectListModel) model;
+            JList list = new JList(slModel);
+            int size = HTML.getIntegerAttributeValue(atts, HTML.Attribute.SIZE,
+                                                     1);
+            list.setVisibleRowCount(size);
+            list.setSelectionModel(slModel.getSelectionModel());
+            comp = new JScrollPane(list);
+          }
+        else if (model instanceof SelectComboBoxModel)
+          {
+            SelectComboBoxModel scbModel = (SelectComboBoxModel) model;
+            comp = new JComboBox(scbModel);
+          }
+        maxIsPreferred = true;
+      }
     return comp;
   }
 
   /**
    * Determines the maximum span for this view on the specified axis.
    *
    * @param axis the axis along which to determine the span
    *
    * @return the maximum span for this view on the specified axis
    *
    * @throws IllegalArgumentException if the axis is invalid
    */
   public float getMaximumSpan(int axis)
   {
     float span;
@@ -545,30 +578,32 @@
    * unless this text/password field is the last one, in which case the form
    * is submitted.
    *
    * @param ev the action event
    */
   public void actionPerformed(ActionEvent ev)
   {
     Element el = getElement();
     Object tag = el.getAttributes().getAttribute(StyleConstants.NameAttribute);
     if (tag.equals(HTML.Tag.INPUT))
       {
         AttributeSet atts = el.getAttributes();
         String type = (String) atts.getAttribute(HTML.Attribute.TYPE);
         if (type.equals("submit"))
           submitData(getFormData());
+        else if (type.equals("reset"))
+          resetForm();
       }
     // FIXME: Implement the remaining actions.
   }
 
   /**
    * Submits the form data. A separate thread is created to do the
    * transmission.
    *
    * @param data the form data
    */
   protected void submitData(String data)
   {
     SubmitThread submitThread = new SubmitThread(data);
     submitThread.start();
   }
@@ -668,41 +703,107 @@
   /**
    * Fetches the form data from the specified element and appends it to
    * the data string.
    *
    * @param el the element from which to fetch form data
    * @param b the data string
    */
   private void getElementFormData(Element el, StringBuilder b)
   {
     AttributeSet atts = el.getAttributes();
     String name = (String) atts.getAttribute(HTML.Attribute.NAME);
     if (name != null)
       {
         String value = null;
         HTML.Tag tag = (HTML.Tag) atts.getAttribute(StyleConstants.NameAttribute);
-        if (tag == HTML.Tag.INPUT)
-          value = getInputFormData(atts);
-        // TODO:  Implement textarea and select.
-        if (name != null && value != null)
+        if (tag == HTML.Tag.SELECT)
+          {
+            getSelectData(atts, b);
+          }
+        else
           {
-            addData(b, name, value);
+            if (tag == HTML.Tag.INPUT)
+              value = getInputFormData(atts);
+            else if (tag == HTML.Tag.TEXTAREA)
+              value = getTextAreaData(atts);
+            if (name != null && value != null)
+              {
+                addData(b, name, value);
+              }
           }
       }
   }
 
   /**
+   * Fetches form data from select boxes.
+   *
+   * @param atts the attributes of the element
+   *
+   * @param b the form data string to append to
+   */
+  private void getSelectData(AttributeSet atts, StringBuilder b)
+  {
+    String name = (String) atts.getAttribute(HTML.Attribute.NAME);
+    if (name != null)
+      {
+        Object m = atts.getAttribute(StyleConstants.ModelAttribute);
+        if (m instanceof SelectListModel)
+          {
+            SelectListModel sl = (SelectListModel) m;
+            ListSelectionModel lsm = sl.getSelectionModel();
+            for (int i = 0; i < sl.getSize(); i++)
+              {
+                if (lsm.isSelectedIndex(i))
+                  {
+                    Option o = (Option) sl.getElementAt(i);
+                    addData(b, name, o.getValue());
+                  }
+              }
+          }
+        else if (m instanceof SelectComboBoxModel)
+          {
+            SelectComboBoxModel scb = (SelectComboBoxModel) m;
+            Option o = (Option) scb.getSelectedItem();
+            if (o != null)
+              addData(b, name, o.getValue());
+          }
+      }
+  }
+
+  /**
+   * Fetches form data from a textarea.
+   *
+   * @param atts the attributes
+   *
+   * @return the form data
+   */
+  private String getTextAreaData(AttributeSet atts)
+  {
+    Document doc = (Document) atts.getAttribute(StyleConstants.ModelAttribute);
+    String data;
+    try
+      {
+        data = doc.getText(0, doc.getLength());
+      }
+    catch (BadLocationException ex)
+      {
+        data = null;
+      }
+    return data;
+  }
+
+  /**
    * Fetches form data from an input tag.
    *
    * @param atts the attributes from which to fetch the data
    *
    * @return the field value
    */
   private String getInputFormData(AttributeSet atts)
   {
     String type = (String) atts.getAttribute(HTML.Attribute.TYPE);
     Object model = atts.getAttribute(StyleConstants.ModelAttribute);
     String value = null;
     if (type.equals("text") || type.equals("password"))
       {
         Document doc = (Document) model;
         try
@@ -731,16 +832,39 @@
    *
    * @param b the string at which the form data to be added
    * @param name the name of the field
    * @param value the value
    */
   private void addData(StringBuilder b, String name, String value)
   {
     if (b.length() > 0)
       b.append('&');
     String encName = URLEncoder.encode(name);
     b.append(encName);
     b.append('=');
     String encValue = URLEncoder.encode(value);
     b.append(encValue);
   }
+
+  /**
+   * Resets the form data to their initial state.
+   */
+  private void resetForm()
+  {
+    Element form = getFormElement();
+    if (form != null)
+      {
+        ElementIterator iter = new ElementIterator(form);
+        Element next;
+        while ((next = iter.next()) != null)
+          {
+            if (next.isLeaf())
+              {
+                AttributeSet atts = next.getAttributes();
+                Object m = atts.getAttribute(StyleConstants.ModelAttribute);
+                if (m instanceof ResetableModel)
+                  ((ResetableModel) m).reset();
+              }
+          }
+      }
+  }
 }
Index: javax/swing/text/html/HTMLDocument.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLDocument.java,v
retrieving revision 1.56
diff -u -1 -5 -r1.56 HTMLDocument.java
--- javax/swing/text/html/HTMLDocument.java	1 Dec 2006 23:20:28 -0000	1.56
+++ javax/swing/text/html/HTMLDocument.java	7 Dec 2006 14:41:53 -0000
@@ -37,40 +37,40 @@
 
 
 package javax.swing.text.html;
 
 import gnu.classpath.NotImplementedException;
 
 import java.io.IOException;
 import java.io.StringReader;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Stack;
 import java.util.Vector;
 
+import javax.swing.ButtonGroup;
 import javax.swing.DefaultButtonModel;
 import javax.swing.JEditorPane;
-import javax.swing.JToggleButton;
+import javax.swing.ListSelectionModel;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.UndoableEditEvent;
 import javax.swing.text.AbstractDocument;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.BadLocationException;
 import javax.swing.text.DefaultStyledDocument;
-import javax.swing.text.Document;
 import javax.swing.text.Element;
 import javax.swing.text.ElementIterator;
 import javax.swing.text.GapContent;
 import javax.swing.text.MutableAttributeSet;
 import javax.swing.text.PlainDocument;
 import javax.swing.text.SimpleAttributeSet;
 import javax.swing.text.StyleConstants;
 import javax.swing.text.html.HTML.Tag;
 
 /**
  * Represents the HTML document that is constructed by defining the text and
  * other components (images, buttons, etc) in HTML language. This class can
  * becomes the default document for [EMAIL PROTECTED] JEditorPane} after setting its
  * content type to "text/html". HTML document also serves as an intermediate
  * data structure when it is needed to parse HTML and then obtain the content of
@@ -717,31 +717,52 @@
      */
     boolean inTextArea = false;
 
     /**
      * This contains all stylesheets that are somehow read, either
      * via embedded style tags, or via linked stylesheets. The
      * elements will be String objects containing a stylesheet each.
      */
     ArrayList styles;
 
     /**
      * The document model for a textarea.
      *
      * This is package private to avoid accessor methods.
      */
-    Document textAreaDocument;
+    ResetablePlainDocument textAreaDocument;
+
+    /**
+     * The current model of a select tag. Can be a ComboBoxModel or a
+     * ListModel depending on the type of the select box.
+     */
+    Object selectModel;
+
+    /**
+     * The current option beeing read.
+     */
+    Option option;
+
+    /**
+     * The current number of options in the current select model.
+     */
+    int numOptions;
+
+    /**
+     * The current button groups mappings.
+     */
+    HashMap buttonGroups;
 
     /**
      * The token threshold. This gets increased while loading.
      */
     private int threshold;
 
     public class TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.  By default this does nothing.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
       {
         // Nothing to do here.
@@ -822,86 +843,190 @@
       public void start(HTML.Tag t, MutableAttributeSet a)
       {
         if (t == HTML.Tag.INPUT)
           {
             String type = (String) a.getAttribute(HTML.Attribute.TYPE);
             if (type == null)
               {
                 type = "text"; // Default to 'text' when nothing was specified.
                 a.addAttribute(HTML.Attribute.TYPE, type);
               }
             setModel(type, a);
           }
         else if (t == HTML.Tag.TEXTAREA)
           {
             inTextArea = true;
-            textAreaDocument = new PlainDocument();
+            textAreaDocument = new ResetablePlainDocument();
             a.addAttribute(StyleConstants.ModelAttribute, textAreaDocument);
           }
-        // TODO: Handle select and option tags.
-
-        // Build the element.
-        super.start(t, a);
+        else if (t == HTML.Tag.SELECT)
+          {
+            int size = HTML.getIntegerAttributeValue(a, HTML.Attribute.SIZE,
+                                                     1);
+            boolean multi = a.getAttribute(HTML.Attribute.MULTIPLE) != null;
+            if (size > 1 || multi)
+              {
+                SelectListModel m = new SelectListModel();
+                if (multi)
+                  m.getSelectionModel().setSelectionMode(ListSelectionModel
+                                                 .MULTIPLE_INTERVAL_SELECTION);
+                selectModel = m;
+              }
+            else
+              {
+                selectModel = new SelectComboBoxModel();
+              }
+            a.addAttribute(StyleConstants.ModelAttribute, selectModel);
+          }
+        if (t == HTML.Tag.OPTION)
+          {
+            option = new Option(a);
+            if (selectModel instanceof SelectListModel)
+              {
+                SelectListModel m = (SelectListModel) selectModel;
+                m.addElement(option);
+                if (option.isSelected())
+                  {
+                    m.getSelectionModel().addSelectionInterval(numOptions,
+                                                               numOptions);
+                    m.addInitialSelection(numOptions);
+                  }
+              }
+            else if (selectModel instanceof SelectComboBoxModel)
+              {
+                SelectComboBoxModel m = (SelectComboBoxModel) selectModel;
+                m.addElement(option);
+                if (option.isSelected())
+                  {
+                    m.setSelectedItem(option);
+                    m.setInitialSelection(option);
+                  }
+              }
+            numOptions++;
+          }
+        else
+          {
+            // Build the element.
+            super.start(t, a);
+          }
       }
       
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
       {
-        if (t == HTML.Tag.TEXTAREA)
+        if (t == HTML.Tag.OPTION)
           {
-            inTextArea = false;
+            option = null;
+          }
+        else
+          {
+            if (t == HTML.Tag.TEXTAREA)
+              {
+                inTextArea = false;
+              }
+            else if (t == HTML.Tag.SELECT)
+              {
+                selectModel = null;
+                numOptions = 0;
+              }
+            // Finish the element.
+            super.end(t);
           }
-
-        // TODO: Handle select and option tags.
-
-        // Finish the element.
-        super.end(t);
       }
 
       private void setModel(String type, MutableAttributeSet attrs)
       {
         if (type.equals("submit") || type.equals("reset")
             || type.equals("image"))
           {
             // Create button.
             attrs.addAttribute(StyleConstants.ModelAttribute,
                                new DefaultButtonModel());
           }
         else if (type.equals("text") || type.equals("password"))
           {
-            // TODO: Handle fixed length input fields.
-            attrs.addAttribute(StyleConstants.ModelAttribute,
-                               new PlainDocument());
+            String text = (String) attrs.getAttribute(HTML.Attribute.VALUE);
+            ResetablePlainDocument doc = new ResetablePlainDocument();
+            if (text != null)
+              {
+                doc.setInitialText(text);
+                try
+                  {
+                    doc.insertString(0, text, null);
+                  }
+                catch (BadLocationException ex)
+                  {
+                    // Shouldn't happen.
+                    assert false;
+                  }
+              }
+            attrs.addAttribute(StyleConstants.ModelAttribute, doc);
           }
         else if (type.equals("file"))
           {
             attrs.addAttribute(StyleConstants.ModelAttribute,
                                new PlainDocument());
           }
         else if (type.equals("checkbox") || type.equals("radio"))
           {
-            JToggleButton.ToggleButtonModel model =
-              new JToggleButton.ToggleButtonModel();
-            // TODO: Handle radio button via ButtonGroups.
+            ResetableToggleButtonModel model =
+              new ResetableToggleButtonModel();
+            if (attrs.getAttribute(HTML.Attribute.SELECTED) != null)
+              {
+                model.setSelected(true);
+                model.setInitial(true);
+              }
+            if (type.equals("radio"))
+              {
+                String name = (String) attrs.getAttribute(HTML.Attribute.NAME);
+                if (name != null)
+                  {
+                    if (buttonGroups == null)
+                      buttonGroups = new HashMap();
+                    ButtonGroup group = (ButtonGroup) buttonGroups.get(name);
+                    if (group == null)
+                      {
+                        group = new ButtonGroup();
+                        buttonGroups.put(name, group);
+                      }
+                    model.setGroup(group);
+                  }
+              }
             attrs.addAttribute(StyleConstants.ModelAttribute, model);
           }
       }
     }
-    
+
+    /**
+     * Called for form tags.
+     */
+    class FormTagAction
+      extends BlockAction
+    {
+      /**
+       * Clears the button group mapping.
+       */
+      public void end(HTML.Tag t)
+      {
+        super.end(t);
+        buttonGroups = null;
+      } 
+    }
+
     /**
      * This action indicates that the content between starting and closing HTML
      * elements (like script - /script) should not be visible. The content is
      * still inserted and can be accessed when iterating the HTML document. The
      * parser will only fire
      * [EMAIL PROTECTED] javax.swing.text.html.HTMLEditorKit.ParserCallback#handleText} for
      * the hidden tags, regardless from that html tags the hidden section may
      * contain.
      */
     public class HiddenAction
         extends TagAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
@@ -1315,31 +1440,31 @@
       tagToAction.put(HTML.Tag.BLOCKQUOTE, blockAction);
       tagToAction.put(HTML.Tag.BODY, blockAction);
       tagToAction.put(HTML.Tag.BR, specialAction);
       tagToAction.put(HTML.Tag.CAPTION, blockAction);
       tagToAction.put(HTML.Tag.CENTER, blockAction);
       tagToAction.put(HTML.Tag.CITE, characterAction);
       tagToAction.put(HTML.Tag.CODE, characterAction);
       tagToAction.put(HTML.Tag.DD, blockAction);
       tagToAction.put(HTML.Tag.DFN, characterAction);
       tagToAction.put(HTML.Tag.DIR, blockAction);
       tagToAction.put(HTML.Tag.DIV, blockAction);
       tagToAction.put(HTML.Tag.DL, blockAction);
       tagToAction.put(HTML.Tag.DT, paragraphAction);
       tagToAction.put(HTML.Tag.EM, characterAction);
       tagToAction.put(HTML.Tag.FONT, convertAction);
-      tagToAction.put(HTML.Tag.FORM, blockAction);
+      tagToAction.put(HTML.Tag.FORM, new FormTagAction());
       tagToAction.put(HTML.Tag.FRAME, specialAction);
       tagToAction.put(HTML.Tag.FRAMESET, blockAction);
       tagToAction.put(HTML.Tag.H1, paragraphAction);
       tagToAction.put(HTML.Tag.H2, paragraphAction);
       tagToAction.put(HTML.Tag.H3, paragraphAction);
       tagToAction.put(HTML.Tag.H4, paragraphAction);
       tagToAction.put(HTML.Tag.H5, paragraphAction);
       tagToAction.put(HTML.Tag.H6, paragraphAction);
       tagToAction.put(HTML.Tag.HEAD, headAction);
       tagToAction.put(HTML.Tag.HR, specialAction);
       tagToAction.put(HTML.Tag.HTML, blockAction);
       tagToAction.put(HTML.Tag.I, characterAction);
       tagToAction.put(HTML.Tag.IMG, specialAction);
       tagToAction.put(HTML.Tag.INPUT, formAction);
       tagToAction.put(HTML.Tag.ISINDEX, isindexAction);
@@ -1442,30 +1567,32 @@
     /**
      * This method is called by the parser to indicate a block of 
      * text was encountered.  Should insert the text appropriately.
      * 
      * @param data the text that was inserted
      * @param pos the position at which the text was inserted
      */
     public void handleText(char[] data, int pos)
     {
       if (shouldInsert() && data != null && data.length > 0)
         {
           if (inTextArea)
             textAreaContent(data);
           else if (inPreTag)
             preContent(data);
+          else if (option != null)
+            option.setLabel(new String(data));
           else if (inStyleTag)
             {
               if (styles == null)
                 styles = new ArrayList();
               styles.add(new String(data));
             }
           else
             addContent(data, 0, data.length);
             
         }
     }
     
     /**
      * Checks if the HTML tag should be inserted. The tags before insert tag (if
      * specified) are not inserted. Also, the tags after the end of the html are
@@ -1576,31 +1703,33 @@
     {
       // FIXME: Implement.
     }
     
     /**
      * Adds the given text to the textarea document.  Called only when we are
      * within a textarea.  
      * 
      * @param data the text to add to the textarea
      */
     protected void textAreaContent(char[] data)
     {
       try
         {
           int offset = textAreaDocument.getLength();
-          textAreaDocument.insertString(offset, new String(data), null);
+          String text = new String(data);
+          textAreaDocument.setInitialText(text);
+          textAreaDocument.insertString(offset, text, null);
         }
       catch (BadLocationException ex)
         {
           // Must not happen as we insert at a model location that we
           // got from the document itself.
           assert false;
         }
     }
     
     /**
      * Adds the given text that was encountered in a <PRE> element.
      * This adds synthesized lines to hold the text runs.
      *
      * @param data the text
      */
Index: javax/swing/text/html/Option.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/Option.java,v
retrieving revision 1.1
diff -u -1 -5 -r1.1 Option.java
--- javax/swing/text/html/Option.java	20 Feb 2006 15:52:57 -0000	1.1
+++ javax/swing/text/html/Option.java	7 Dec 2006 14:41:53 -0000
@@ -60,34 +60,34 @@
   private String label;
 
   /**
    * The selected state of this label.
    */
   private boolean selected;
 
   /**
    * Creates a new <code>Option</code> instance that uses the specified
    * tag attributes.
    *
    * @param attr the attributes to use
    */
   public Option(AttributeSet attr)
   {
-    attributes = attr;
+    // Protect the attribute set.
+    attributes = attr.copyAttributes();
     label = null;
-    selected = false;
-    // FIXME: Probably initialize something using the attributes.
+    selected = attr.getAttribute(HTML.Attribute.SELECTED) != null;
   }
 
   /**
    * Sets the label to use for this <code>&lt;option&gt;</code> tag.
    *
    * @param l the label to set
    */
   public void setLabel(String l)
   {
     label = l;
   }
 
   /**
    * Returns the label of this <code>&lt;option&gt;</code> tag.
    *
@@ -139,19 +139,21 @@
    */
   public boolean isSelected()
   {
     return selected;
   }
 
   /**
    * Returns the string associated with the <code>value</code> attribute or
    * the label, if no such attribute is specified.
    *
    * @return the string associated with the <code>value</code> attribute or
    *         the label, if no such attribute is specified
    */
   public String getValue()
   {
-    // FIXME: Return some attribute here if specified.
-    return label;
+    String value = (String) attributes.getAttribute(HTML.Attribute.VALUE);
+    if (value == null)
+      value = label;
+    return value;
   }
 }
Index: javax/swing/text/html/ResetableModel.java
===================================================================
RCS file: javax/swing/text/html/ResetableModel.java
diff -N javax/swing/text/html/ResetableModel.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ javax/swing/text/html/ResetableModel.java	7 Dec 2006 14:41:53 -0000
@@ -0,0 +1,50 @@
+/* ResetableModel.java -- Form models that can be resetted
+   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;
+
+/**
+ * Form models that can be resetted implement this.
+ */
+interface ResetableModel
+{
+  /**
+   * Resets the model.
+   */
+  void reset();
+}
Index: javax/swing/text/html/ResetablePlainDocument.java
===================================================================
RCS file: javax/swing/text/html/ResetablePlainDocument.java
diff -N javax/swing/text/html/ResetablePlainDocument.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ javax/swing/text/html/ResetablePlainDocument.java	7 Dec 2006 14:41:53 -0000
@@ -0,0 +1,82 @@
+/* ResetablePlainDocument.java -- A plain document for use in the HTML renderer
+   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.BadLocationException;
+import javax.swing.text.PlainDocument;
+
+/**
+ * A PlainDocument that can be resetted.
+ */
+class ResetablePlainDocument
+  extends PlainDocument
+  implements ResetableModel
+{
+  /**
+   * The initial text.
+   */
+  private String initial;
+
+  /**
+   * Stores the initial text.
+   *
+   * @param text the initial text
+   */
+  void setInitialText(String text)
+  {
+    initial = text;
+  }
+
+  /**
+   * Resets the model.
+   */
+  public void reset()
+  {
+    try
+      {
+        replace(0, getLength(), initial, null);
+      }
+    catch (BadLocationException ex)
+      {
+        // Shouldn't happen.
+        assert false;
+      }
+  }
+
+}
Index: javax/swing/text/html/ResetableToggleButtonModel.java
===================================================================
RCS file: javax/swing/text/html/ResetableToggleButtonModel.java
diff -N javax/swing/text/html/ResetableToggleButtonModel.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ javax/swing/text/html/ResetableToggleButtonModel.java	7 Dec 2006 14:41:53 -0000
@@ -0,0 +1,71 @@
+/* ResetableToggleButtonModel.java -- A toggle button model with reset support
+   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.ButtonGroup;
+import javax.swing.JToggleButton.ToggleButtonModel;
+
+class ResetableToggleButtonModel
+  extends ToggleButtonModel
+  implements ResetableModel
+{
+
+  /**
+   * The initial state.
+   */
+  private boolean initial;
+
+  /**
+   * Sets the initial selection value.
+   *
+   * @param state the initial value
+   */
+  public void setInitial(boolean state)
+  {
+    initial = state;
+  }
+
+  /**
+   * Resets the model.
+   */
+  public void reset()
+  {
+    setSelected(initial);
+  }
+}
Index: javax/swing/text/html/SelectComboBoxModel.java
===================================================================
RCS file: javax/swing/text/html/SelectComboBoxModel.java
diff -N javax/swing/text/html/SelectComboBoxModel.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ javax/swing/text/html/SelectComboBoxModel.java	7 Dec 2006 14:41:53 -0000
@@ -0,0 +1,84 @@
+/* SelectComboBoxModel.java -- A special ComboBoxModel for use in HTML renderer
+   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.DefaultComboBoxModel;
+
+/**
+ * A special ComboBoxModel that supports storing the initial value so that
+ * the combobox can be resetted later.
+ */
+class SelectComboBoxModel
+  extends DefaultComboBoxModel
+  implements ResetableModel
+{
+
+  /**
+   * The initial selection.
+   */
+  private Option initial;
+
+  /**
+   * Sets the initial selection.
+   *
+   * @param option the initial selection
+   */
+  void setInitialSelection(Option option)
+  {
+    initial = option;
+  }
+
+  /**
+   * Returns the initial selection.
+   *
+   * @return the initial selection
+   */
+  Option getInitialSelection()
+  {
+    return initial;
+  }
+
+  /**
+   * Resets the model.
+   */
+  public void reset()
+  {
+    setSelectedItem(initial);
+  }
+}
Index: javax/swing/text/html/SelectListModel.java
===================================================================
RCS file: javax/swing/text/html/SelectListModel.java
diff -N javax/swing/text/html/SelectListModel.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ javax/swing/text/html/SelectListModel.java	7 Dec 2006 14:41:53 -0000
@@ -0,0 +1,106 @@
+/* OptionListModel.java -- A special ListModel for use in the HTML renderer
+   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 java.util.BitSet;
+
+import javax.swing.DefaultListModel;
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.ListSelectionModel;
+
+/**
+ * A special list model that encapsulates its selection model and supports
+ * storing of the initial value so that it can be resetted.
+ */
+class SelectListModel
+  extends DefaultListModel
+  implements ResetableModel
+{
+  /**
+   * The selection model.
+   */
+  private DefaultListSelectionModel selectionModel;
+
+  /**
+   * The initial selection.
+   */
+  private BitSet initialSelection;
+
+  /**
+   * Creates a new SelectListModel.
+   */
+  SelectListModel()
+  {
+    selectionModel = new DefaultListSelectionModel();
+    initialSelection = new BitSet();
+  }
+
+  /**
+   * Sets the initial selection.
+   *
+   * @param init the initial selection
+   */
+  void addInitialSelection(int init)
+  {
+    initialSelection.set(init);
+  }
+
+  /**
+   * Resets the model.
+   */
+  public void reset()
+  {
+    selectionModel.clearSelection();
+    for (int i = initialSelection.size(); i >= 0; i--)
+      {
+        if (initialSelection.get(i))
+          selectionModel.addSelectionInterval(i, i);
+      }
+  }
+
+  /**
+   * Returns the associated selection model.
+   *
+   * @return the associated selection model
+   */
+  ListSelectionModel getSelectionModel()
+  {
+    return selectionModel;
+  }
+}

Reply via email to