home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / JTextField.java < prev    next >
Text File  |  1998-02-26  |  16KB  |  522 lines

  1. /*
  2.  * @(#)JTextField.java    1.44 98/02/12
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20. package com.sun.java.swing;
  21.  
  22. import java.awt.*;
  23. import java.awt.event.*;
  24. import com.sun.java.swing.text.*;
  25. import com.sun.java.swing.plaf.*;
  26. import com.sun.java.swing.event.*;
  27. import com.sun.java.accessibility.*;
  28.  
  29. /**
  30.  * JTextField is a lightweight component that allows the editing 
  31.  * of a single line of text.  It is intended to be source-compatible
  32.  * with java.awt.TextField where it is reasonable to do so.  This
  33.  * component has capabilities not found in the java.awt.TextField 
  34.  * class.  The superclass should be consulted for additional capabilities.
  35.  * <p>
  36.  * JTextField has a method to establish the string used as the
  37.  * command string for the action event that gets fired.  The
  38.  * java.awt.TextField used the text of the field as the command
  39.  * string for the ActionEvent.  JTextField will use the command
  40.  * string set with the <code>setActionCommand</code> method if not null, 
  41.  * otherwise it will use the text of the field as a compatibility with 
  42.  * java.awt.TextField.
  43.  * <p>
  44.  * The method <code>setEchoChar</code> and <code>getEchoChar</code>
  45.  * are not provided directly to avoid a new implementation of a
  46.  * pluggable look-and-feel inadvertantly exposing password characters.
  47.  * To provide password-like services a seperate class JPasswordField
  48.  * extends JTextField to provide this service with an independantly
  49.  * pluggable look-and-feel.
  50.  * <p>
  51.  * The java.awt.TextField could be monitored for changes by adding
  52.  * a TextListener for TextEvent's.  In the JTextComponent based
  53.  * components, changes are broadcasted from the model via a
  54.  * DocumentEvent to DocumentListeners.  The DocumentEvent gives 
  55.  * the location of the change and the kind of change if desired.
  56.  * The code fragment might look something like:
  57.  * <pre><code>
  58.  *    DocumentListener myListener = ??;
  59.  *    JTextField myArea = ??;
  60.  *    myArea.getDocument().addDocumentListener(myListener);
  61.  * </code></pre>
  62.  * <p>
  63.  * The horizontal alignment of JTextField can be set to be left
  64.  * justified, centered, or right justified if the required size
  65.  * of the field text is smaller than the size allocated to it.
  66.  * This is determined by the <code>setHorizontalAlignment</code>
  67.  * and <code>getHorizontalAlignment</code> methods.  The default
  68.  * is to be left justified.
  69.  * <p>
  70.  * Warning: serialized objects of this class will not be compatible with
  71.  * future swing releases.  The current serialization support is appropriate
  72.  * for short term storage or RMI between Swing1.0 applications.  It will
  73.  * not be possible to load serialized Swing1.0 objects with future releases
  74.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  75.  * baseline for the serialized form of Swing objects.
  76.  *
  77.  * @beaninfo
  78.  *   attribute: isContainer false
  79.  *
  80.  * @author  Timothy Prinzing
  81.  * @version 1.44 02/12/98
  82.  * @see #setActionCommand
  83.  * @see JPasswordField
  84.  */
  85. public class JTextField extends JTextComponent implements SwingConstants {
  86.  
  87.     /**
  88.      * Constructs a new TextField.
  89.      */
  90.     public JTextField() {
  91.     this(null, null, 0);
  92.     }
  93.  
  94.     /**
  95.      * Constructs a new TextField initialized with the specified text.
  96.      *
  97.      * @param text the text to be displayed
  98.      */
  99.     public JTextField(String text) {
  100.     this(null, text, 0);
  101.     }
  102.  
  103.     /**
  104.      * Constructs a new empty TextField with the specified number of columns.
  105.      *
  106.      * @param columns the number of columns
  107.      */ 
  108.     public JTextField(int columns) {
  109.     this(null, null, columns);
  110.     }
  111.  
  112.     /**
  113.      * Constructs a new TextField initialized with the specified text
  114.      * and columns.
  115.      *
  116.      * @param text the text to be displayed
  117.      * @param columns the number of columns
  118.      */
  119.     public JTextField(String text, int columns) {
  120.     this(null, text, columns);
  121.     }
  122.  
  123.     /**
  124.      * Constructs a new JTextField that uses the given text storage
  125.      * model and the given number of columns.  This is the constructor
  126.      * through which the other constructors feed.
  127.      *
  128.      * @param doc  the text storage to use
  129.      * @param text  the initial string to display
  130.      * @param columns  the number of columns to use to calculate 
  131.      *   the preferred width.  If columns is set to zero, the
  132.      *   preferred width will be whatever naturally results from
  133.      *   the component implementation.
  134.      */
  135.     public JTextField(Document doc, String text, int columns) {
  136.     setName(base + nameCounter++);
  137.     if (columns < 0) {
  138.         throw new IllegalArgumentException("columns less than zero.");
  139.     }
  140.     visibility = new DefaultBoundedRangeModel();
  141.     visibility.addChangeListener(new ScrollRepainter());
  142.     this.columns = columns;
  143.     if (doc == null) {
  144.         doc = createDefaultModel();
  145.     }
  146.     setDocument(doc);
  147.     if (text != null) {
  148.         setText(text);
  149.     }
  150.     }
  151.  
  152.     /**
  153.      * Gets the class ID for a UI.
  154.      *
  155.      * @return the ID
  156.      * @see JComponent#getUIClassID
  157.      * @see UIDefaults#getUI
  158.      */
  159.     public String getUIClassID() {
  160.     return "TextFieldUI";
  161.     }
  162.  
  163.     /**
  164.      * Returns the horizontal alignment of the text.
  165.      * Valid keys: LEFT (the default), CENTER, RIGHT.
  166.      *
  167.      * @return the alignment
  168.      */
  169.     public int getHorizontalAlignment() {
  170.     return horizontalAlignment;
  171.     }
  172.     
  173.     /**
  174.      * Sets the horizontal alignment of the text.
  175.      * Valid keys: LEFT (the default), CENTER, RIGHT.
  176.      *
  177.      * @param alignment the alignment
  178.      * @exception IllegalArgumentException if the alignment
  179.      *  specified is not a valid key.
  180.      * @beaninfo
  181.      *   preferred: true
  182.      *       bound: true
  183.      * description: Set the field alignment to LEFT (the default), CENTER, RIGHT
  184.      *        enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT
  185.      */
  186.     public void setHorizontalAlignment(int alignment) {
  187.     if (alignment == horizontalAlignment) return;
  188.     int oldValue = horizontalAlignment;
  189.     if ((alignment == LEFT) || (alignment == CENTER) || (alignment == RIGHT)) {
  190.         horizontalAlignment = alignment;
  191.     } else {
  192.         throw new IllegalArgumentException("horizontalAlignment");
  193.     }
  194.     firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);    
  195.     invalidate();
  196.     repaint();
  197.     }
  198.  
  199.     /**
  200.      * Creates the default implementation of the model
  201.      * to be used at construction if one isn't explicitly 
  202.      * given.
  203.      *
  204.      * @return the default model implementation
  205.      */
  206.     protected Document createDefaultModel() {
  207.     return new PlainDocument();
  208.     }
  209.  
  210.     /**
  211.      * Returns the number of columns in this TextField.
  212.      *
  213.      * @return the number of columns
  214.      */
  215.     public int getColumns() {
  216.     return columns;
  217.     }
  218.  
  219.     /**
  220.      * Sets the number of columns in this TextField.
  221.      *
  222.      * @param columns the number of columns
  223.      * @exception IllegalArgumentException if columns is less than 0
  224.      * @beaninfo
  225.      * description: the number of columns preferred for display
  226.      */
  227.     public void setColumns(int columns) {
  228.     int oldVal = this.columns;
  229.     if (columns < 0) {
  230.         throw new IllegalArgumentException("columns less than zero.");
  231.     }
  232.     if (columns != oldVal) {
  233.         this.columns = columns;
  234.         invalidate();
  235.     }
  236.     }
  237.  
  238.     /**
  239.      * Gets the column width.
  240.      * The meaning of what a column is can be considered a fairly weak
  241.      * notion for some fonts.  This method is used to define the width
  242.      * of a column.  By default this is defined to be the width of the
  243.      * character <em>m</em> for the font used.  This method can be 
  244.      * redefined to be some alternative amount
  245.      *
  246.      * @return the column width
  247.      */
  248.     protected int getColumnWidth() {
  249.     if (columnWidth == 0) {
  250.         FontMetrics metrics = getFontMetrics(getFont());
  251.         columnWidth = metrics.charWidth('m');
  252.     }
  253.     return columnWidth;
  254.     }
  255.  
  256.     /**
  257.      * Returns the preferred size Dimensions needed for this 
  258.      * TextField.  If a non-zero number of columns has been
  259.      * set, the width is set to the columns multiplied by
  260.      * the column width. 
  261.      *
  262.      * @return the dimensions
  263.      */
  264.     public Dimension getPreferredSize() {
  265.      synchronized (getTreeLock()) {
  266.         Dimension size = super.getPreferredSize();
  267.         if (columns != 0) {
  268.         size.width = columns * getColumnWidth();
  269.         }
  270.         return size;
  271.     }
  272.     }
  273.  
  274.     /**
  275.      * Returns the minimum size Dimensions needed for this 
  276.      * TextField.  This defaults to the preferred size.
  277.      *
  278.      * @return the dimensions
  279.      */
  280.     public Dimension getMinimumSize() {
  281.     return getPreferredSize();
  282.     }
  283.  
  284.     /**
  285.      * Sets the current font.  This removes cached row height and column
  286.      * width so the new font will be reflected.
  287.      *
  288.      * @param f the new font
  289.      */
  290.     public void setFont(Font f) {
  291.     super.setFont(f);
  292.     columnWidth = 0;
  293.     revalidate();
  294.     }
  295.  
  296.     /**
  297.      * Adds the specified action listener to receive 
  298.      * action events from this textfield.
  299.      *
  300.      * @param l the action listener
  301.      */ 
  302.     public synchronized void addActionListener(ActionListener l) {
  303.     listenerList.add(ActionListener.class, l);
  304.     }
  305.  
  306.     /**
  307.      * Removes the specified action listener so that it no longer
  308.      * receives action events from this textfield.
  309.      *
  310.      * @param l the action listener 
  311.      */ 
  312.     public synchronized void removeActionListener(ActionListener l) {
  313.     listenerList.remove(ActionListener.class, l);
  314.     }
  315.  
  316.     /**
  317.      * Notifies all listeners that have registered interest for
  318.      * notification on this event type.  The event instance 
  319.      * is lazily created using the parameters passed into 
  320.      * the fire method.
  321.      * @see EventListenerList
  322.      */
  323.     protected void fireActionPerformed() {
  324.     // Guaranteed to return a non-null array
  325.     Object[] listeners = listenerList.getListenerList();
  326.     ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
  327.                     (command != null) ? command : getText());
  328.     // Process the listeners last to first, notifying
  329.     // those that are interested in this event
  330.     for (int i = listeners.length-2; i>=0; i-=2) {
  331.         if (listeners[i]==ActionListener.class) {
  332.         ((ActionListener)listeners[i+1]).actionPerformed(e);
  333.         }           
  334.     }
  335.     }
  336.  
  337.     /**
  338.      * Sets the command string used for action events.
  339.      *
  340.      * @param command the command string
  341.      */
  342.     public void setActionCommand(String command) {
  343.     this.command = command;
  344.     }
  345.  
  346.     /**
  347.      * Fetches the command list for the editor.  This is
  348.      * the list of commands supported by the plugged-in UI
  349.      * augmented by the collection of commands that the
  350.      * editor itself supports.  These are useful for binding
  351.      * to events, such as in a keymap.
  352.      *
  353.      * @return the command list
  354.      */
  355.     public Action[] getActions() {
  356.     return TextAction.augmentList(super.getActions(), defaultActions);
  357.     }
  358.  
  359.     /** 
  360.      * Processes action events occurring on this textfield by
  361.      * dispatching them to any registered ActionListener objects.
  362.      * This is normally called by the controller registered with
  363.      * textfield.
  364.      */  
  365.     public void postActionEvent() {
  366.     fireActionPerformed();
  367.     }
  368.  
  369.     /**
  370.      * Returns the String of parameters for this JTextField.
  371.      *
  372.      * @return the string of parameters
  373.      */
  374.     protected String paramString() {
  375.     return super.paramString() + ",columns=" + columns + 
  376.         ",command=" + command;
  377.     }
  378.  
  379.     // --- Scrolling support -----------------------------------
  380.  
  381.     /**
  382.      * Gets the visibility of the text field.  This can
  383.      * be adjusted to change the location of the visible
  384.      * area if the size of the field is greater than
  385.      * the area that was allocated to the field.
  386.      *
  387.      * The fields look-and-feel implementation manages
  388.      * the values of the minimum, maximum, and extent
  389.      * properties on the BoundedRangeModel.
  390.      * 
  391.      * @return the visibility
  392.      * @see BoundedRangeModel
  393.      */
  394.     public BoundedRangeModel getHorizontalVisibility() {
  395.     return visibility;
  396.     }
  397.  
  398.     /**
  399.      * Gets the scroll offset.
  400.      *
  401.      * @return the offset
  402.      */
  403.     public int getScrollOffset() {
  404.     return visibility.getValue();
  405.     }
  406.  
  407.     /**
  408.      * Sets the scroll offset.
  409.      *
  410.      * @param scrollOffset the offset
  411.      */
  412.     public void setScrollOffset(int scrollOffset) {
  413.     visibility.setValue(scrollOffset);
  414.     }
  415.     
  416.     /**
  417.      * Scrolls the field left or right.
  418.      *
  419.      * @param r the region to scroll
  420.      */
  421.     public void scrollRectToVisible(Rectangle r) {
  422.         // convert to coordinate system of the bounded range
  423.         int x = r.x + visibility.getValue();
  424.     if (x < visibility.getValue()) {
  425.         // Scroll to the left
  426.         visibility.setValue(x - 2);
  427.     } else if(x > visibility.getValue() + visibility.getExtent()) {
  428.         // Scroll to the right
  429.         visibility.setValue(x - visibility.getExtent() + 2);
  430.     }
  431.     }
  432.  
  433.     // --- variables -------------------------------------------
  434.  
  435.     /**
  436.      * Name of the action to send notification that the
  437.      * contents of the field have been accepted.  Typically
  438.      * this is bound to a carriage-return.
  439.      */
  440.     public static final String notifyAction = "notify-field-accept";
  441.  
  442.     private BoundedRangeModel visibility;
  443.     private int horizontalAlignment  = LEFT;
  444.     private int columns;
  445.     private int columnWidth;
  446.     private String command;
  447.     private static final String base = "textfield";
  448.     private static int nameCounter = 0;
  449.  
  450.     private static final Action[] defaultActions = {
  451.     new NotifyAction()
  452.     };
  453.  
  454.     // --- Action implementations -----------------------------------
  455.  
  456.     static class NotifyAction extends TextAction {
  457.  
  458.     NotifyAction() {
  459.         super(notifyAction);
  460.     }
  461.  
  462.         public void actionPerformed(ActionEvent e) {
  463.         JTextComponent target = getFocusedComponent();
  464.         if (target instanceof JTextField) {
  465.         JTextField field = (JTextField) target;
  466.         field.postActionEvent();
  467.         }
  468.     }
  469.     }
  470.  
  471.     class ScrollRepainter implements ChangeListener {
  472.  
  473.         public void stateChanged(ChangeEvent e) {
  474.         repaint();
  475.     }
  476.  
  477.     }
  478.  
  479. /////////////////
  480. // Accessibility support
  481. ////////////////
  482.  
  483.  
  484.     /**
  485.      * Get the AccessibleContext associated with this JTextField
  486.      *
  487.      * @return the AccessibleContext of this JTextField
  488.      */
  489.     public AccessibleContext getAccessibleContext() {
  490.         if (accessibleContext == null) {
  491.             accessibleContext = new AccessibleJTextField();
  492.         }
  493.         return accessibleContext;
  494.     }
  495.  
  496.     /**
  497.      * The class used to obtain the accessible role for this object.
  498.      * <p>
  499.      * Warning: serialized objects of this class will not be compatible with
  500.      * future swing releases.  The current serialization support is appropriate
  501.      * for short term storage or RMI between Swing1.0 applications.  It will
  502.      * not be possible to load serialized Swing1.0 objects with future releases
  503.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  504.      * baseline for the serialized form of Swing objects.
  505.      */
  506.     protected class AccessibleJTextField extends AccessibleJTextComponent {
  507.  
  508.         /**
  509.          * Gets the state set of this object.
  510.          *
  511.          * @return an instance of AccessibleStateSet describing the states 
  512.          * of the object
  513.          * @see AccessibleState
  514.          */
  515.         public AccessibleStateSet getAccessibleStateSet() {
  516.         AccessibleStateSet states = super.getAccessibleStateSet();
  517.         states.add(AccessibleState.SINGLE_LINE);
  518.             return states;
  519.         }
  520.     }
  521. }
  522.