Source for javax.swing.JTextField

   1: /* JTextField.java --
   2:    Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import java.awt.Dimension;
  42: import java.awt.Font;
  43: import java.awt.FontMetrics;
  44: import java.awt.event.ActionEvent;
  45: import java.awt.event.ActionListener;
  46: import java.beans.PropertyChangeEvent;
  47: import java.beans.PropertyChangeListener;
  48: 
  49: import javax.accessibility.AccessibleStateSet;
  50: import javax.swing.text.AttributeSet;
  51: import javax.swing.text.BadLocationException;
  52: import javax.swing.text.Document;
  53: import javax.swing.text.JTextComponent;
  54: import javax.swing.text.PlainDocument;
  55: import javax.swing.text.TextAction;
  56: 
  57: public class JTextField extends JTextComponent
  58:   implements SwingConstants
  59: {
  60:   /**
  61:    * AccessibleJTextField
  62:    */
  63:   protected class AccessibleJTextField extends AccessibleJTextComponent
  64:   {
  65:     private static final long serialVersionUID = 8255147276740453036L;
  66: 
  67:     /**
  68:      * Constructor AccessibleJTextField
  69:      */
  70:     protected AccessibleJTextField()
  71:     {
  72:     }
  73: 
  74:     /**
  75:      * getAccessibleStateSet
  76:      * @return AccessibleStateSet
  77:      */
  78:     public AccessibleStateSet getAccessibleStateSet()
  79:     {
  80:       return null;
  81:     }
  82:   }
  83: 
  84:   private static final long serialVersionUID = 353853209832607592L;
  85: 
  86:   private static final Action[] actions;
  87: 
  88:   /**
  89:    * Name of the action that gets sent when the content of the text field
  90:    * gets accepted.
  91:    */
  92:   public static final String notifyAction = "notify-field-accept";
  93:   
  94:   static
  95:   {
  96:     actions = new Action[1];
  97:     actions[0] = new TextAction(notifyAction)
  98:       {
  99:     public void actionPerformed(ActionEvent event)
 100:     {
 101:       JTextField textField = (JTextField) event.getSource();
 102:       textField.fireActionPerformed();
 103:     }
 104:       };
 105:   }
 106:   
 107:   private int columns;
 108:   private int align;
 109:   private int scrollOffset;
 110: 
 111:   /** @since 1.3 */
 112:   private Action action;
 113: 
 114:   /** @since 1.3 */
 115:   private String actionCommand;
 116:   
 117:   private PropertyChangeListener actionPropertyChangeListener;
 118: 
 119:   /**
 120:    * Creates a new instance of <code>JTextField</code>.
 121:    */
 122:   public JTextField()
 123:   {
 124:     this(null, null, 0);
 125:   }
 126: 
 127:   /**
 128:    * Creates a new instance of <code>JTextField</code>.
 129:    *
 130:    * @param text the initial text
 131:    */
 132:   public JTextField(String text)
 133:   {
 134:     this(null, text, 0);
 135:   }
 136:   
 137:   /**
 138:    * Creates a new instance of <code>JTextField</code>.
 139:    *
 140:    * @param columns the number of columns
 141:    *
 142:    * @exception IllegalArgumentException if columns %lt; 0
 143:    */
 144:   public JTextField(int columns)
 145:   {
 146:     this(null, null, columns);
 147:   }
 148: 
 149:   /**
 150:    * Creates a new instance of <code>JTextField</code>.
 151:    *
 152:    * @param text the initial text
 153:    * @param columns the number of columns
 154:    *
 155:    * @exception IllegalArgumentException if columns %lt; 0
 156:    */
 157:   public JTextField(String text, int columns)
 158:   {
 159:     this(null, text, columns);
 160:   }
 161: 
 162:   /**
 163:    * Creates a new instance of <code>JTextField</code>.
 164:    *
 165:    * @param doc the document to use
 166:    * @param text the initial text
 167:    * @param columns the number of columns
 168:    *
 169:    * @exception IllegalArgumentException if columns %lt; 0
 170:    */
 171:   public JTextField(Document doc, String text, int columns)
 172:   {
 173:     if (columns < 0)
 174:       throw new IllegalArgumentException();
 175:     
 176:     this.columns = columns;
 177:     
 178:     setDocument(doc == null ? createDefaultModel() : doc);
 179: 
 180:     if (text != null)
 181:       setText(text);
 182: 
 183:     // default value for alignment
 184:     align = LEADING;
 185:   }
 186: 
 187:   /**
 188:    * Creates the default model for this text field.
 189:    * This implementation returns an instance of <code>PlainDocument</code>.
 190:    *
 191:    * @return a new instance of the default model
 192:    */
 193:   protected Document createDefaultModel()
 194:   {
 195:     // subclassed to swallow newlines
 196:     return new PlainDocument() {
 197:         public void insertString(int offset, String str, AttributeSet a)
 198:           throws BadLocationException
 199:         {
 200:           if (str.indexOf('\n') == -1)
 201:             super.insertString(offset, str, a);
 202:         }
 203:       };
 204:   }
 205: 
 206:   /**
 207:    * Returns the class ID for the UI.
 208:    *
 209:    * @return "TextFieldUI";
 210:    */
 211:   public String getUIClassID()
 212:   {
 213:     return "TextFieldUI";
 214:   }
 215: 
 216:   /**
 217:    * Adds a new listener object to this text field.
 218:    *
 219:    * @param listener the listener to add
 220:    */
 221:   public void addActionListener(ActionListener listener)
 222:   {
 223:     listenerList.add(ActionListener.class, listener);
 224:   }
 225: 
 226:   /**
 227:    * Removes a listener object from this text field.
 228:    *
 229:    * @param listener the listener to remove
 230:    */
 231:   public void removeActionListener(ActionListener listener)
 232:   {
 233:     listenerList.remove(ActionListener.class, listener);
 234:   }
 235: 
 236:   /**
 237:    * Returns all registered <code>ActionListener</code> objects.
 238:    *
 239:    * @return an array of listeners
 240:    *
 241:    * @since 1.4
 242:    */
 243:   public ActionListener[] getActionListeners()
 244:   {
 245:     return (ActionListener[]) getListeners(ActionListener.class);
 246:   }
 247: 
 248:   /**
 249:    * Sends an action event to all registered
 250:    * <code>ActionListener</code> objects.
 251:    */
 252:   protected void fireActionPerformed()
 253:   {
 254:     ActionEvent event = new ActionEvent(this, 0, notifyAction);
 255:     ActionListener[] listeners = getActionListeners();
 256: 
 257:     for (int index = 0; index < listeners.length; ++index)
 258:       listeners[index].actionPerformed(event);
 259:   }
 260: 
 261:   /**
 262:    * Returns the number of columns of this text field.
 263:    *
 264:    * @return the number of columns
 265:    */
 266:   public int getColumns()
 267:   {
 268:     return columns;
 269:   }
 270: 
 271:   public void setColumns(int columns)
 272:   {
 273:     if (columns < 0)
 274:       throw new IllegalArgumentException();
 275: 
 276:     this.columns = columns;
 277:     invalidate();
 278:     repaint();
 279:   }
 280: 
 281:   public int getHorizontalAlignment()
 282:   {
 283:     return align;
 284:   }
 285: 
 286:   public void setHorizontalAlignment(int newAlign)
 287:   {
 288:     if (align == newAlign)
 289:       return;
 290: 
 291:     int oldAlign = align;
 292:     align = newAlign;
 293:     firePropertyChange("horizontalAlignment", oldAlign, newAlign);
 294:     invalidate();
 295:     repaint();
 296:   }
 297: 
 298:   public void setFont(Font newFont)
 299:   {
 300:     super.setFont(newFont);
 301:     revalidate();
 302:   }
 303: 
 304:   public Dimension getPreferredSize()
 305:   {
 306:     Dimension size = super.getPreferredSize();
 307: 
 308:     if (columns != 0)
 309:       size.width = columns * getColumnWidth();
 310: 
 311:     return size;
 312:   }
 313: 
 314:   /**
 315:    * Returns the scroll offset in pixels.
 316:    *
 317:    * @return the scroll offset
 318:    */
 319:   public int getScrollOffset()
 320:   {
 321:     return scrollOffset;
 322:   }
 323: 
 324:   /**
 325:    * Sets the scroll offset in pixels.
 326:    * 
 327:    * @param offset the scroll offset
 328:    */
 329:   public void setScrollOffset(int offset)
 330:   {
 331:     scrollOffset = offset;
 332:   }
 333: 
 334:   public Action[] getActions()
 335:   {
 336:     return TextAction.augmentList(super.getActions(), actions);
 337:   }
 338: 
 339:   public void postActionEvent()
 340:   {
 341:     String command = actionCommand != null ? actionCommand : getText();
 342:     ActionEvent event = new ActionEvent(this, 0, command);
 343:     ActionListener[] listeners = getActionListeners();
 344: 
 345:     for (int index = 0; index < listeners.length; ++index)
 346:       listeners[index].actionPerformed(event);
 347:   }
 348:   
 349:   /**
 350:    * @since 1.3
 351:    */
 352:   public Action getAction()
 353:   {
 354:     return action;
 355:   }
 356: 
 357:   /**
 358:    * @since 1.3
 359:    */
 360:   public void setAction(Action newAction)
 361:   {
 362:     if (action == newAction)
 363:       return;
 364: 
 365:     if (action != null)
 366:       {
 367:     removeActionListener(action);
 368:     action.removePropertyChangeListener(actionPropertyChangeListener);
 369:     actionPropertyChangeListener = null;
 370:       }
 371:     
 372:     Action oldAction = action;
 373:     action = newAction;
 374: 
 375:     if (action != null)
 376:       {
 377:     addActionListener(action);
 378:     actionPropertyChangeListener =
 379:       createActionPropertyChangeListener(action);
 380:     action.addPropertyChangeListener(actionPropertyChangeListener);
 381:       }
 382:     
 383:     firePropertyChange("horizontalAlignment", oldAction, newAction);
 384:   }
 385: 
 386:   /**
 387:    * @since 1.3
 388:    */
 389:   public void setActionCommand(String command)
 390:   {
 391:     actionCommand = command;
 392:   }
 393: 
 394:   /**
 395:    * @since 1.3
 396:    */
 397:   protected PropertyChangeListener createActionPropertyChangeListener(Action action)
 398:   {
 399:     return new PropertyChangeListener()
 400:       {
 401:     public void propertyChange(PropertyChangeEvent event)
 402:     {
 403:       // Update properties "action" and "horizontalAlignment".
 404:       String name = event.getPropertyName();
 405: 
 406:       if (name.equals("enabled"))
 407:         {
 408:           boolean enabled = ((Boolean) event.getNewValue()).booleanValue();
 409:           JTextField.this.setEnabled(enabled);
 410:         }
 411:       else if (name.equals(Action.SHORT_DESCRIPTION))
 412:         {
 413:           JTextField.this.setToolTipText((String) event.getNewValue());
 414:         }
 415:     }
 416:       };
 417:   }
 418: 
 419:   /**
 420:    * @since 1.3
 421:    */
 422:   protected void configurePropertiesFromAction(Action action)
 423:   {
 424:     if (action != null)
 425:       {
 426:     setEnabled(action.isEnabled());
 427:     setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
 428:       }
 429:     else
 430:       {
 431:     setEnabled(true);      
 432:     setToolTipText(null);
 433:       }
 434:   }
 435: 
 436:   protected int getColumnWidth()
 437:   {
 438:     FontMetrics metrics = getToolkit().getFontMetrics(getFont());
 439:     return metrics.charWidth('m');
 440:   }
 441: }