mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			871 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			871 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
/* FormView.java -- A view for a variety of HTML form elements
 | 
						|
   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.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.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 {@link 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>
 | 
						|
 * <tr><td>input, radio</td><td>JButton</td></tr>
 | 
						|
 * <tr><td>input, reset</td><td>JButton</td></tr>
 | 
						|
 * <tr><td>input, submit</td><td>JButton</td></tr>
 | 
						|
 * <tr><td>input, text</td><td>JButton</td></tr>
 | 
						|
 * <tr><td>select, size > 1 or with multiple attribute</td>
 | 
						|
 * <td>JList in JScrollPane</td></tr>
 | 
						|
 * <tr><td>select, size unspecified or == 1</td><td>JComboBox</td></tr>
 | 
						|
 * <tr><td>textarea, text</td><td>JTextArea in JScrollPane</td></tr>
 | 
						|
 * <tr><td>input, file</td><td>JTextField</td></tr>
 | 
						|
 * </table>
 | 
						|
 *
 | 
						|
 * @author Roman Kennke (kennke@aicas.com)
 | 
						|
 */
 | 
						|
public class FormView
 | 
						|
  extends ComponentView
 | 
						|
  implements ActionListener
 | 
						|
{
 | 
						|
 | 
						|
  protected class MouseEventListener
 | 
						|
    extends MouseAdapter
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * Creates a new <code>MouseEventListener</code>.
 | 
						|
     */
 | 
						|
    protected MouseEventListener()
 | 
						|
    {
 | 
						|
      // Nothing to do here.
 | 
						|
    }
 | 
						|
 | 
						|
    public void mouseReleased(MouseEvent ev)
 | 
						|
    {
 | 
						|
      String data = getImageData(ev.getPoint());
 | 
						|
      imageSubmit(data);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Actually submits the form data.
 | 
						|
   */
 | 
						|
  private class SubmitThread
 | 
						|
    extends Thread
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * The submit data.
 | 
						|
     */
 | 
						|
    private String data;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a new SubmitThread.
 | 
						|
     *
 | 
						|
     * @param d the submit data
 | 
						|
     */
 | 
						|
    SubmitThread(String d)
 | 
						|
    {
 | 
						|
      data = d;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Actually performs the submit.
 | 
						|
     */
 | 
						|
    public void run()
 | 
						|
    {
 | 
						|
      if (data.length() > 0)
 | 
						|
        {
 | 
						|
          final String method = getMethod();
 | 
						|
          final URL actionURL = getActionURL();
 | 
						|
          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, 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));
 | 
						|
                        }
 | 
						|
                      else
 | 
						|
                        {
 | 
						|
                          try
 | 
						|
                          {
 | 
						|
                            editor.setPage(url);
 | 
						|
                          }
 | 
						|
                          catch (IOException ex)
 | 
						|
                          {
 | 
						|
                            // Oh well.
 | 
						|
                            ex.printStackTrace();
 | 
						|
                          }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                  };
 | 
						|
                  SwingUtilities.invokeLater(loadDoc);
 | 
						|
                }
 | 
						|
              catch (MalformedURLException ex)
 | 
						|
                {
 | 
						|
                  ex.printStackTrace();
 | 
						|
                }
 | 
						|
              catch (IOException ex)
 | 
						|
                {
 | 
						|
                  ex.printStackTrace();
 | 
						|
                }
 | 
						|
            }
 | 
						|
          else
 | 
						|
            {
 | 
						|
              editor.fireHyperlinkUpdate(createSubmitEvent(method,actionURL,
 | 
						|
                                                           target));
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Determines the submit method.
 | 
						|
     *
 | 
						|
     * @return the submit method
 | 
						|
     */
 | 
						|
    private String getMethod()
 | 
						|
    {
 | 
						|
      AttributeSet formAtts = getFormAttributes();
 | 
						|
      String method = null;
 | 
						|
      if (formAtts != null)
 | 
						|
        {
 | 
						|
          method = (String) formAtts.getAttribute(HTML.Attribute.METHOD);
 | 
						|
        }
 | 
						|
      return method;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Determines the action URL.
 | 
						|
     *
 | 
						|
     * @return the action URL
 | 
						|
     */
 | 
						|
    private URL getActionURL()
 | 
						|
    {
 | 
						|
      AttributeSet formAtts = getFormAttributes();
 | 
						|
      HTMLDocument doc = (HTMLDocument) getElement().getDocument();
 | 
						|
      URL url = doc.getBase();
 | 
						|
      if (formAtts != null)
 | 
						|
        {
 | 
						|
          String action =
 | 
						|
            (String) formAtts.getAttribute(HTML.Attribute.ACTION);
 | 
						|
          if (action != null)
 | 
						|
            {
 | 
						|
              try
 | 
						|
                {
 | 
						|
                  url = new URL(url, action);
 | 
						|
                }
 | 
						|
              catch (MalformedURLException ex)
 | 
						|
                {
 | 
						|
                  url = null;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
      return url;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Fetches the target attribute.
 | 
						|
     *
 | 
						|
     * @return the target attribute or _self if none is present
 | 
						|
     */
 | 
						|
    private String getTarget()
 | 
						|
    {
 | 
						|
      AttributeSet formAtts = getFormAttributes();
 | 
						|
      String target = null;
 | 
						|
      if (formAtts != null)
 | 
						|
        {
 | 
						|
          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, String data)
 | 
						|
    {
 | 
						|
      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;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates the submit event that should be fired.
 | 
						|
     *
 | 
						|
     * This is package private to avoid accessor methods.
 | 
						|
     *
 | 
						|
     * @param method the submit method
 | 
						|
     * @param actionURL the action URL
 | 
						|
     * @param target the target
 | 
						|
     *
 | 
						|
     * @return the submit event
 | 
						|
     */
 | 
						|
    FormSubmitEvent createSubmitEvent(String method, URL actionURL,
 | 
						|
                                      String target)
 | 
						|
    {
 | 
						|
      FormSubmitEvent.MethodType m = "post".equals(method)
 | 
						|
                                     ? FormSubmitEvent.MethodType.POST
 | 
						|
                                     : FormSubmitEvent.MethodType.GET;
 | 
						|
      return new FormSubmitEvent(FormView.this,
 | 
						|
                                 HyperlinkEvent.EventType.ACTIVATED,
 | 
						|
                                 actionURL, getElement(), target, m, data);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * If the value attribute of an <code><input type="submit">>
 | 
						|
   * tag is not specified, then this string is used.
 | 
						|
   *
 | 
						|
   * @deprecated As of JDK1.3 the value is fetched from the UIManager property
 | 
						|
   *             <code>FormView.submitButtonText</code>.
 | 
						|
   */
 | 
						|
  public static final String SUBMIT =
 | 
						|
    UIManager.getString("FormView.submitButtonText");
 | 
						|
 | 
						|
  /**
 | 
						|
   * If the value attribute of an <code><input type="reset">>
 | 
						|
   * 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();
 | 
						|
    AttributeSet atts = el.getAttributes();
 | 
						|
    Object tag = atts.getAttribute(StyleConstants.NameAttribute);
 | 
						|
    Object model = atts.getAttribute(StyleConstants.ModelAttribute);
 | 
						|
    if (tag.equals(HTML.Tag.INPUT))
 | 
						|
      {
 | 
						|
        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"))
 | 
						|
          {
 | 
						|
            if (model instanceof ResetableToggleButtonModel)
 | 
						|
              {
 | 
						|
                ResetableToggleButtonModel m =
 | 
						|
                  (ResetableToggleButtonModel) model;
 | 
						|
                JCheckBox c = new JCheckBox();
 | 
						|
                c.setModel(m);
 | 
						|
                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);
 | 
						|
              }
 | 
						|
            if (model != null)
 | 
						|
              {
 | 
						|
                b.setModel((ButtonModel) model);
 | 
						|
                b.addActionListener(this);
 | 
						|
              }
 | 
						|
            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);
 | 
						|
            tf.addActionListener(this);
 | 
						|
            comp = tf;
 | 
						|
            maxIsPreferred = true;
 | 
						|
          }
 | 
						|
        else if (type.equals("radio"))
 | 
						|
          {
 | 
						|
            if (model instanceof ResetableToggleButtonModel)
 | 
						|
              {
 | 
						|
                ResetableToggleButtonModel m =
 | 
						|
                  (ResetableToggleButtonModel) model;
 | 
						|
                JRadioButton c = new JRadioButton();
 | 
						|
                c.setModel(m);
 | 
						|
                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;
 | 
						|
          }
 | 
						|
        else if (type.equals("submit"))
 | 
						|
          {
 | 
						|
            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"))
 | 
						|
          {
 | 
						|
            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);
 | 
						|
            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);
 | 
						|
      }
 | 
						|
    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;
 | 
						|
    if (maxIsPreferred)
 | 
						|
      span = getPreferredSpan(axis);
 | 
						|
    else
 | 
						|
      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
 | 
						|
   * {@link #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
 | 
						|
   */
 | 
						|
  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();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Submits the form data in response to a click on a
 | 
						|
   * <code><input type="image"></code> element.
 | 
						|
   *
 | 
						|
   * @param imageData the mouse click coordinates
 | 
						|
   */
 | 
						|
  protected void imageSubmit(String imageData)
 | 
						|
  {
 | 
						|
    // FIXME: Implement this.
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Determines the image data that should be submitted in response to a
 | 
						|
   * mouse click on a image. This is either 'x=<p.x>&y=<p.y>' if the name
 | 
						|
   * attribute of the element is null or '' or
 | 
						|
   * <name>.x=<p.x>&<name>.y=<p.y>' when the name attribute is not empty.
 | 
						|
   *
 | 
						|
   * @param p the coordinates of the mouseclick
 | 
						|
   */
 | 
						|
  String getImageData(Point p)
 | 
						|
  {
 | 
						|
    String name = (String) getElement().getAttributes()
 | 
						|
                                            .getAttribute(HTML.Attribute.NAME);
 | 
						|
    String data;
 | 
						|
    if (name == null || name.equals(""))
 | 
						|
      {
 | 
						|
        data = "x=" + p.x + "&y=" + p.y;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
        data = name + ".x=" + p.x + "&" + name + ".y=" + p.y;
 | 
						|
      }
 | 
						|
    return data;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Determines and returns the enclosing form element if there is any.
 | 
						|
   *
 | 
						|
   * This is package private to avoid accessor methods.
 | 
						|
   *
 | 
						|
   * @return the enclosing form element, or <code>null</code> if there is no
 | 
						|
   *         enclosing form element
 | 
						|
   */
 | 
						|
  Element getFormElement()
 | 
						|
  {
 | 
						|
    Element form = null;
 | 
						|
    Element el = getElement();
 | 
						|
    while (el != null && form == null)
 | 
						|
      {
 | 
						|
        AttributeSet atts = el.getAttributes();
 | 
						|
        if (atts.getAttribute(StyleConstants.NameAttribute) == HTML.Tag.FORM)
 | 
						|
          form = el;
 | 
						|
        else
 | 
						|
          el = el.getParentElement();
 | 
						|
      }
 | 
						|
    return form;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Determines the form data that is about to be submitted.
 | 
						|
   *
 | 
						|
   * @return the form data
 | 
						|
   */
 | 
						|
  private String getFormData()
 | 
						|
  {
 | 
						|
    Element form = getFormElement();
 | 
						|
    StringBuilder b = new StringBuilder();
 | 
						|
    if (form != null)
 | 
						|
      {
 | 
						|
        ElementIterator i = new ElementIterator(form);
 | 
						|
        Element next;
 | 
						|
        while ((next = i.next()) != null)
 | 
						|
          {
 | 
						|
            if (next.isLeaf())
 | 
						|
              {
 | 
						|
                AttributeSet atts = next.getAttributes();
 | 
						|
                String type = (String) atts.getAttribute(HTML.Attribute.TYPE);
 | 
						|
                if (type != null && type.equals("submit")
 | 
						|
                    && next != getElement())
 | 
						|
                  {
 | 
						|
                    // Skip this. This is not the actual submit trigger.
 | 
						|
                  }
 | 
						|
                else if (type == null || ! type.equals("image"))
 | 
						|
                  {
 | 
						|
                    getElementFormData(next, b);
 | 
						|
                  }
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return b.toString();
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * 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.SELECT)
 | 
						|
          {
 | 
						|
            getSelectData(atts, b);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            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
 | 
						|
          {
 | 
						|
            value = doc.getText(0, doc.getLength());
 | 
						|
          }
 | 
						|
        catch (BadLocationException ex)
 | 
						|
          {
 | 
						|
            // Sigh.
 | 
						|
            assert false;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    else if (type.equals("hidden") || type.equals("submit"))
 | 
						|
      {
 | 
						|
        value = (String) atts.getAttribute(HTML.Attribute.VALUE);
 | 
						|
        if (value == null)
 | 
						|
          value = "";
 | 
						|
      }
 | 
						|
    // TODO: Implement the others. radio, checkbox and file.
 | 
						|
    return value;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Actually adds the specified data to the string. It URL encodes
 | 
						|
   * the name and value and handles separation of the fields.
 | 
						|
   *
 | 
						|
   * @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();
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
}
 |