This adds (very) basic support for <input> tags. That is the following
<input> tag types are now rendered:
text -> JTextField
password -> JPasswordField
submit -> JButton
reset -> JButton
button -> JButton
image -> JButton
checkbox -> JCheckBox
radio -> JRadioButton

Note that this probably won't work due to a problem that I'll report
next. Also note that this is only for rendering yet, no more actions
supported.

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

        * javax/swing/text/html/FormView.java
        (maxIsPreferred): New field.
        (createComponent): Initialize components correctly.
        (getMaximumSpan): Return the preferred span for components
        that need this. The maxIsPreferred flag is set accordingly
        in createComponent.
        * javax/swing/text/html/HTMLDocument.java
        (HTMLReader.FormAction.start): Implemented to set the
        correct model as attribute.
        (HTMLReader.FormAction.setModel): New helper method.
        (HTMLReader.FormAction.end): Call super to finish the element.
        Added TODO about things left to do.
        (HTMLReader.handleComment): Use SimpleAttributeSet rather
        than htmlAttributeSet.
        * javax/swing/text/html/HTMLEditorKit.java
        (HTMLFactory.create): Create BlockView for FORM tags.
        Create FormView for INPUT, TEXTAREA and SELECT tags.


Index: javax/swing/text/html/FormView.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/FormView.java,v
retrieving revision 1.3
diff -u -1 -5 -r1.3 FormView.java
--- javax/swing/text/html/FormView.java	22 Mar 2006 08:16:25 -0000	1.3
+++ javax/swing/text/html/FormView.java	2 Nov 2006 21:35:06 -0000
@@ -32,39 +32,45 @@
 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.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.net.MalformedURLException;
+import java.net.URL;
 
+import javax.swing.ButtonModel;
+import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JPasswordField;
 import javax.swing.JRadioButton;
 import javax.swing.JTextField;
+import javax.swing.JToggleButton;
 import javax.swing.UIManager;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.ComponentView;
+import javax.swing.text.Document;
 import javax.swing.text.Element;
 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.
  *
  * Namely, this view creates the following components:
  * <table>
  * <tr><th>Element type</th><th>Swing component</th></tr>
  * <tr><td>input, button</td><td>JButton</td></tr>
  * <tr><td>input, checkbox</td><td>JButton</td></tr>
  * <tr><td>input, image</td><td>JButton</td></tr>
  * <tr><td>input, password</td><td>JButton</td></tr>
