GNU Classpath (0.19) | ||
Frames | No Frames |
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.AccessibleContext; 50: import javax.accessibility.AccessibleStateSet; 51: import javax.swing.text.Document; 52: import javax.swing.text.JTextComponent; 53: import javax.swing.text.PlainDocument; 54: import javax.swing.text.TextAction; 55: 56: public class JTextField extends JTextComponent 57: implements SwingConstants 58: { 59: /** 60: * AccessibleJTextField 61: */ 62: protected class AccessibleJTextField extends AccessibleJTextComponent 63: { 64: private static final long serialVersionUID = 8255147276740453036L; 65: 66: /** 67: * Constructor AccessibleJTextField 68: */ 69: protected AccessibleJTextField() 70: { 71: super(); 72: } 73: 74: /** 75: * Returns the accessible state of this <code>AccessibleJTextField</code>. 76: * 77: * @return the accessible state of this <code>AccessibleJTextField</code> 78: */ 79: public AccessibleStateSet getAccessibleStateSet() 80: { 81: AccessibleStateSet state = super.getAccessibleStateSet(); 82: // TODO: Figure out what state must be added here to the super's state. 83: return state; 84: } 85: } 86: 87: private static final long serialVersionUID = 353853209832607592L; 88: 89: private static final Action[] actions; 90: 91: /** 92: * Name of the action that gets sent when the content of the text field 93: * gets accepted. 94: */ 95: public static final String notifyAction = "notify-field-accept"; 96: 97: static 98: { 99: actions = new Action[1]; 100: actions[0] = new TextAction(notifyAction) 101: { 102: public void actionPerformed(ActionEvent event) 103: { 104: JTextField textField = (JTextField) event.getSource(); 105: textField.fireActionPerformed(); 106: } 107: }; 108: } 109: 110: private int columns; 111: private int align; 112: private int scrollOffset; 113: 114: /** @since 1.3 */ 115: private Action action; 116: 117: /** @since 1.3 */ 118: private String actionCommand; 119: 120: private PropertyChangeListener actionPropertyChangeListener; 121: 122: /** 123: * The horizontal visibility of the textfield. 124: */ 125: private BoundedRangeModel horizontalVisibility; 126: 127: /** 128: * Creates a new instance of <code>JTextField</code>. 129: */ 130: public JTextField() 131: { 132: this(null, null, 0); 133: } 134: 135: /** 136: * Creates a new instance of <code>JTextField</code>. 137: * 138: * @param text the initial text 139: */ 140: public JTextField(String text) 141: { 142: this(null, text, 0); 143: } 144: 145: /** 146: * Creates a new instance of <code>JTextField</code>. 147: * 148: * @param columns the number of columns 149: * 150: * @exception IllegalArgumentException if columns %lt; 0 151: */ 152: public JTextField(int columns) 153: { 154: this(null, null, columns); 155: } 156: 157: /** 158: * Creates a new instance of <code>JTextField</code>. 159: * 160: * @param text the initial text 161: * @param columns the number of columns 162: * 163: * @exception IllegalArgumentException if columns %lt; 0 164: */ 165: public JTextField(String text, int columns) 166: { 167: this(null, text, columns); 168: } 169: 170: /** 171: * Creates a new instance of <code>JTextField</code>. 172: * 173: * @param doc the document to use 174: * @param text the initial text 175: * @param columns the number of columns 176: * 177: * @exception IllegalArgumentException if columns %lt; 0 178: */ 179: public JTextField(Document doc, String text, int columns) 180: { 181: if (columns < 0) 182: throw new IllegalArgumentException(); 183: 184: this.columns = columns; 185: 186: setDocument(doc == null ? createDefaultModel() : doc); 187: 188: if (text != null) 189: setText(text); 190: 191: // default value for alignment 192: align = LEADING; 193: 194: // Initialize the horizontal visibility model. 195: horizontalVisibility = new DefaultBoundedRangeModel(); 196: } 197: 198: /** 199: * Creates the default model for this text field. 200: * This implementation returns an instance of <code>PlainDocument</code>. 201: * 202: * @return a new instance of the default model 203: */ 204: protected Document createDefaultModel() 205: { 206: return new PlainDocument(); 207: } 208: 209: /** 210: * Returns the class ID for the UI. 211: * 212: * @return "TextFieldUI"; 213: */ 214: public String getUIClassID() 215: { 216: return "TextFieldUI"; 217: } 218: 219: /** 220: * Adds a new listener object to this text field. 221: * 222: * @param listener the listener to add 223: */ 224: public void addActionListener(ActionListener listener) 225: { 226: listenerList.add(ActionListener.class, listener); 227: } 228: 229: /** 230: * Removes a listener object from this text field. 231: * 232: * @param listener the listener to remove 233: */ 234: public void removeActionListener(ActionListener listener) 235: { 236: listenerList.remove(ActionListener.class, listener); 237: } 238: 239: /** 240: * Returns all registered <code>ActionListener</code> objects. 241: * 242: * @return an array of listeners 243: * 244: * @since 1.4 245: */ 246: public ActionListener[] getActionListeners() 247: { 248: return (ActionListener[]) getListeners(ActionListener.class); 249: } 250: 251: /** 252: * Sends an action event to all registered 253: * <code>ActionListener</code> objects. 254: */ 255: protected void fireActionPerformed() 256: { 257: ActionEvent event = new ActionEvent(this, 0, notifyAction); 258: ActionListener[] listeners = getActionListeners(); 259: 260: for (int index = 0; index < listeners.length; ++index) 261: listeners[index].actionPerformed(event); 262: } 263: 264: /** 265: * Returns the number of columns of this text field. 266: * 267: * @return the number of columns 268: */ 269: public int getColumns() 270: { 271: return columns; 272: } 273: 274: /** 275: * Sets the number of columns and then invalidates the layout. 276: * @param columns the number of columns 277: * @throws IllegalArgumentException if columns < 0 278: */ 279: public void setColumns(int columns) 280: { 281: if (columns < 0) 282: throw new IllegalArgumentException(); 283: 284: this.columns = columns; 285: invalidate(); 286: //FIXME: do we need this repaint call? 287: repaint(); 288: } 289: 290: /** 291: * Returns the horizontal alignment, which is one of: JTextField.LEFT, 292: * JTextField.CENTER, JTextField.RIGHT, JTextField.LEADING, 293: * JTextField.TRAILING. 294: * @return the horizontal alignment 295: */ 296: public int getHorizontalAlignment() 297: { 298: return align; 299: } 300: 301: /** 302: * Sets the horizontal alignment of the text. Calls invalidate and repaint 303: * and fires a property change event. 304: * @param newAlign must be one of: JTextField.LEFT, JTextField.CENTER, 305: * JTextField.RIGHT, JTextField.LEADING, JTextField.TRAILING. 306: * @throws IllegalArgumentException if newAlign is not one of the above. 307: */ 308: public void setHorizontalAlignment(int newAlign) 309: { 310: //FIXME: should throw an IllegalArgumentException if newAlign is invalid 311: if (align == newAlign) 312: return; 313: 314: int oldAlign = align; 315: align = newAlign; 316: firePropertyChange("horizontalAlignment", oldAlign, newAlign); 317: invalidate(); 318: repaint(); 319: } 320: 321: /** 322: * Sets the current font and revalidates so the font will take effect. 323: */ 324: public void setFont(Font newFont) 325: { 326: super.setFont(newFont); 327: revalidate(); 328: } 329: 330: /** 331: * Returns the preferred size. If there is a non-zero number of columns, 332: * this is the number of columns multiplied by the column width, otherwise 333: * it returns super.getPreferredSize(). 334: */ 335: public Dimension getPreferredSize() 336: { 337: Dimension size = super.getPreferredSize(); 338: 339: if (columns != 0) 340: size.width = columns * getColumnWidth(); 341: 342: return size; 343: } 344: 345: /** 346: * Returns the scroll offset in pixels. 347: * 348: * @return the scroll offset 349: */ 350: public int getScrollOffset() 351: { 352: //FIXME: this should return horizontalVisibility's value 353: return scrollOffset; 354: } 355: 356: /** 357: * Sets the scroll offset in pixels. 358: * 359: * @param offset the scroll offset 360: */ 361: public void setScrollOffset(int offset) 362: { 363: //FIXME: this should actualy scroll the field if needed 364: scrollOffset = offset; 365: } 366: 367: /** 368: * Returns the set of Actions that are commands for the editor. 369: * This is the actions supported by this editor plus the actions 370: * of the UI (returned by JTextComponent.getActions()). 371: */ 372: public Action[] getActions() 373: { 374: return TextAction.augmentList(super.getActions(), actions); 375: } 376: 377: public void postActionEvent() 378: { 379: String command = actionCommand != null ? actionCommand : getText(); 380: ActionEvent event = new ActionEvent(this, 0, command); 381: ActionListener[] listeners = getActionListeners(); 382: 383: for (int index = 0; index < listeners.length; ++index) 384: listeners[index].actionPerformed(event); 385: } 386: 387: /** 388: * @since 1.3 389: */ 390: public Action getAction() 391: { 392: return action; 393: } 394: 395: /** 396: * @since 1.3 397: */ 398: public void setAction(Action newAction) 399: { 400: if (action == newAction) 401: return; 402: 403: if (action != null) 404: { 405: removeActionListener(action); 406: action.removePropertyChangeListener(actionPropertyChangeListener); 407: actionPropertyChangeListener = null; 408: } 409: 410: Action oldAction = action; 411: action = newAction; 412: 413: if (action != null) 414: { 415: addActionListener(action); 416: actionPropertyChangeListener = createActionPropertyChangeListener(action); 417: action.addPropertyChangeListener(actionPropertyChangeListener); 418: } 419: 420: //FIXME: is this a hack? The horizontal alignment hasn't changed 421: firePropertyChange("horizontalAlignment", oldAction, newAction); 422: } 423: 424: /** 425: * Sets the command string used in action events. 426: * @since 1.3 427: */ 428: public void setActionCommand(String command) 429: { 430: actionCommand = command; 431: } 432: 433: /** 434: * @since 1.3 435: */ 436: protected PropertyChangeListener createActionPropertyChangeListener(Action action) 437: { 438: return new PropertyChangeListener() 439: { 440: public void propertyChange(PropertyChangeEvent event) 441: { 442: // Update properties "action" and "horizontalAlignment". 443: String name = event.getPropertyName(); 444: 445: if (name.equals("enabled")) 446: { 447: boolean enabled = ((Boolean) event.getNewValue()).booleanValue(); 448: JTextField.this.setEnabled(enabled); 449: } 450: else if (name.equals(Action.SHORT_DESCRIPTION)) 451: { 452: JTextField.this.setToolTipText((String) event.getNewValue()); 453: } 454: } 455: }; 456: } 457: 458: /** 459: * 460: * @since 1.3 461: */ 462: protected void configurePropertiesFromAction(Action action) 463: { 464: if (action != null) 465: { 466: setEnabled(action.isEnabled()); 467: setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION)); 468: } 469: else 470: { 471: setEnabled(true); 472: setToolTipText(null); 473: } 474: } 475: 476: /** 477: * Returns the column width, which is the width of the character m 478: * for the font in use. 479: * @return the width of the character m for the font in use. 480: */ 481: protected int getColumnWidth() 482: { 483: FontMetrics metrics = getToolkit().getFontMetrics(getFont()); 484: return metrics.charWidth('m'); 485: } 486: 487: /** 488: * Returns the accessible context associated with the <code>JTextField</code>. 489: * 490: * @return the accessible context associated with the <code>JTextField</code> 491: */ 492: public AccessibleContext getAccessibleContext() 493: { 494: if (accessibleContext == null) 495: accessibleContext = new AccessibleJTextField(); 496: return accessibleContext; 497: } 498: 499: /** 500: * Returns the bounded range model that describes the horizontal visibility 501: * of the text field in the case when the text does not fit into the 502: * available space. The actual values of this model are managed by the look 503: * and feel implementation. 504: * 505: * @return the bounded range model that describes the horizontal visibility 506: */ 507: public BoundedRangeModel getHorizontalVisibility() 508: { 509: // TODO: The real implementation of this property is still missing. 510: // However, this is not done in JTextField but must instead be handled in 511: // javax.swing.text.FieldView. 512: return horizontalVisibility; 513: } 514: }
GNU Classpath (0.19) |