/*
 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package javax.swing.text.html;

import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

Component decorator that implements the view interface for form elements, <input>, <textarea>, and <select>. The model for the component is stored as an attribute of the the element (using StyleConstants.ModelAttribute), and is used to build the component of the view. The type of the model is assumed to of the type that would be set by HTMLDocument.HTMLReader.FormAction. If there are multiple views mapped over the document, they will share the embedded component models.

The following table shows what components get built by this view.

Element Type Component built
input, type button JButton
input, type checkbox JCheckBox
input, type image JButton
input, type password JPasswordField
input, type radio JRadioButton
input, type reset JButton
input, type submit JButton
input, type text JTextField
select, size > 1 or multiple attribute defined JList in a JScrollPane
select, size unspecified or 1 JComboBox
textarea JTextArea in a JScrollPane
input, type file JTextField
Author:Timothy Prinzing, Sunita Mani
/** * Component decorator that implements the view interface * for form elements, &lt;input&gt;, &lt;textarea&gt;, * and &lt;select&gt;. The model for the component is stored * as an attribute of the the element (using StyleConstants.ModelAttribute), * and is used to build the component of the view. The type * of the model is assumed to of the type that would be set by * <code>HTMLDocument.HTMLReader.FormAction</code>. If there are * multiple views mapped over the document, they will share the * embedded component models. * <p> * The following table shows what components get built * by this view. * <table summary="shows what components get built by this view"> * <tr> * <th>Element Type</th> * <th>Component built</th> * </tr> * <tr> * <td>input, type button</td> * <td>JButton</td> * </tr> * <tr> * <td>input, type checkbox</td> * <td>JCheckBox</td> * </tr> * <tr> * <td>input, type image</td> * <td>JButton</td> * </tr> * <tr> * <td>input, type password</td> * <td>JPasswordField</td> * </tr> * <tr> * <td>input, type radio</td> * <td>JRadioButton</td> * </tr> * <tr> * <td>input, type reset</td> * <td>JButton</td> * </tr> * <tr> * <td>input, type submit</td> * <td>JButton</td> * </tr> * <tr> * <td>input, type text</td> * <td>JTextField</td> * </tr> * <tr> * <td>select, size &gt; 1 or multiple attribute defined</td> * <td>JList in a JScrollPane</td> * </tr> * <tr> * <td>select, size unspecified or 1</td> * <td>JComboBox</td> * </tr> * <tr> * <td>textarea</td> * <td>JTextArea in a JScrollPane</td> * </tr> * <tr> * <td>input, type file</td> * <td>JTextField</td> * </tr> * </table> * * @author Timothy Prinzing * @author Sunita Mani */
public class FormView extends ComponentView implements ActionListener {
If a value attribute is not specified for a FORM input element of type "submit", then this default string is used.
Deprecated:As of 1.3, value now comes from UIManager property FormView.submitButtonText
/** * If a value attribute is not specified for a FORM input element * of type "submit", then this default string is used. * * @deprecated As of 1.3, value now comes from UIManager property * FormView.submitButtonText */
@Deprecated public static final String SUBMIT = new String("Submit Query");
If a value attribute is not specified for a FORM input element of type "reset", then this default string is used.
Deprecated:As of 1.3, value comes from UIManager UIManager property FormView.resetButtonText
/** * If a value attribute is not specified for a FORM input element * of type "reset", then this default string is used. * * @deprecated As of 1.3, value comes from UIManager UIManager property * FormView.resetButtonText */
@Deprecated public static final String RESET = new String("Reset");
Document attribute name for storing POST data. JEditorPane.getPostData() uses the same name, should be kept in sync.
/** * Document attribute name for storing POST data. JEditorPane.getPostData() * uses the same name, should be kept in sync. */
final static String PostDataProperty = "javax.swing.JEditorPane.postdata";
Used to indicate if the maximum span should be the same as the preferred span. This is used so that the Component's size doesn't change if there is extra room on a line. The first bit is used for the X direction, and the second for the y direction.
/** * Used to indicate if the maximum span should be the same as the * preferred span. This is used so that the Component's size doesn't * change if there is extra room on a line. The first bit is used for * the X direction, and the second for the y direction. */
private short maxIsPreferred;
Creates a new FormView object.
Params:
  • elem – the element to decorate
/** * Creates a new FormView object. * * @param elem the element to decorate */
public FormView(Element elem) { super(elem); }
Create the component. This is basically a big switch statement based upon the tag type and html attributes of the associated element.
/** * Create the component. This is basically a * big switch statement based upon the tag type * and html attributes of the associated element. */
protected Component createComponent() { AttributeSet attr = getElement().getAttributes(); HTML.Tag t = (HTML.Tag) attr.getAttribute(StyleConstants.NameAttribute); JComponent c = null; Object model = attr.getAttribute(StyleConstants.ModelAttribute); // Remove listeners previously registered in shared model // when a new UI component is replaced. See bug 8008289. removeStaleListenerForModel(model); if (t == HTML.Tag.INPUT) { c = createInputComponent(attr, model); } else if (t == HTML.Tag.SELECT) { if (model instanceof OptionListModel) { JList list = new JList((ListModel) model); int size = HTML.getIntegerAttributeValue(attr, HTML.Attribute.SIZE, 1); list.setVisibleRowCount(size); list.setSelectionModel((ListSelectionModel)model); c = new JScrollPane(list); } else { c = new JComboBox((ComboBoxModel) model); maxIsPreferred = 3; } } else if (t == HTML.Tag.TEXTAREA) { JTextArea area = new JTextArea((Document) model); int rows = HTML.getIntegerAttributeValue(attr, HTML.Attribute.ROWS, 1); area.setRows(rows); int cols = HTML.getIntegerAttributeValue(attr, HTML.Attribute.COLS, 20); maxIsPreferred = 3; area.setColumns(cols); c = new JScrollPane(area, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); } if (c != null) { c.setAlignmentY(1.0f); } return c; }
Creates a component for an <INPUT> element based on the value of the "type" attribute.
Params:
  • set – of attributes associated with the <INPUT> element.
  • model – the value of the StyleConstants.ModelAttribute
Returns:the component.
/** * Creates a component for an &lt;INPUT&gt; element based on the * value of the "type" attribute. * * @param set of attributes associated with the &lt;INPUT&gt; element. * @param model the value of the StyleConstants.ModelAttribute * @return the component. */
private JComponent createInputComponent(AttributeSet attr, Object model) { JComponent c = null; String type = (String) attr.getAttribute(HTML.Attribute.TYPE); if (type.equals("submit") || type.equals("reset")) { String value = (String) attr.getAttribute(HTML.Attribute.VALUE); if (value == null) { if (type.equals("submit")) { value = UIManager.getString("FormView.submitButtonText"); } else { value = UIManager.getString("FormView.resetButtonText"); } } JButton button = new JButton(value); if (model != null) { button.setModel((ButtonModel)model); button.addActionListener(this); } c = button; maxIsPreferred = 3; } else if (type.equals("image")) { String srcAtt = (String) attr.getAttribute(HTML.Attribute.SRC); JButton button; try { URL base = ((HTMLDocument)getElement().getDocument()).getBase(); URL srcURL = new URL(base, srcAtt); Icon icon = new ImageIcon(srcURL); button = new JButton(icon); } catch (MalformedURLException e) { button = new JButton(srcAtt); } if (model != null) { button.setModel((ButtonModel)model); button.addMouseListener(new MouseEventListener()); } c = button; maxIsPreferred = 3; } else if (type.equals("checkbox")) { c = new JCheckBox(); if (model != null) { ((JCheckBox)c).setModel((JToggleButton.ToggleButtonModel) model); } maxIsPreferred = 3; } else if (type.equals("radio")) { c = new JRadioButton(); if (model != null) { ((JRadioButton)c).setModel((JToggleButton.ToggleButtonModel)model); } maxIsPreferred = 3; } else if (type.equals("text")) { int size = HTML.getIntegerAttributeValue(attr, HTML.Attribute.SIZE, -1); JTextField field; if (size > 0) { field = new JTextField(); field.setColumns(size); } else { field = new JTextField(); field.setColumns(20); } c = field; if (model != null) { field.setDocument((Document) model); } field.addActionListener(this); maxIsPreferred = 3; } else if (type.equals("password")) { JPasswordField field = new JPasswordField(); c = field; if (model != null) { field.setDocument((Document) model); } int size = HTML.getIntegerAttributeValue(attr, HTML.Attribute.SIZE, -1); field.setColumns((size > 0) ? size : 20); field.addActionListener(this); maxIsPreferred = 3; } else if (type.equals("file")) { JTextField field = new JTextField(); if (model != null) { field.setDocument((Document)model); } int size = HTML.getIntegerAttributeValue(attr, HTML.Attribute.SIZE, -1); field.setColumns((size > 0) ? size : 20); JButton browseButton = new JButton(UIManager.getString ("FormView.browseFileButtonText")); Box box = Box.createHorizontalBox(); box.add(field); box.add(Box.createHorizontalStrut(5)); box.add(browseButton); browseButton.addActionListener(new BrowseFileAction( attr, (Document)model)); c = box; maxIsPreferred = 3; } return c; } private void removeStaleListenerForModel(Object model) { if (model instanceof DefaultButtonModel) { // case of JButton whose model is DefaultButtonModel // Need to remove stale ActionListener, ChangeListener and // ItemListener that are instance of AbstractButton$Handler. DefaultButtonModel buttonModel = (DefaultButtonModel) model; String listenerClass = "javax.swing.AbstractButton$Handler"; for (ActionListener listener : buttonModel.getActionListeners()) { if (listenerClass.equals(listener.getClass().getName())) { buttonModel.removeActionListener(listener); } } for (ChangeListener listener : buttonModel.getChangeListeners()) { if (listenerClass.equals(listener.getClass().getName())) { buttonModel.removeChangeListener(listener); } } for (ItemListener listener : buttonModel.getItemListeners()) { if (listenerClass.equals(listener.getClass().getName())) { buttonModel.removeItemListener(listener); } } } else if (model instanceof AbstractListModel) { // case of JComboBox and JList // For JList, the stale ListDataListener is instance // BasicListUI$Handler. // For JComboBox, there are 2 stale ListDataListeners, which are // BasicListUI$Handler and BasicComboBoxUI$Handler. AbstractListModel listModel = (AbstractListModel) model; String listenerClass1 = "javax.swing.plaf.basic.BasicListUI$Handler"; String listenerClass2 = "javax.swing.plaf.basic.BasicComboBoxUI$Handler"; for (ListDataListener listener : listModel.getListDataListeners()) { if (listenerClass1.equals(listener.getClass().getName()) || listenerClass2.equals(listener.getClass().getName())) { listModel.removeListDataListener(listener); } } } else if (model instanceof AbstractDocument) { // case of JPasswordField, JTextField and JTextArea // All have 2 stale DocumentListeners. String listenerClass1 = "javax.swing.plaf.basic.BasicTextUI$UpdateHandler"; String listenerClass2 = "javax.swing.text.DefaultCaret$Handler"; AbstractDocument docModel = (AbstractDocument) model; for (DocumentListener listener : docModel.getDocumentListeners()) { if (listenerClass1.equals(listener.getClass().getName()) || listenerClass2.equals(listener.getClass().getName())) { docModel.removeDocumentListener(listener); } } } }
Determines the maximum span for this view along an axis. For certain components, the maximum and preferred span are the same. For others this will return the value returned by Component.getMaximumSize along the axis of interest.
Params:
  • axis – may be either View.X_AXIS or View.Y_AXIS
Throws:
Returns: the span the view would like to be rendered into >= 0. Typically the view is told to render into the span that is returned, although there is no guarantee. The parent may choose to resize or break the view.
/** * Determines the maximum span for this view along an * axis. For certain components, the maximum and preferred span are the * same. For others this will return the value * returned by Component.getMaximumSize along the * axis of interest. * * @param axis may be either View.X_AXIS or View.Y_AXIS * @return the span the view would like to be rendered into >= 0. * Typically the view is told to render into the span * that is returned, although there is no guarantee. * The parent may choose to resize or break the view. * @exception IllegalArgumentException for an invalid axis */
public float getMaximumSpan(int axis) { switch (axis) { case View.X_AXIS: if ((maxIsPreferred & 1) == 1) { super.getMaximumSpan(axis); return getPreferredSpan(axis); } return super.getMaximumSpan(axis); case View.Y_AXIS: if ((maxIsPreferred & 2) == 2) { super.getMaximumSpan(axis); return getPreferredSpan(axis); } return super.getMaximumSpan(axis); default: break; } return super.getMaximumSpan(axis); }
Responsible for processing the ActionEvent. If the element associated with the FormView, has a type of "submit", "reset", "text" or "password" then the action is processed. In the case of a "submit" the form is submitted. In the case of a "reset" the form is reset to its original state. In the case of "text" or "password", if the element is the last one of type "text" or "password", the form is submitted. Otherwise, focus is transferred to the next component in the form.
Params:
  • evt – the ActionEvent.
/** * Responsible for processing the ActionEvent. * If the element associated with the FormView, * has a type of "submit", "reset", "text" or "password" * then the action is processed. In the case of a "submit" * the form is submitted. In the case of a "reset" * the form is reset to its original state. * In the case of "text" or "password", if the * element is the last one of type "text" or "password", * the form is submitted. Otherwise, focus is transferred * to the next component in the form. * * @param evt the ActionEvent. */
public void actionPerformed(ActionEvent evt) { Element element = getElement(); StringBuilder dataBuffer = new StringBuilder(); HTMLDocument doc = (HTMLDocument)getDocument(); AttributeSet attr = element.getAttributes(); String type = (String) attr.getAttribute(HTML.Attribute.TYPE); if (type.equals("submit")) { getFormData(dataBuffer); submitData(dataBuffer.toString()); } else if (type.equals("reset")) { resetForm(); } else if (type.equals("text") || type.equals("password")) { if (isLastTextOrPasswordField()) { getFormData(dataBuffer); submitData(dataBuffer.toString()); } else { getComponent().transferFocus(); } } }
This method is responsible for submitting the form data. A thread is forked to undertake the submission.
/** * This method is responsible for submitting the form data. * A thread is forked to undertake the submission. */
protected void submitData(String data) { Element form = getFormElement(); AttributeSet attrs = form.getAttributes(); HTMLDocument doc = (HTMLDocument) form.getDocument(); URL base = doc.getBase(); String target = (String) attrs.getAttribute(HTML.Attribute.TARGET); if (target == null) { target = "_self"; } String method = (String) attrs.getAttribute(HTML.Attribute.METHOD); if (method == null) { method = "GET"; } method = method.toLowerCase(); boolean isPostMethod = method.equals("post"); if (isPostMethod) { storePostData(doc, target, data); } String action = (String) attrs.getAttribute(HTML.Attribute.ACTION); URL actionURL; try { actionURL = (action == null) ? new URL(base.getProtocol(), base.getHost(), base.getPort(), base.getFile()) : new URL(base, action); if (!isPostMethod) { String query = data.toString(); actionURL = new URL(actionURL + "?" + query); } } catch (MalformedURLException e) { actionURL = null; } final JEditorPane c = (JEditorPane) getContainer(); HTMLEditorKit kit = (HTMLEditorKit) c.getEditorKit(); FormSubmitEvent formEvent = null; if (!kit.isAutoFormSubmission() || doc.isFrameDocument()) { FormSubmitEvent.MethodType methodType = isPostMethod ? FormSubmitEvent.MethodType.POST : FormSubmitEvent.MethodType.GET; formEvent = new FormSubmitEvent( FormView.this, HyperlinkEvent.EventType.ACTIVATED, actionURL, form, target, methodType, data); } // setPage() may take significant time so schedule it to run later. final FormSubmitEvent fse = formEvent; final URL url = actionURL; SwingUtilities.invokeLater(new Runnable() { public void run() { if (fse != null) { c.fireHyperlinkUpdate(fse); } else { try { c.setPage(url); } catch (IOException e) { UIManager.getLookAndFeel().provideErrorFeedback(c); } } } }); } private void storePostData(HTMLDocument doc, String target, String data) { /* POST data is stored into the document property named by constant * PostDataProperty from where it is later retrieved by method * JEditorPane.getPostData(). If the current document is in a frame, * the data is initially put into the toplevel (frameset) document * property (named <PostDataProperty>.<Target frame name>). It is the * responsibility of FrameView which updates the target frame * to move data from the frameset document property into the frame * document property. */ Document propDoc = doc; String propName = PostDataProperty; if (doc.isFrameDocument()) { // find the top-most JEditorPane holding the frameset view. FrameView.FrameEditorPane p = (FrameView.FrameEditorPane) getContainer(); FrameView v = p.getFrameView(); JEditorPane c = v.getOutermostJEditorPane(); if (c != null) { propDoc = c.getDocument(); propName += ("." + target); } } propDoc.putProperty(propName, data); }
MouseEventListener class to handle form submissions when an input with type equal to image is clicked on. A MouseListener is necessary since along with the image data the coordinates associated with the mouse click need to be submitted.
/** * MouseEventListener class to handle form submissions when * an input with type equal to image is clicked on. * A MouseListener is necessary since along with the image * data the coordinates associated with the mouse click * need to be submitted. */
protected class MouseEventListener extends MouseAdapter { public void mouseReleased(MouseEvent evt) { String imageData = getImageData(evt.getPoint()); imageSubmit(imageData); } }
This method is called to submit a form in response to a click on an image -- an <INPUT> form element of type "image".
Params:
  • imageData – the mouse click coordinates.
/** * This method is called to submit a form in response * to a click on an image -- an &lt;INPUT&gt; form * element of type "image". * * @param imageData the mouse click coordinates. */
protected void imageSubmit(String imageData) { StringBuilder dataBuffer = new StringBuilder(); Element elem = getElement(); HTMLDocument hdoc = (HTMLDocument)elem.getDocument(); getFormData(dataBuffer); if (dataBuffer.length() > 0) { dataBuffer.append('&'); } dataBuffer.append(imageData); submitData(dataBuffer.toString()); return; }
Extracts the value of the name attribute associated with the input element of type image. If name is defined it is encoded using the URLEncoder.encode() method and the image data is returned in the following format: name + ".x" +"="+ x +"&"+ name +".y"+"="+ y otherwise, "x="+ x +"&y="+ y
Params:
  • point – associated with the mouse click.
Returns:the image data.
/** * Extracts the value of the name attribute * associated with the input element of type * image. If name is defined it is encoded using * the URLEncoder.encode() method and the * image data is returned in the following format: * name + ".x" +"="+ x +"&"+ name +".y"+"="+ y * otherwise, * "x="+ x +"&y="+ y * * @param point associated with the mouse click. * @return the image data. */
private String getImageData(Point point) { String mouseCoords = point.x + ":" + point.y; int sep = mouseCoords.indexOf(':'); String x = mouseCoords.substring(0, sep); String y = mouseCoords.substring(++sep); String name = (String) getElement().getAttributes().getAttribute(HTML.Attribute.NAME); String data; if (name == null || name.equals("")) { data = "x="+ x +"&y="+ y; } else { name = URLEncoder.encode(name); data = name + ".x" +"="+ x +"&"+ name +".y"+"="+ y; } return data; } /** * The following methods provide functionality required to * iterate over a the elements of the form and in the case * of a form submission, extract the data from each model * that is associated with each form element, and in the * case of reset, reinitialize the each model to its * initial state. */
Returns the Element representing the FORM.
/** * Returns the Element representing the <code>FORM</code>. */
private Element getFormElement() { Element elem = getElement(); while (elem != null) { if (elem.getAttributes().getAttribute (StyleConstants.NameAttribute) == HTML.Tag.FORM) { return elem; } elem = elem.getParentElement(); } return null; }
Iterates over the element hierarchy, extracting data from the models associated with the relevant form elements. "Relevant" means the form elements that are part of the same form whose element triggered the submit action.
Params:
  • buffer – the buffer that contains that data to submit
  • targetElement – the element that triggered the form submission
/** * Iterates over the * element hierarchy, extracting data from the * models associated with the relevant form elements. * "Relevant" means the form elements that are part * of the same form whose element triggered the submit * action. * * @param buffer the buffer that contains that data to submit * @param targetElement the element that triggered the * form submission */
private void getFormData(StringBuilder buffer) { Element formE = getFormElement(); if (formE != null) { ElementIterator it = new ElementIterator(formE); Element next; while ((next = it.next()) != null) { if (isControl(next)) { String type = (String)next.getAttributes().getAttribute (HTML.Attribute.TYPE); if (type != null && type.equals("submit") && next != getElement()) { // do nothing - this submit is not the trigger } else if (type == null || !type.equals("image")) { // images only result in data if they triggered // the submit and they require that the mouse click // coords be appended to the data. Hence its // processing is handled by the view. loadElementDataIntoBuffer(next, buffer); } } } } }
Loads the data associated with the element into the buffer. The format in which data is appended depends on the type of the form element. Essentially data is loaded in name/value pairs.
/** * Loads the data * associated with the element into the buffer. * The format in which data is appended depends * on the type of the form element. Essentially * data is loaded in name/value pairs. * */
private void loadElementDataIntoBuffer(Element elem, StringBuilder buffer) { AttributeSet attr = elem.getAttributes(); String name = (String)attr.getAttribute(HTML.Attribute.NAME); if (name == null) { return; } String value = null; HTML.Tag tag = (HTML.Tag)elem.getAttributes().getAttribute (StyleConstants.NameAttribute); if (tag == HTML.Tag.INPUT) { value = getInputElementData(attr); } else if (tag == HTML.Tag.TEXTAREA) { value = getTextAreaData(attr); } else if (tag == HTML.Tag.SELECT) { loadSelectData(attr, buffer); } if (name != null && value != null) { appendBuffer(buffer, name, value); } }
Returns the data associated with an <INPUT> form element. The value of "type" attributes is used to determine the type of the model associated with the element and then the relevant data is extracted.
/** * Returns the data associated with an &lt;INPUT&gt; form * element. The value of "type" attributes is * used to determine the type of the model associated * with the element and then the relevant data is * extracted. */
private String getInputElementData(AttributeSet attr) { Object model = attr.getAttribute(StyleConstants.ModelAttribute); String type = (String) attr.getAttribute(HTML.Attribute.TYPE); String value = null; if (type.equals("text") || type.equals("password")) { Document doc = (Document)model; try { value = doc.getText(0, doc.getLength()); } catch (BadLocationException e) { value = null; } } else if (type.equals("submit") || type.equals("hidden")) { value = (String) attr.getAttribute(HTML.Attribute.VALUE); if (value == null) { value = ""; } } else if (type.equals("radio") || type.equals("checkbox")) { ButtonModel m = (ButtonModel)model; if (m.isSelected()) { value = (String) attr.getAttribute(HTML.Attribute.VALUE); if (value == null) { value = "on"; } } } else if (type.equals("file")) { Document doc = (Document)model; String path; try { path = doc.getText(0, doc.getLength()); } catch (BadLocationException e) { path = null; } if (path != null && path.length() > 0) { value = path; } } return value; }
Returns the data associated with the <TEXTAREA> form element. This is done by getting the text stored in the Document model.
/** * Returns the data associated with the &lt;TEXTAREA&gt; form * element. This is done by getting the text stored in the * Document model. */
private String getTextAreaData(AttributeSet attr) { Document doc = (Document)attr.getAttribute(StyleConstants.ModelAttribute); try { return doc.getText(0, doc.getLength()); } catch (BadLocationException e) { return null; } }
Loads the buffer with the data associated with the Select form element. Basically, only items that are selected and have their name attribute set are added to the buffer.
/** * Loads the buffer with the data associated with the Select * form element. Basically, only items that are selected * and have their name attribute set are added to the buffer. */
private void loadSelectData(AttributeSet attr, StringBuilder buffer) { String name = (String)attr.getAttribute(HTML.Attribute.NAME); if (name == null) { return; } Object m = attr.getAttribute(StyleConstants.ModelAttribute); if (m instanceof OptionListModel) { OptionListModel model = (OptionListModel)m; for (int i = 0; i < model.getSize(); i++) { if (model.isSelectedIndex(i)) { Option option = (Option) model.getElementAt(i); appendBuffer(buffer, name, option.getValue()); } } } else if (m instanceof ComboBoxModel) { ComboBoxModel model = (ComboBoxModel)m; Option option = (Option)model.getSelectedItem(); if (option != null) { appendBuffer(buffer, name, option.getValue()); } } }
Appends name / value pairs into the buffer. Both names and values are encoded using the URLEncoder.encode() method before being added to the buffer.
/** * Appends name / value pairs into the * buffer. Both names and values are encoded using the * URLEncoder.encode() method before being added to the * buffer. */
private void appendBuffer(StringBuilder buffer, String name, String value) { if (buffer.length() > 0) { buffer.append('&'); } String encodedName = URLEncoder.encode(name); buffer.append(encodedName); buffer.append('='); String encodedValue = URLEncoder.encode(value); buffer.append(encodedValue); }
Returns true if the Element elem represents a control.
/** * Returns true if the Element <code>elem</code> represents a control. */
private boolean isControl(Element elem) { return elem.isLeaf(); }
Iterates over the element hierarchy to determine if the element parameter, which is assumed to be an <INPUT> element of type password or text, is the last one of either kind, in the form to which it belongs.
/** * Iterates over the element hierarchy to determine if * the element parameter, which is assumed to be an * &lt;INPUT&gt; element of type password or text, is the last * one of either kind, in the form to which it belongs. */
boolean isLastTextOrPasswordField() { Element parent = getFormElement(); Element elem = getElement(); if (parent != null) { ElementIterator it = new ElementIterator(parent); Element next; boolean found = false; while ((next = it.next()) != null) { if (next == elem) { found = true; } else if (found && isControl(next)) { AttributeSet elemAttr = next.getAttributes(); if (HTMLDocument.matchNameAttribute (elemAttr, HTML.Tag.INPUT)) { String type = (String)elemAttr.getAttribute (HTML.Attribute.TYPE); if ("text".equals(type) || "password".equals(type)) { return false; } } } } } return true; }
Resets the form to its initial state by reinitializing the models associated with each form element to their initial values. param elem the element that triggered the reset
/** * Resets the form * to its initial state by reinitializing the models * associated with each form element to their initial * values. * * param elem the element that triggered the reset */
void resetForm() { Element parent = getFormElement(); if (parent != null) { ElementIterator it = new ElementIterator(parent); Element next; while((next = it.next()) != null) { if (isControl(next)) { AttributeSet elemAttr = next.getAttributes(); Object m = elemAttr.getAttribute(StyleConstants. ModelAttribute); if (m instanceof TextAreaDocument) { TextAreaDocument doc = (TextAreaDocument)m; doc.reset(); } else if (m instanceof PlainDocument) { try { PlainDocument doc = (PlainDocument)m; doc.remove(0, doc.getLength()); if (HTMLDocument.matchNameAttribute (elemAttr, HTML.Tag.INPUT)) { String value = (String)elemAttr. getAttribute(HTML.Attribute.VALUE); if (value != null) { doc.insertString(0, value, null); } } } catch (BadLocationException e) { } } else if (m instanceof OptionListModel) { OptionListModel model = (OptionListModel) m; int size = model.getSize(); for (int i = 0; i < size; i++) { model.removeIndexInterval(i, i); } BitSet selectionRange = model.getInitialSelection(); for (int i = 0; i < selectionRange.size(); i++) { if (selectionRange.get(i)) { model.addSelectionInterval(i, i); } } } else if (m instanceof OptionComboBoxModel) { OptionComboBoxModel model = (OptionComboBoxModel) m; Option option = model.getInitialSelection(); if (option != null) { model.setSelectedItem(option); } } else if (m instanceof JToggleButton.ToggleButtonModel) { boolean checked = ((String)elemAttr.getAttribute (HTML.Attribute.CHECKED) != null); JToggleButton.ToggleButtonModel model = (JToggleButton.ToggleButtonModel)m; model.setSelected(checked); } } } } }
BrowseFileAction is used for input type == file. When the user clicks the button a JFileChooser is brought up allowing the user to select a file in the file system. The resulting path to the selected file is set in the text field (actually an instance of Document).
/** * BrowseFileAction is used for input type == file. When the user * clicks the button a JFileChooser is brought up allowing the user * to select a file in the file system. The resulting path to the selected * file is set in the text field (actually an instance of Document). */
private class BrowseFileAction implements ActionListener { private AttributeSet attrs; private Document model; BrowseFileAction(AttributeSet attrs, Document model) { this.attrs = attrs; this.model = model; } public void actionPerformed(ActionEvent ae) { // PENDING: When mime support is added to JFileChooser use the // accept value of attrs. JFileChooser fc = new JFileChooser(); fc.setMultiSelectionEnabled(false); if (fc.showOpenDialog(getContainer()) == JFileChooser.APPROVE_OPTION) { File selected = fc.getSelectedFile(); if (selected != null) { try { if (model.getLength() > 0) { model.remove(0, model.getLength()); } model.insertString(0, selected.getPath(), null); } catch (BadLocationException ble) {} } } } } }