@@ -113,103 +119,201 @@
    */
   public static final String SUBMIT =
     UIManager.getString("FormView.submitButtonText");
 
   /**
    * If the value attribute of an <code>&lt;input type=&quot;reset&quot;&gt>
    * tag is not specified, then this string is used.
    * 
    * @deprecated As of JDK1.3 the value is fetched from the UIManager property
    *             <code>FormView.resetButtonText</code>.
    */
   public static final String RESET =
     UIManager.getString("FormView.resetButtonText");
 
   /**
+   * If this is true, the maximum size is set to the preferred size.
+   */
+  private boolean maxIsPreferred;
+
+  /**
    * Creates a new <code>FormView</code>.
    *
    * @param el the element that is displayed by this view.
    */
   public FormView(Element el)
   {
     super(el);
   }
 
   /**
    * Creates the correct AWT component for rendering the form element.
    */
   protected Component createComponent()
   {
     Component comp = null;
     Element el = getElement();
-    Object tag = el.getAttributes().getAttribute(StyleConstants.NameAttribute);
+    AttributeSet atts = el.getAttributes();
+    Object tag = atts.getAttribute(StyleConstants.NameAttribute);
+    Object model = atts.getAttribute(StyleConstants.ModelAttribute);
     if (tag.equals(HTML.Tag.INPUT))
       {
-        AttributeSet atts = el.getAttributes();
         String type = (String) atts.getAttribute(HTML.Attribute.TYPE);
-        String value = (String) atts.getAttribute(HTML.Attribute.VALUE);
         if (type.equals("button"))
-          comp = new JButton(value);
+          {
+            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"))
-          comp = new JCheckBox(value);
+          {
+            JCheckBox c = new JCheckBox();
+            if (model != null)
+              {
+                boolean sel = atts.getAttribute(HTML.Attribute.CHECKED) != null;
+                ((JToggleButton.ToggleButtonModel) model).setSelected(sel);
+                c.setModel((ButtonModel) model);
+              }
+            comp = c;
+            maxIsPreferred = true;
+          }
         else if (type.equals("image"))
-          comp = new JButton(value); // FIXME: Find out how to fetch the 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);
+              }
+            if (model != null)
+              {
+                b.setModel((ButtonModel) model);
+                b.addActionListener(this);
+              }
+            comp = b;
+            maxIsPreferred = true;
+          }
         else if (type.equals("password"))
-          comp = new JPasswordField(value);
+          {
+            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"))
-          comp = new JRadioButton(value);
+          {
+            JRadioButton c = new JRadioButton();
+            if (model != null)
+              {
+                boolean sel = atts.getAttribute(HTML.Attribute.CHECKED) != null;
+                ((JToggleButton.ToggleButtonModel) model).setSelected(sel);
+                c.setModel((ButtonModel) model);
+              }
+            comp = c;
+            maxIsPreferred = true;
+          }
         else if (type.equals("reset"))
           {
-            if (value == null || value.equals(""))
-              value = RESET;
-            comp = new JButton(value);
+            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;
           }
         else if (type.equals("submit"))
           {
-            if (value == null || value.equals(""))
-              value = SUBMIT;
-            comp = new JButton(value);
+            String value = (String) atts.getAttribute(HTML.Attribute.VALUE);
+            if (value == null)
+              value = UIManager.getString("FormView.submitButtonText");
+            JButton b = new JButton(value);
+            if (model != null)
+              {
+                b.setModel((ButtonModel) model);
+                b.addActionListener(this);
+              }
+            comp = b;
+            maxIsPreferred = true;
           }
         else if (type.equals("text"))
-          comp = new JTextField(value);
-        
+          {
+            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;
+          }
       }
     // FIXME: Implement the remaining components.
     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)
   {
-    // FIXME: The specs say that for some components the maximum span == the
-    // preferred span of the component. This should be figured out and
-    // implemented accordingly.
     float span;
-    if (axis == X_AXIS)
-      span = getComponent().getMaximumSize().width;
-    else if (axis == Y_AXIS)
-      span = getComponent().getMaximumSize().height;
+    if (maxIsPreferred)
+      span = getPreferredSpan(axis);
     else
-      throw new IllegalArgumentException("Invalid axis parameter");
+      span = super.getMaximumSpan(axis);
     return span;
   }
 
   /**
    * Processes an action from the Swing component.
    *
    * If the action comes from a submit button, the form is submitted by calling
    * [EMAIL PROTECTED] #submitData}. In the case of a reset button, the form is reset to
    * the original state. If the action comes from a password or text field,
    * then the input focus is transferred to the next input element in the form,
    * unless this text/password field is the last one, in which case the form
    * is submitted.
    *
    * @param ev the action event
    */
Index: javax/swing/text/html/HTMLDocument.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLDocument.java,v
retrieving revision 1.42
diff -u -1 -5 -r1.42 HTMLDocument.java
--- javax/swing/text/html/HTMLDocument.java	31 Oct 2006 16:39:44 -0000	1.42
+++ javax/swing/text/html/HTMLDocument.java	2 Nov 2006 21:35:07 -0000
@@ -36,39 +36,42 @@
 exception statement from your version. */
 
 
 package javax.swing.text.html;
 
 import gnu.classpath.NotImplementedException;
 import gnu.javax.swing.text.html.parser.htmlAttributeSet;
 
 import java.io.IOException;
 import java.io.StringReader;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.Stack;
 import java.util.Vector;
 
+import javax.swing.DefaultButtonModel;
 import javax.swing.JEditorPane;
+import javax.swing.JToggleButton;
 import javax.swing.text.AbstractDocument;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.BadLocationException;
 import javax.swing.text.DefaultStyledDocument;
 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
  * the certain types of tags. This class also has methods for modifying the HTML
  * content.
  * 
  * @author Audrius Meskauskas ([EMAIL PROTECTED])
  * @author Anthony Balkissoon ([EMAIL PROTECTED])
