Home » openjdk-7 » javax » swing » text » html » [javadoc | source]

    1   /*
    2    * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package javax.swing.text.html;
   26   
   27   import java.net;
   28   import java.io;
   29   import java.awt;
   30   import java.awt.event;
   31   import java.util;
   32   import javax.swing;
   33   import javax.swing.event;
   34   import javax.swing.text;
   35   
   36   /**
   37    * Component decorator that implements the view interface
   38    * for form elements, <input>, <textarea>,
   39    * and <select>.  The model for the component is stored
   40    * as an attribute of the the element (using StyleConstants.ModelAttribute),
   41    * and is used to build the component of the view.  The type
   42    * of the model is assumed to of the type that would be set by
   43    * <code>HTMLDocument.HTMLReader.FormAction</code>.  If there are
   44    * multiple views mapped over the document, they will share the
   45    * embedded component models.
   46    * <p>
   47    * The following table shows what components get built
   48    * by this view.
   49    * <table summary="shows what components get built by this view">
   50    * <tr>
   51    *   <th>Element Type</th>
   52    *   <th>Component built</th>
   53    * </tr>
   54    * <tr>
   55    *   <td>input, type button</td>
   56    *   <td>JButton</td>
   57    * </tr>
   58    * <tr>
   59    *   <td>input, type checkbox</td>
   60    *   <td>JCheckBox</td>
   61    * </tr>
   62    * <tr>
   63    *   <td>input, type image</td>
   64    *   <td>JButton</td>
   65    * </tr>
   66    * <tr>
   67    *   <td>input, type password</td>
   68    *   <td>JPasswordField</td>
   69    * </tr>
   70    * <tr>
   71    *   <td>input, type radio</td>
   72    *   <td>JRadioButton</td>
   73    * </tr>
   74    * <tr>
   75    *   <td>input, type reset</td>
   76    *   <td>JButton</td>
   77    * </tr>
   78    * <tr>
   79    *   <td>input, type submit</td>
   80    *   <td>JButton</td>
   81    * </tr>
   82    * <tr>
   83    *   <td>input, type text</td>
   84    *   <td>JTextField</td>
   85    * </tr>
   86    * <tr>
   87    *   <td>select, size &gt; 1 or multiple attribute defined</td>
   88    *   <td>JList in a JScrollPane</td>
   89    * </tr>
   90    * <tr>
   91    *   <td>select, size unspecified or 1</td>
   92    *   <td>JComboBox</td>
   93    * </tr>
   94    * <tr>
   95    *   <td>textarea</td>
   96    *   <td>JTextArea in a JScrollPane</td>
   97    * </tr>
   98    * <tr>
   99    *   <td>input, type file</td>
  100    *   <td>JTextField</td>
  101    * </tr>
  102    * </table>
  103    *
  104    * @author Timothy Prinzing
  105    * @author Sunita Mani
  106    */
  107   public class FormView extends ComponentView implements ActionListener {
  108   
  109       /**
  110        * If a value attribute is not specified for a FORM input element
  111        * of type "submit", then this default string is used.
  112        *
  113        * @deprecated As of 1.3, value now comes from UIManager property
  114        *             FormView.submitButtonText
  115        */
  116       @Deprecated
  117       public static final String SUBMIT = new String("Submit Query");
  118       /**
  119        * If a value attribute is not specified for a FORM input element
  120        * of type "reset", then this default string is used.
  121        *
  122        * @deprecated As of 1.3, value comes from UIManager UIManager property
  123        *             FormView.resetButtonText
  124        */
  125       @Deprecated
  126       public static final String RESET = new String("Reset");
  127   
  128       /**
  129        * Document attribute name for storing POST data. JEditorPane.getPostData()
  130        * uses the same name, should be kept in sync.
  131        */
  132       final static String PostDataProperty = "javax.swing.JEditorPane.postdata";
  133   
  134       /**
  135        * Used to indicate if the maximum span should be the same as the
  136        * preferred span. This is used so that the Component's size doesn't
  137        * change if there is extra room on a line. The first bit is used for
  138        * the X direction, and the second for the y direction.
  139        */
  140       private short maxIsPreferred;
  141   
  142       /**
  143        * Creates a new FormView object.
  144        *
  145        * @param elem the element to decorate
  146        */
  147       public FormView(Element elem) {
  148           super(elem);
  149       }
  150   
  151       /**
  152        * Create the component.  This is basically a
  153        * big switch statement based upon the tag type
  154        * and html attributes of the associated element.
  155        */
  156       protected Component createComponent() {
  157           AttributeSet attr = getElement().getAttributes();
  158           HTML.Tag t = (HTML.Tag)
  159               attr.getAttribute(StyleConstants.NameAttribute);
  160           JComponent c = null;
  161           Object model = attr.getAttribute(StyleConstants.ModelAttribute);
  162           if (t == HTML.Tag.INPUT) {
  163               c = createInputComponent(attr, model);
  164           } else if (t == HTML.Tag.SELECT) {
  165   
  166               if (model instanceof OptionListModel) {
  167   
  168                   JList list = new JList((ListModel) model);
  169                   int size = HTML.getIntegerAttributeValue(attr,
  170                                                            HTML.Attribute.SIZE,
  171                                                            1);
  172                   list.setVisibleRowCount(size);
  173                   list.setSelectionModel((ListSelectionModel)model);
  174                   c = new JScrollPane(list);
  175               } else {
  176                   c = new JComboBox((ComboBoxModel) model);
  177                   maxIsPreferred = 3;
  178               }
  179           } else if (t == HTML.Tag.TEXTAREA) {
  180               JTextArea area = new JTextArea((Document) model);
  181               int rows = HTML.getIntegerAttributeValue(attr,
  182                                                        HTML.Attribute.ROWS,
  183                                                        1);
  184               area.setRows(rows);
  185               int cols = HTML.getIntegerAttributeValue(attr,
  186                                                        HTML.Attribute.COLS,
  187                                                        20);
  188               maxIsPreferred = 3;
  189               area.setColumns(cols);
  190               c = new JScrollPane(area,
  191                                   JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
  192                                   JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
  193           }
  194   
  195           if (c != null) {
  196               c.setAlignmentY(1.0f);
  197           }
  198           return c;
  199       }
  200   
  201   
  202       /**
  203        * Creates a component for an &lt;INPUT&gt; element based on the
  204        * value of the "type" attribute.
  205        *
  206        * @param set of attributes associated with the &lt;INPUT&gt; element.
  207        * @param model the value of the StyleConstants.ModelAttribute
  208        * @return the component.
  209        */
  210       private JComponent createInputComponent(AttributeSet attr, Object model) {
  211           JComponent c = null;
  212           String type = (String) attr.getAttribute(HTML.Attribute.TYPE);
  213   
  214           if (type.equals("submit") || type.equals("reset")) {
  215               String value = (String)
  216                   attr.getAttribute(HTML.Attribute.VALUE);
  217               if (value == null) {
  218                   if (type.equals("submit")) {
  219                       value = UIManager.getString("FormView.submitButtonText");
  220                   } else {
  221                       value = UIManager.getString("FormView.resetButtonText");
  222                   }
  223               }
  224               JButton button = new JButton(value);
  225               if (model != null) {
  226                   button.setModel((ButtonModel)model);
  227                   button.addActionListener(this);
  228               }
  229               c = button;
  230               maxIsPreferred = 3;
  231           } else if (type.equals("image")) {
  232               String srcAtt = (String) attr.getAttribute(HTML.Attribute.SRC);
  233               JButton button;
  234               try {
  235                   URL base = ((HTMLDocument)getElement().getDocument()).getBase();
  236                   URL srcURL = new URL(base, srcAtt);
  237                   Icon icon = new ImageIcon(srcURL);
  238                   button  = new JButton(icon);
  239               } catch (MalformedURLException e) {
  240                   button = new JButton(srcAtt);
  241               }
  242               if (model != null) {
  243                   button.setModel((ButtonModel)model);
  244                   button.addMouseListener(new MouseEventListener());
  245               }
  246               c = button;
  247               maxIsPreferred = 3;
  248           } else if (type.equals("checkbox")) {
  249               c = new JCheckBox();
  250               if (model != null) {
  251                   ((JCheckBox)c).setModel((JToggleButton.ToggleButtonModel) model);
  252               }
  253               maxIsPreferred = 3;
  254           } else if (type.equals("radio")) {
  255               c = new JRadioButton();
  256               if (model != null) {
  257                   ((JRadioButton)c).setModel((JToggleButton.ToggleButtonModel)model);
  258               }
  259               maxIsPreferred = 3;
  260           } else if (type.equals("text")) {
  261               int size = HTML.getIntegerAttributeValue(attr,
  262                                                        HTML.Attribute.SIZE,
  263                                                        -1);
  264               JTextField field;
  265               if (size > 0) {
  266                   field = new JTextField();
  267                   field.setColumns(size);
  268               }
  269               else {
  270                   field = new JTextField();
  271                   field.setColumns(20);
  272               }
  273               c = field;
  274               if (model != null) {
  275                   field.setDocument((Document) model);
  276               }
  277               field.addActionListener(this);
  278               maxIsPreferred = 3;
  279           } else if (type.equals("password")) {
  280               JPasswordField field = new JPasswordField();
  281               c = field;
  282               if (model != null) {
  283                   field.setDocument((Document) model);
  284               }
  285               int size = HTML.getIntegerAttributeValue(attr,
  286                                                        HTML.Attribute.SIZE,
  287                                                        -1);
  288               field.setColumns((size > 0) ? size : 20);
  289               field.addActionListener(this);
  290               maxIsPreferred = 3;
  291           } else if (type.equals("file")) {
  292               JTextField field = new JTextField();
  293               if (model != null) {
  294                   field.setDocument((Document)model);
  295               }
  296               int size = HTML.getIntegerAttributeValue(attr, HTML.Attribute.SIZE,
  297                                                        -1);
  298               field.setColumns((size > 0) ? size : 20);
  299               JButton browseButton = new JButton(UIManager.getString
  300                                              ("FormView.browseFileButtonText"));
  301               Box box = Box.createHorizontalBox();
  302               box.add(field);
  303               box.add(Box.createHorizontalStrut(5));
  304               box.add(browseButton);
  305               browseButton.addActionListener(new BrowseFileAction(
  306                                              attr, (Document)model));
  307               c = box;
  308               maxIsPreferred = 3;
  309           }
  310           return c;
  311       }
  312   
  313   
  314       /**
  315        * Determines the maximum span for this view along an
  316        * axis. For certain components, the maximum and preferred span are the
  317        * same. For others this will return the value
  318        * returned by Component.getMaximumSize along the
  319        * axis of interest.
  320        *
  321        * @param axis may be either View.X_AXIS or View.Y_AXIS
  322        * @return   the span the view would like to be rendered into >= 0.
  323        *           Typically the view is told to render into the span
  324        *           that is returned, although there is no guarantee.
  325        *           The parent may choose to resize or break the view.
  326        * @exception IllegalArgumentException for an invalid axis
  327        */
  328       public float getMaximumSpan(int axis) {
  329           switch (axis) {
  330           case View.X_AXIS:
  331               if ((maxIsPreferred & 1) == 1) {
  332                   super.getMaximumSpan(axis);
  333                   return getPreferredSpan(axis);
  334               }
  335               return super.getMaximumSpan(axis);
  336           case View.Y_AXIS:
  337               if ((maxIsPreferred & 2) == 2) {
  338                   super.getMaximumSpan(axis);
  339                   return getPreferredSpan(axis);
  340               }
  341               return super.getMaximumSpan(axis);
  342           default:
  343               break;
  344           }
  345           return super.getMaximumSpan(axis);
  346       }
  347   
  348   
  349       /**
  350        * Responsible for processeing the ActionEvent.
  351        * If the element associated with the FormView,
  352        * has a type of "submit", "reset", "text" or "password"
  353        * then the action is processed.  In the case of a "submit"
  354        * the form is submitted.  In the case of a "reset"
  355        * the form is reset to its original state.
  356        * In the case of "text" or "password", if the
  357        * element is the last one of type "text" or "password",
  358        * the form is submitted.  Otherwise, focus is transferred
  359        * to the next component in the form.
  360        *
  361        * @param evt the ActionEvent.
  362        */
  363       public void actionPerformed(ActionEvent evt) {
  364           Element element = getElement();
  365           StringBuilder dataBuffer = new StringBuilder();
  366           HTMLDocument doc = (HTMLDocument)getDocument();
  367           AttributeSet attr = element.getAttributes();
  368   
  369           String type = (String) attr.getAttribute(HTML.Attribute.TYPE);
  370   
  371           if (type.equals("submit")) {
  372               getFormData(dataBuffer);
  373               submitData(dataBuffer.toString());
  374           } else if (type.equals("reset")) {
  375               resetForm();
  376           } else if (type.equals("text") || type.equals("password")) {
  377               if (isLastTextOrPasswordField()) {
  378                   getFormData(dataBuffer);
  379                   submitData(dataBuffer.toString());
  380               } else {
  381                   getComponent().transferFocus();
  382               }
  383           }
  384       }
  385   
  386   
  387       /**
  388        * This method is responsible for submitting the form data.
  389        * A thread is forked to undertake the submission.
  390        */
  391       protected void submitData(String data) {
  392           Element form = getFormElement();
  393           AttributeSet attrs = form.getAttributes();
  394           HTMLDocument doc = (HTMLDocument) form.getDocument();
  395           URL base = doc.getBase();
  396   
  397           String target = (String) attrs.getAttribute(HTML.Attribute.TARGET);
  398           if (target == null) {
  399               target = "_self";
  400           }
  401   
  402           String method = (String) attrs.getAttribute(HTML.Attribute.METHOD);
  403           if (method == null) {
  404               method = "GET";
  405           }
  406           method = method.toLowerCase();
  407           boolean isPostMethod = method.equals("post");
  408           if (isPostMethod) {
  409               storePostData(doc, target, data);
  410           }
  411   
  412           String action = (String) attrs.getAttribute(HTML.Attribute.ACTION);
  413           URL actionURL;
  414           try {
  415               actionURL = (action == null)
  416                   ? new URL(base.getProtocol(), base.getHost(),
  417                                           base.getPort(), base.getFile())
  418                   : new URL(base, action);
  419               if (!isPostMethod) {
  420                   String query = data.toString();
  421                   actionURL = new URL(actionURL + "?" + query);
  422               }
  423           } catch (MalformedURLException e) {
  424               actionURL = null;
  425           }
  426           final JEditorPane c = (JEditorPane) getContainer();
  427           HTMLEditorKit kit = (HTMLEditorKit) c.getEditorKit();
  428   
  429           FormSubmitEvent formEvent = null;
  430           if (!kit.isAutoFormSubmission() || doc.isFrameDocument()) {
  431               FormSubmitEvent.MethodType methodType = isPostMethod
  432                       ? FormSubmitEvent.MethodType.POST
  433                       : FormSubmitEvent.MethodType.GET;
  434               formEvent = new FormSubmitEvent(
  435                       FormView.this, HyperlinkEvent.EventType.ACTIVATED,
  436                       actionURL, form, target, methodType, data);
  437   
  438           }
  439           // setPage() may take significant time so schedule it to run later.
  440           final FormSubmitEvent fse = formEvent;
  441           final URL url = actionURL;
  442           SwingUtilities.invokeLater(new Runnable() {
  443               public void run() {
  444                   if (fse != null) {
  445                       c.fireHyperlinkUpdate(fse);
  446                   } else {
  447                       try {
  448                           c.setPage(url);
  449                       } catch (IOException e) {
  450                           UIManager.getLookAndFeel().provideErrorFeedback(c);
  451                       }
  452                   }
  453               }
  454           });
  455       }
  456   
  457       private void storePostData(HTMLDocument doc, String target, String data) {
  458   
  459           /* POST data is stored into the document property named by constant
  460            * PostDataProperty from where it is later retrieved by method
  461            * JEditorPane.getPostData().  If the current document is in a frame,
  462            * the data is initially put into the toplevel (frameset) document
  463            * property (named <PostDataProperty>.<Target frame name>).  It is the
  464            * responsibility of FrameView which updates the target frame
  465            * to move data from the frameset document property into the frame
  466            * document property.
  467            */
  468   
  469           Document propDoc = doc;
  470           String propName = PostDataProperty;
  471   
  472           if (doc.isFrameDocument()) {
  473               // find the top-most JEditorPane holding the frameset view.
  474               FrameView.FrameEditorPane p =
  475                       (FrameView.FrameEditorPane) getContainer();
  476               FrameView v = p.getFrameView();
  477               JEditorPane c = v.getOutermostJEditorPane();
  478               if (c != null) {
  479                   propDoc = c.getDocument();
  480                   propName += ("." + target);
  481               }
  482           }
  483   
  484           propDoc.putProperty(propName, data);
  485       }
  486   
  487       /**
  488        * MouseEventListener class to handle form submissions when
  489        * an input with type equal to image is clicked on.
  490        * A MouseListener is necessary since along with the image
  491        * data the coordinates associated with the mouse click
  492        * need to be submitted.
  493        */
  494       protected class MouseEventListener extends MouseAdapter {
  495   
  496           public void mouseReleased(MouseEvent evt) {
  497               String imageData = getImageData(evt.getPoint());
  498               imageSubmit(imageData);
  499           }
  500       }
  501   
  502       /**
  503        * This method is called to submit a form in response
  504        * to a click on an image -- an &lt;INPUT&gt; form
  505        * element of type "image".
  506        *
  507        * @param imageData the mouse click coordinates.
  508        */
  509       protected void imageSubmit(String imageData) {
  510   
  511           StringBuilder dataBuffer = new StringBuilder();
  512           Element elem = getElement();
  513           HTMLDocument hdoc = (HTMLDocument)elem.getDocument();
  514           getFormData(dataBuffer);
  515           if (dataBuffer.length() > 0) {
  516               dataBuffer.append('&');
  517           }
  518           dataBuffer.append(imageData);
  519           submitData(dataBuffer.toString());
  520           return;
  521       }
  522   
  523       /**
  524        * Extracts the value of the name attribute
  525        * associated with the input element of type
  526        * image.  If name is defined it is encoded using
  527        * the URLEncoder.encode() method and the
  528        * image data is returned in the following format:
  529        *      name + ".x" +"="+ x +"&"+ name +".y"+"="+ y
  530        * otherwise,
  531        *      "x="+ x +"&y="+ y
  532        *
  533        * @param point associated with the mouse click.
  534        * @return the image data.
  535        */
  536       private String getImageData(Point point) {
  537   
  538           String mouseCoords = point.x + ":" + point.y;
  539           int sep = mouseCoords.indexOf(':');
  540           String x = mouseCoords.substring(0, sep);
  541           String y = mouseCoords.substring(++sep);
  542           String name = (String) getElement().getAttributes().getAttribute(HTML.Attribute.NAME);
  543   
  544           String data;
  545           if (name == null || name.equals("")) {
  546               data = "x="+ x +"&y="+ y;
  547           } else {
  548               name = URLEncoder.encode(name);
  549               data = name + ".x" +"="+ x +"&"+ name +".y"+"="+ y;
  550           }
  551           return data;
  552       }
  553   
  554   
  555       /**
  556        * The following methods provide functionality required to
  557        * iterate over a the elements of the form and in the case
  558        * of a form submission, extract the data from each model
  559        * that is associated with each form element, and in the
  560        * case of reset, reinitialize the each model to its
  561        * initial state.
  562        */
  563   
  564   
  565       /**
  566        * Returns the Element representing the <code>FORM</code>.
  567        */
  568       private Element getFormElement() {
  569           Element elem = getElement();
  570           while (elem != null) {
  571               if (elem.getAttributes().getAttribute
  572                   (StyleConstants.NameAttribute) == HTML.Tag.FORM) {
  573                   return elem;
  574               }
  575               elem = elem.getParentElement();
  576           }
  577           return null;
  578       }
  579   
  580       /**
  581        * Iterates over the
  582        * element hierarchy, extracting data from the
  583        * models associated with the relevant form elements.
  584        * "Relevant" means the form elements that are part
  585        * of the same form whose element triggered the submit
  586        * action.
  587        *
  588        * @param buffer        the buffer that contains that data to submit
  589        * @param targetElement the element that triggered the
  590        *                      form submission
  591        */
  592       private void getFormData(StringBuilder buffer) {
  593           Element formE = getFormElement();
  594           if (formE != null) {
  595               ElementIterator it = new ElementIterator(formE);
  596               Element next;
  597   
  598               while ((next = it.next()) != null) {
  599                   if (isControl(next)) {
  600                       String type = (String)next.getAttributes().getAttribute
  601                                          (HTML.Attribute.TYPE);
  602   
  603                       if (type != null && type.equals("submit") &&
  604                           next != getElement()) {
  605                           // do nothing - this submit isnt the trigger
  606                       } else if (type == null || !type.equals("image")) {
  607                           // images only result in data if they triggered
  608                           // the submit and they require that the mouse click
  609                           // coords be appended to the data.  Hence its
  610                           // processing is handled by the view.
  611                           loadElementDataIntoBuffer(next, buffer);
  612                       }
  613                   }
  614               }
  615           }
  616       }
  617   
  618       /**
  619        * Loads the data
  620        * associated with the element into the buffer.
  621        * The format in which data is appended depends
  622        * on the type of the form element.  Essentially
  623        * data is loaded in name/value pairs.
  624        *
  625        */
  626       private void loadElementDataIntoBuffer(Element elem, StringBuilder buffer) {
  627   
  628           AttributeSet attr = elem.getAttributes();
  629           String name = (String)attr.getAttribute(HTML.Attribute.NAME);
  630           if (name == null) {
  631               return;
  632           }
  633           String value = null;
  634           HTML.Tag tag = (HTML.Tag)elem.getAttributes().getAttribute
  635                                     (StyleConstants.NameAttribute);
  636   
  637           if (tag == HTML.Tag.INPUT) {
  638               value = getInputElementData(attr);
  639           } else if (tag ==  HTML.Tag.TEXTAREA) {
  640               value = getTextAreaData(attr);
  641           } else if (tag == HTML.Tag.SELECT) {
  642               loadSelectData(attr, buffer);
  643           }
  644   
  645           if (name != null && value != null) {
  646               appendBuffer(buffer, name, value);
  647           }
  648       }
  649   
  650   
  651       /**
  652        * Returns the data associated with an &lt;INPUT&gt; form
  653        * element.  The value of "type" attributes is
  654        * used to determine the type of the model associated
  655        * with the element and then the relevant data is
  656        * extracted.
  657        */
  658       private String getInputElementData(AttributeSet attr) {
  659   
  660           Object model = attr.getAttribute(StyleConstants.ModelAttribute);
  661           String type = (String) attr.getAttribute(HTML.Attribute.TYPE);
  662           String value = null;
  663   
  664           if (type.equals("text") || type.equals("password")) {
  665               Document doc = (Document)model;
  666               try {
  667                   value = doc.getText(0, doc.getLength());
  668               } catch (BadLocationException e) {
  669                   value = null;
  670               }
  671           } else if (type.equals("submit") || type.equals("hidden")) {
  672               value = (String) attr.getAttribute(HTML.Attribute.VALUE);
  673               if (value == null) {
  674                   value = "";
  675               }
  676           } else if (type.equals("radio") || type.equals("checkbox")) {
  677               ButtonModel m = (ButtonModel)model;
  678               if (m.isSelected()) {
  679                   value = (String) attr.getAttribute(HTML.Attribute.VALUE);
  680                   if (value == null) {
  681                       value = "on";
  682                   }
  683               }
  684           } else if (type.equals("file")) {
  685               Document doc = (Document)model;
  686               String path;
  687   
  688               try {
  689                   path = doc.getText(0, doc.getLength());
  690               } catch (BadLocationException e) {
  691                   path = null;
  692               }
  693               if (path != null && path.length() > 0) {
  694                   value = path;
  695               }
  696           }
  697           return value;
  698       }
  699   
  700       /**
  701        * Returns the data associated with the &lt;TEXTAREA&gt; form
  702        * element.  This is done by getting the text stored in the
  703        * Document model.
  704        */
  705       private String getTextAreaData(AttributeSet attr) {
  706           Document doc = (Document)attr.getAttribute(StyleConstants.ModelAttribute);
  707           try {
  708               return doc.getText(0, doc.getLength());
  709           } catch (BadLocationException e) {
  710               return null;
  711           }
  712       }
  713   
  714   
  715       /**
  716        * Loads the buffer with the data associated with the Select
  717        * form element.  Basically, only items that are selected
  718        * and have their name attribute set are added to the buffer.
  719        */
  720       private void loadSelectData(AttributeSet attr, StringBuilder buffer) {
  721   
  722           String name = (String)attr.getAttribute(HTML.Attribute.NAME);
  723           if (name == null) {
  724               return;
  725           }
  726           Object m = attr.getAttribute(StyleConstants.ModelAttribute);
  727           if (m instanceof OptionListModel) {
  728               OptionListModel model = (OptionListModel)m;
  729   
  730               for (int i = 0; i < model.getSize(); i++) {
  731                   if (model.isSelectedIndex(i)) {
  732                       Option option = (Option) model.getElementAt(i);
  733                       appendBuffer(buffer, name, option.getValue());
  734                   }
  735               }
  736           } else if (m instanceof ComboBoxModel) {
  737               ComboBoxModel model = (ComboBoxModel)m;
  738               Option option = (Option)model.getSelectedItem();
  739               if (option != null) {
  740                   appendBuffer(buffer, name, option.getValue());
  741               }
  742           }
  743       }
  744   
  745       /**
  746        * Appends name / value pairs into the
  747        * buffer.  Both names and values are encoded using the
  748        * URLEncoder.encode() method before being added to the
  749        * buffer.
  750        */
  751       private void appendBuffer(StringBuilder buffer, String name, String value) {
  752           if (buffer.length() > 0) {
  753               buffer.append('&');
  754           }
  755           String encodedName = URLEncoder.encode(name);
  756           buffer.append(encodedName);
  757           buffer.append('=');
  758           String encodedValue = URLEncoder.encode(value);
  759           buffer.append(encodedValue);
  760       }
  761   
  762       /**
  763        * Returns true if the Element <code>elem</code> represents a control.
  764        */
  765       private boolean isControl(Element elem) {
  766           return elem.isLeaf();
  767       }
  768   
  769       /**
  770        * Iterates over the element hierarchy to determine if
  771        * the element parameter, which is assumed to be an
  772        * &lt;INPUT&gt; element of type password or text, is the last
  773        * one of either kind, in the form to which it belongs.
  774        */
  775       boolean isLastTextOrPasswordField() {
  776           Element parent = getFormElement();
  777           Element elem = getElement();
  778   
  779           if (parent != null) {
  780               ElementIterator it = new ElementIterator(parent);
  781               Element next;
  782               boolean found = false;
  783   
  784               while ((next = it.next()) != null) {
  785                   if (next == elem) {
  786                       found = true;
  787                   }
  788                   else if (found && isControl(next)) {
  789                       AttributeSet elemAttr = next.getAttributes();
  790   
  791                       if (HTMLDocument.matchNameAttribute
  792                                        (elemAttr, HTML.Tag.INPUT)) {
  793                           String type = (String)elemAttr.getAttribute
  794                                                     (HTML.Attribute.TYPE);
  795   
  796                           if ("text".equals(type) || "password".equals(type)) {
  797                               return false;
  798                           }
  799                       }
  800                   }
  801               }
  802           }
  803           return true;
  804       }
  805   
  806       /**
  807        * Resets the form
  808        * to its initial state by reinitializing the models
  809        * associated with each form element to their initial
  810        * values.
  811        *
  812        * param elem the element that triggered the reset
  813        */
  814       void resetForm() {
  815           Element parent = getFormElement();
  816   
  817           if (parent != null) {
  818               ElementIterator it = new ElementIterator(parent);
  819               Element next;
  820   
  821               while((next = it.next()) != null) {
  822                   if (isControl(next)) {
  823                       AttributeSet elemAttr = next.getAttributes();
  824                       Object m = elemAttr.getAttribute(StyleConstants.
  825                                                        ModelAttribute);
  826                       if (m instanceof TextAreaDocument) {
  827                           TextAreaDocument doc = (TextAreaDocument)m;
  828                           doc.reset();
  829                       } else if (m instanceof PlainDocument) {
  830                           try {
  831                               PlainDocument doc =  (PlainDocument)m;
  832                               doc.remove(0, doc.getLength());
  833                               if (HTMLDocument.matchNameAttribute
  834                                                (elemAttr, HTML.Tag.INPUT)) {
  835                                   String value = (String)elemAttr.
  836                                              getAttribute(HTML.Attribute.VALUE);
  837                                   if (value != null) {
  838                                       doc.insertString(0, value, null);
  839                                   }
  840                               }
  841                           } catch (BadLocationException e) {
  842                           }
  843                       } else if (m instanceof OptionListModel) {
  844                           OptionListModel model = (OptionListModel) m;
  845                           int size = model.getSize();
  846                           for (int i = 0; i < size; i++) {
  847                               model.removeIndexInterval(i, i);
  848                           }
  849                           BitSet selectionRange = model.getInitialSelection();
  850                           for (int i = 0; i < selectionRange.size(); i++) {
  851                               if (selectionRange.get(i)) {
  852                                   model.addSelectionInterval(i, i);
  853                               }
  854                           }
  855                       } else if (m instanceof OptionComboBoxModel) {
  856                           OptionComboBoxModel model = (OptionComboBoxModel) m;
  857                           Option option = model.getInitialSelection();
  858                           if (option != null) {
  859                               model.setSelectedItem(option);
  860                           }
  861                       } else if (m instanceof JToggleButton.ToggleButtonModel) {
  862                           boolean checked = ((String)elemAttr.getAttribute
  863                                              (HTML.Attribute.CHECKED) != null);
  864                           JToggleButton.ToggleButtonModel model =
  865                                           (JToggleButton.ToggleButtonModel)m;
  866                           model.setSelected(checked);
  867                       }
  868                   }
  869               }
  870           }
  871       }
  872   
  873   
  874       /**
  875        * BrowseFileAction is used for input type == file. When the user
  876        * clicks the button a JFileChooser is brought up allowing the user
  877        * to select a file in the file system. The resulting path to the selected
  878        * file is set in the text field (actually an instance of Document).
  879        */
  880       private class BrowseFileAction implements ActionListener {
  881           private AttributeSet attrs;
  882           private Document model;
  883   
  884           BrowseFileAction(AttributeSet attrs, Document model) {
  885               this.attrs = attrs;
  886               this.model = model;
  887           }
  888   
  889           public void actionPerformed(ActionEvent ae) {
  890               // PENDING: When mime support is added to JFileChooser use the
  891               // accept value of attrs.
  892               JFileChooser fc = new JFileChooser();
  893               fc.setMultiSelectionEnabled(false);
  894               if (fc.showOpenDialog(getContainer()) ==
  895                     JFileChooser.APPROVE_OPTION) {
  896                   File selected = fc.getSelectedFile();
  897   
  898                   if (selected != null) {
  899                       try {
  900                           if (model.getLength() > 0) {
  901                               model.remove(0, model.getLength());
  902                           }
  903                           model.insertString(0, selected.getPath(), null);
  904                       } catch (BadLocationException ble) {}
  905                   }
  906               }
  907           }
  908       }
  909   }

Home » openjdk-7 » javax » swing » text » html » [javadoc | source]