909 lines · 32.6 KB · Java
RawDownload
/* * 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, &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     */    @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     */    @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.     */    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.     */    private short maxIsPreferred;     /**     * 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.     */    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);        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 &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;    }      /**     * 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 processeing 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.     */    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.     */    protected class MouseEventListener extends MouseAdapter {         public void mouseReleased(MouseEvent evt) {            String imageData = getImageData(evt.getPoint());            imageSubmit(imageData);        }    }

Lines 1–500 of 909.