@@ -627,54 +630,99 @@
         pushCharacterStyle();
 
         // Just add the attributes in <code>a</code>.
         charAttr.addAttribute(t, a.copyAttributes());
       }
 
       /**
        * Called when an end tag is seen for one of the types of tags associated
        * with this Action.
        */
       public void end(HTML.Tag t)
       {
         popCharacterStyle();
       } 
     }
-    
+
+    /**
+     * Processes elements that make up forms: &lt;input&gt;, &lt;textarea&gt;,
+     * &lt;select&gt; and &lt;option&gt;.
+     */
     public class FormAction extends SpecialAction
     {
       /**
        * This method is called when a start tag is seen for one of the types
        * of tags associated with this Action.
        */
       public void start(HTML.Tag t, MutableAttributeSet a)
-        throws NotImplementedException
       {
-        // FIXME: Implement.
-        print ("FormAction.start not implemented");
+        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);
+          }
+        // TODO: Handle textarea, select and option tags.
+
+        // 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)
-        throws NotImplementedException
       {
-        // FIXME: Implement.
-        print ("FormAction.end not implemented");
-      } 
+        // TODO: Handle textarea, 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());
+          }
+        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.
+            attrs.addAttribute(StyleConstants.ModelAttribute, model);
+          }
+      }
     }
     
     /**
      * 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
     {
       /**
Index: javax/swing/text/html/HTMLEditorKit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/html/HTMLEditorKit.java,v
retrieving revision 1.36
diff -u -1 -5 -r1.36 HTMLEditorKit.java
--- javax/swing/text/html/HTMLEditorKit.java	2 Nov 2006 14:00:45 -0000	1.36
+++ javax/swing/text/html/HTMLEditorKit.java	2 Nov 2006 21:35:07 -0000
@@ -628,56 +628,57 @@
       if (attr instanceof HTML.Tag)
         {
           HTML.Tag tag = (HTML.Tag) attr;
 
           if (tag.equals(HTML.Tag.IMPLIED) || tag.equals(HTML.Tag.P)
               || tag.equals(HTML.Tag.H1) || tag.equals(HTML.Tag.H2)
               || tag.equals(HTML.Tag.H3) || tag.equals(HTML.Tag.H4)
               || tag.equals(HTML.Tag.H5) || tag.equals(HTML.Tag.H6)
               || tag.equals(HTML.Tag.DT))
             view = new ParagraphView(element);
           else if (tag.equals(HTML.Tag.LI) || tag.equals(HTML.Tag.DL)
                    || tag.equals(HTML.Tag.DD) || tag.equals(HTML.Tag.BODY)
                    || tag.equals(HTML.Tag.HTML) || tag.equals(HTML.Tag.CENTER)
                    || tag.equals(HTML.Tag.DIV)
                    || tag.equals(HTML.Tag.BLOCKQUOTE)
-                   || tag.equals(HTML.Tag.PRE))
+                   || tag.equals(HTML.Tag.PRE)
+                   || tag.equals(HTML.Tag.FORM))
             view = new BlockView(element, View.Y_AXIS);
           else if (tag.equals(HTML.Tag.IMG))
             view = new ImageView(element);
           
           // FIXME: Uncomment when the views have been implemented
           else if (tag.equals(HTML.Tag.CONTENT))
             view = new InlineView(element);
           else if (tag == HTML.Tag.HEAD)
             view = new NullView(element);
           else if (tag.equals(HTML.Tag.TABLE))
             view = new javax.swing.text.html.TableView(element);
           else if (tag.equals(HTML.Tag.TD))
             view = new ParagraphView(element);
           else if (tag.equals(HTML.Tag.HR))
             view = new HRuleView(element);
           else if (tag.equals(HTML.Tag.BR))
             view = new BRView(element);
+          else if (tag.equals(HTML.Tag.INPUT) || tag.equals(HTML.Tag.SELECT)
+                   || tag.equals(HTML.Tag.TEXTAREA))
+            view = new FormView(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);
-          else if (tag.equals(HTML.Tag.INPUT) || tag.equals(HTML.Tag.SELECT)
-                   || tag.equals(HTML.Tag.TEXTAREA))
-            view = new FormView(element);
           else if (tag.equals(HTML.Tag.OBJECT))
             view = new ObjectView(element);
           else if (tag.equals(HTML.Tag.FRAMESET))
             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;
     }
   }

Reply via email to