GNU Classpath (0.20) | |
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: * Sets the document to be used for this JTextField. 211: * 212: * This sets the document property <code>filterNewlines</code> to 213: * <code>true</code> and then calls the super behaviour to setup a view and 214: * revalidate the text field. 215: * 216: * @param doc the document to set 217: */ 218: public void setDocument(Document doc) 219: { 220: doc.putProperty("filterNewlines", Boolean.TRUE); 221: super.setDocument(doc); 222: } 223: 224: /** 225: * Returns the class ID for the UI. 226: * 227: * @return "TextFieldUI"; 228: */ 229: public String getUIClassID() 230: { 231: return "TextFieldUI"; 232: } 233: 234: /** 235: * Adds a new listener object to this text field. 236: * 237: * @param listener the listener to add 238: */ 239: public void addActionListener(ActionListener listener) 240: { 241: listenerList.add(ActionListener.class, listener); 242: } 243: 244: /** 245: * Removes a listener object from this text field. 246: * 247: * @param listener the listener to remove 248: */ 249: public void removeActionListener(ActionListener listener) 250: { 251: listenerList.remove(ActionListener.class, listener); 252: } 253: 254: /** 255: * Returns all registered <code>ActionListener</code> objects. 256: * 257: * @return an array of listeners 258: * 259: * @since 1.4 260: */ 261: public ActionListener[] getActionListeners() 262: { 263: return (ActionListener[]) getListeners(ActionListener.class); 264: } 265: 266: /** 267: * Sends an action event to all registered 268: * <code>ActionListener</code> objects. 269: */ 270: protected void fireActionPerformed() 271: { 272: ActionEvent event = new ActionEvent(this, 0, notifyAction); 273: ActionListener[] listeners = getActionListeners(); 274: 275: for (int index = 0; index < listeners.length; ++index) 276: listeners[index].actionPerformed(event); 277: } 278: 279: /** 280: * Returns the number of columns of this text field. 281: * 282: * @return the number of columns 283: */ 284: public int getColumns() 285: { 286: return columns; 287: } 288: 289: /** 290: * Sets the number of columns and then invalidates the layout. 291: * @param columns the number of columns 292: * @throws IllegalArgumentException if columns < 0 293: */ 294: public void setColumns(int columns) 295: { 296: if (columns < 0) 297: throw new IllegalArgumentException(); 298: 299: this.columns = columns; 300: invalidate(); 301: //FIXME: do we need this repaint call? 302: repaint(); 303: } 304: 305: /** 306: * Returns the horizontal alignment, which is one of: JTextField.LEFT, 307: * JTextField.CENTER, JTextField.RIGHT, JTextField.LEADING, 308: * JTextField.TRAILING. 309: * @return the horizontal alignment 310: */ 311: public int getHorizontalAlignment() 312: { 313: return align; 314: } 315: 316: /** 317: * Sets the horizontal alignment of the text. Calls invalidate and repaint 318: * and fires a property change event. 319: * @param newAlign must be one of: JTextField.LEFT, JTextField.CENTER, 320: * JTextField.RIGHT, JTextField.LEADING, JTextField.TRAILING. 321: * @throws IllegalArgumentException if newAlign is not one of the above. 322: */ 323: public void setHorizontalAlignment(int newAlign) 324: { 325: //FIXME: should throw an IllegalArgumentException if newAlign is invalid 326: if (align == newAlign) 327: return; 328: 329: int oldAlign = align; 330: align = newAlign; 331: firePropertyChange("horizontalAlignment", oldAlign, newAlign); 332: invalidate(); 333: repaint(); 334: } 335: 336: /** 337: * Sets the current font and revalidates so the font will take effect. 338: */ 339: public void setFont(Font newFont) 340: { 341: super.setFont(newFont); 342: revalidate(); 343: } 344: 345: /** 346: * Returns the preferred size. If there is a non-zero number of columns, 347: * this is the number of columns multiplied by the column width, otherwise 348: * it returns super.getPreferredSize(). 349: */ 350: public Dimension getPreferredSize() 351: { 352: Dimension size = super.getPreferredSize(); 353: 354: if (columns != 0) 355: size.width = columns * getColumnWidth(); 356: 357: return size; 358: } 359: 360: /** 361: * Returns the scroll offset in pixels. 362: * 363: * @return the scroll offset 364: */ 365: public int getScrollOffset() 366: { 367: //FIXME: this should return horizontalVisibility's value 368: return scrollOffset; 369: } 370: 371: /** 372: * Sets the scroll offset in pixels. 373: * 374: * @param offset the scroll offset 375: */ 376: public void setScrollOffset(int offset) 377: { 378: //FIXME: this should actualy scroll the field if needed 379: scrollOffset = offset; 380: } 381: 382: /** 383: * Returns the set of Actions that are commands for the editor. 384: * This is the actions supported by this editor plus the actions 385: * of the UI (returned by JTextComponent.getActions()). 386: */ 387: public Action[] getActions() 388: { 389: return TextAction.augmentList(super.getActions(), actions); 390: } 391: 392: public void postActionEvent() 393: { 394: String command = actionCommand != null ? actionCommand : getText(); 395: ActionEvent event = new ActionEvent(this, 0, command); 396: ActionListener[] listeners = getActionListeners(); 397: 398: for (int index = 0; index < listeners.length; ++index) 399: listeners[index].actionPerformed(event); 400: } 401: 402: /** 403: * @since 1.3 404: */ 405: public Action getAction() 406: { 407: return action; 408: } 409: 410: /** 411: * @since 1.3 412: */ 413: public void setAction(Action newAction) 414: { 415: if (action == newAction) 416: return; 417: 418: if (action != null) 419: { 420: removeActionListener(action); 421: action.removePropertyChangeListener(actionPropertyChangeListener); 422: actionPropertyChangeListener = null; 423: } 424: 425: Action oldAction = action; 426: action = newAction; 427: 428: if (action != null) 429: { 430: addActionListener(action); 431: actionPropertyChangeListener = createActionPropertyChangeListener(action); 432: action.addPropertyChangeListener(actionPropertyChangeListener); 433: } 434: 435: //FIXME: is this a hack? The horizontal alignment hasn't changed 436: firePropertyChange("horizontalAlignment", oldAction, newAction); 437: } 438: 439: /** 440: * Sets the command string used in action events. 441: * @since 1.3 442: */ 443: public void setActionCommand(String command) 444: { 445: actionCommand = command; 446: } 447: 448: /** 449: * @since 1.3 450: */ 451: protected PropertyChangeListener createActionPropertyChangeListener(Action action) 452: { 453: return new PropertyChangeListener() 454: { 455: public void propertyChange(PropertyChangeEvent event) 456: { 457: // Update properties "action" and "horizontalAlignment". 458: String name = event.getPropertyName(); 459: 460: if (name.equals("enabled")) 461: { 462: boolean enabled = ((Boolean) event.getNewValue()).booleanValue(); 463: JTextField.this.setEnabled(enabled); 464: } 465: else if (name.equals(Action.SHORT_DESCRIPTION)) 466: { 467: JTextField.this.setToolTipText((String) event.getNewValue()); 468: } 469: } 470: }; 471: } 472: 473: /** 474: * 475: * @since 1.3 476: */ 477: protected void configurePropertiesFromAction(Action action) 478: { 479: if (action != null) 480: { 481: setEnabled(action.isEnabled()); 482: setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION)); 483: } 484: else 485: { 486: setEnabled(true); 487: setToolTipText(null); 488: } 489: } 490: 491: /** 492: * Returns the column width, which is the width of the character m 493: * for the font in use. 494: * @return the width of the character m for the font in use. 495: */ 496: protected int getColumnWidth() 497: { 498: FontMetrics metrics = getToolkit().getFontMetrics(getFont()); 499: return metrics.charWidth('m'); 500: } 501: 502: /** 503: * Returns the accessible context associated with the <code>JTextField</code>. 504: * 505: * @return the accessible context associated with the <code>JTextField</code> 506: */ 507: public AccessibleContext getAccessibleContext() 508: { 509: if (accessibleContext == null) 510: accessibleContext = new AccessibleJTextField(); 511: return accessibleContext; 512: } 513: 514: /** 515: * Returns the bounded range model that describes the horizontal visibility 516: * of the text field in the case when the text does not fit into the 517: * available space. The actual values of this model are managed by the look 518: * and feel implementation. 519: * 520: * @return the bounded range model that describes the horizontal visibility 521: */ 522: public BoundedRangeModel getHorizontalVisibility() 523: { 524: // TODO: The real implementation of this property is still missing. 525: // However, this is not done in JTextField but must instead be handled in 526: // javax.swing.text.FieldView. 527: return horizontalVisibility; 528: } 529: }
GNU Classpath (0.20) |