2 Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
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
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. */
41 import java
.awt
.Dimension
;
43 import java
.awt
.FontMetrics
;
44 import java
.awt
.Insets
;
45 import java
.awt
.Rectangle
;
46 import java
.awt
.event
.ActionEvent
;
47 import java
.awt
.event
.ActionListener
;
48 import java
.beans
.PropertyChangeEvent
;
49 import java
.beans
.PropertyChangeListener
;
51 import javax
.accessibility
.AccessibleContext
;
52 import javax
.accessibility
.AccessibleStateSet
;
53 import javax
.swing
.text
.Document
;
54 import javax
.swing
.text
.JTextComponent
;
55 import javax
.swing
.text
.PlainDocument
;
56 import javax
.swing
.text
.TextAction
;
58 public class JTextField
extends JTextComponent
59 implements SwingConstants
62 * AccessibleJTextField
64 protected class AccessibleJTextField
extends AccessibleJTextComponent
66 private static final long serialVersionUID
= 8255147276740453036L;
69 * Constructor AccessibleJTextField
71 protected AccessibleJTextField()
77 * Returns the accessible state of this <code>AccessibleJTextField</code>.
79 * @return the accessible state of this <code>AccessibleJTextField</code>
81 public AccessibleStateSet
getAccessibleStateSet()
83 AccessibleStateSet state
= super.getAccessibleStateSet();
84 // TODO: Figure out what state must be added here to the super's state.
89 private static final long serialVersionUID
= 353853209832607592L;
91 private static final Action
[] actions
;
94 * Name of the action that gets sent when the content of the text field
97 public static final String notifyAction
= "notify-field-accept";
101 actions
= new Action
[1];
102 actions
[0] = new TextAction(notifyAction
)
104 public void actionPerformed(ActionEvent event
)
106 JTextField textField
= (JTextField
) event
.getSource();
107 textField
.fireActionPerformed();
116 private Action action
;
119 private String actionCommand
;
121 private PropertyChangeListener actionPropertyChangeListener
;
124 * The horizontal visibility of the textfield.
126 private BoundedRangeModel horizontalVisibility
;
129 * Creates a new instance of <code>JTextField</code>.
137 * Creates a new instance of <code>JTextField</code>.
139 * @param text the initial text
141 public JTextField(String text
)
147 * Creates a new instance of <code>JTextField</code>.
149 * @param columns the number of columns
151 * @exception IllegalArgumentException if columns %lt; 0
153 public JTextField(int columns
)
155 this(null, null, columns
);
159 * Creates a new instance of <code>JTextField</code>.
161 * @param text the initial text
162 * @param columns the number of columns
164 * @exception IllegalArgumentException if columns %lt; 0
166 public JTextField(String text
, int columns
)
168 this(null, text
, columns
);
172 * Creates a new instance of <code>JTextField</code>.
174 * @param doc the document to use
175 * @param text the initial text
176 * @param columns the number of columns
178 * @exception IllegalArgumentException if columns %lt; 0
180 public JTextField(Document doc
, String text
, int columns
)
183 throw new IllegalArgumentException();
185 this.columns
= columns
;
187 // Initialize the horizontal visibility model.
188 horizontalVisibility
= new DefaultBoundedRangeModel();
190 setDocument(doc
== null ?
createDefaultModel() : doc
);
195 // default value for alignment
200 * Creates the default model for this text field.
201 * This implementation returns an instance of <code>PlainDocument</code>.
203 * @return a new instance of the default model
205 protected Document
createDefaultModel()
207 return new PlainDocument();
211 * Sets the document to be used for this JTextField.
213 * This sets the document property <code>filterNewlines</code> to
214 * <code>true</code> and then calls the super behaviour to setup a view and
215 * revalidate the text field.
217 * @param doc the document to set
219 public void setDocument(Document doc
)
221 doc
.putProperty("filterNewlines", Boolean
.TRUE
);
222 super.setDocument(doc
);
226 * Returns the class ID for the UI.
228 * @return "TextFieldUI";
230 public String
getUIClassID()
232 return "TextFieldUI";
236 * Adds a new listener object to this text field.
238 * @param listener the listener to add
240 public void addActionListener(ActionListener listener
)
242 listenerList
.add(ActionListener
.class, listener
);
246 * Removes a listener object from this text field.
248 * @param listener the listener to remove
250 public void removeActionListener(ActionListener listener
)
252 listenerList
.remove(ActionListener
.class, listener
);
256 * Returns all registered <code>ActionListener</code> objects.
258 * @return an array of listeners
262 public ActionListener
[] getActionListeners()
264 return (ActionListener
[]) getListeners(ActionListener
.class);
268 * Sends an action event to all registered
269 * <code>ActionListener</code> objects.
271 protected void fireActionPerformed()
273 ActionEvent event
= new ActionEvent(this, 0,
274 actionCommand
== null ?
getText() : actionCommand
);
275 ActionListener
[] listeners
= getActionListeners();
277 for (int index
= 0; index
< listeners
.length
; ++index
)
278 listeners
[index
].actionPerformed(event
);
282 * Returns the number of columns of this text field.
284 * @return the number of columns
286 public int getColumns()
292 * Sets the number of columns and then invalidates the layout.
293 * @param columns the number of columns
294 * @throws IllegalArgumentException if columns < 0
296 public void setColumns(int columns
)
299 throw new IllegalArgumentException();
301 this.columns
= columns
;
303 //FIXME: do we need this repaint call?
308 * Returns the horizontal alignment, which is one of: JTextField.LEFT,
309 * JTextField.CENTER, JTextField.RIGHT, JTextField.LEADING,
310 * JTextField.TRAILING.
311 * @return the horizontal alignment
313 public int getHorizontalAlignment()
319 * Sets the horizontal alignment of the text. Calls invalidate and repaint
320 * and fires a property change event.
321 * @param newAlign must be one of: JTextField.LEFT, JTextField.CENTER,
322 * JTextField.RIGHT, JTextField.LEADING, JTextField.TRAILING.
323 * @throws IllegalArgumentException if newAlign is not one of the above.
325 public void setHorizontalAlignment(int newAlign
)
327 //FIXME: should throw an IllegalArgumentException if newAlign is invalid
328 if (align
== newAlign
)
331 int oldAlign
= align
;
333 firePropertyChange("horizontalAlignment", oldAlign
, newAlign
);
339 * Sets the current font and revalidates so the font will take effect.
341 public void setFont(Font newFont
)
343 super.setFont(newFont
);
348 * Returns the preferred size. If there is a non-zero number of columns,
349 * this is the number of columns multiplied by the column width, otherwise
350 * it returns super.getPreferredSize().
352 public Dimension
getPreferredSize()
354 Dimension size
= super.getPreferredSize();
358 Insets i
= getInsets();
359 size
.width
= columns
* getColumnWidth() + i
.left
+ i
.right
;
366 * Returns the scroll offset in pixels.
368 * @return the scroll offset
370 public int getScrollOffset()
372 return horizontalVisibility
.getValue();
376 * Sets the scroll offset in pixels.
378 * @param offset the scroll offset
380 public void setScrollOffset(int offset
)
382 // Automatically sets to the highest possible value if
383 // offset is bigger than that.
384 horizontalVisibility
.setValue(
385 Math
.min(horizontalVisibility
.getMaximum()
386 - horizontalVisibility
.getExtent(),
392 * Returns the set of Actions that are commands for the editor.
393 * This is the actions supported by this editor plus the actions
394 * of the UI (returned by JTextComponent.getActions()).
396 public Action
[] getActions()
398 return TextAction
.augmentList(super.getActions(), actions
);
401 public void postActionEvent()
403 String command
= actionCommand
!= null ? actionCommand
: getText();
404 ActionEvent event
= new ActionEvent(this, 0, command
);
405 ActionListener
[] listeners
= getActionListeners();
407 for (int index
= 0; index
< listeners
.length
; ++index
)
408 listeners
[index
].actionPerformed(event
);
414 public Action
getAction()
422 public void setAction(Action newAction
)
424 if (action
== newAction
)
429 removeActionListener(action
);
430 action
.removePropertyChangeListener(actionPropertyChangeListener
);
431 actionPropertyChangeListener
= null;
434 Action oldAction
= action
;
439 addActionListener(action
);
440 actionPropertyChangeListener
= createActionPropertyChangeListener(action
);
441 action
.addPropertyChangeListener(actionPropertyChangeListener
);
444 //FIXME: is this a hack? The horizontal alignment hasn't changed
445 firePropertyChange("horizontalAlignment", oldAction
, newAction
);
449 * Sets the command string used in action events.
452 public void setActionCommand(String command
)
454 actionCommand
= command
;
460 protected PropertyChangeListener
createActionPropertyChangeListener(Action action
)
462 return new PropertyChangeListener()
464 public void propertyChange(PropertyChangeEvent event
)
466 // Update properties "action" and "horizontalAlignment".
467 String name
= event
.getPropertyName();
469 if (name
.equals("enabled"))
471 boolean enabled
= ((Boolean
) event
.getNewValue()).booleanValue();
472 JTextField
.this.setEnabled(enabled
);
474 else if (name
.equals(Action
.SHORT_DESCRIPTION
))
476 JTextField
.this.setToolTipText((String
) event
.getNewValue());
486 protected void configurePropertiesFromAction(Action action
)
490 setEnabled(action
.isEnabled());
491 setToolTipText((String
) action
.getValue(Action
.SHORT_DESCRIPTION
));
496 setToolTipText(null);
501 * Returns the column width, which is the width of the character m
502 * for the font in use.
503 * @return the width of the character m for the font in use.
505 protected int getColumnWidth()
507 FontMetrics metrics
= getToolkit().getFontMetrics(getFont());
508 return metrics
.charWidth('m');
512 * Returns the accessible context associated with the <code>JTextField</code>.
514 * @return the accessible context associated with the <code>JTextField</code>
516 public AccessibleContext
getAccessibleContext()
518 if (accessibleContext
== null)
519 accessibleContext
= new AccessibleJTextField();
520 return accessibleContext
;
524 * Returns the bounded range model that describes the horizontal visibility
525 * of the text field in the case when the text does not fit into the
526 * available space. The actual values of this model are managed by the look
527 * and feel implementation.
529 * @return the bounded range model that describes the horizontal visibility
531 public BoundedRangeModel
getHorizontalVisibility()
533 return horizontalVisibility
;
537 * Returns <code>true</code>, unless this is embedded in a
538 * <code>JViewport</code> in which case the viewport takes responsibility of
541 * @return <code>true</code>, unless this is embedded in a
542 * <code>JViewport</code> in which case the viewport takes
543 * responsibility of validating
545 public boolean isValidateRoot()
547 return ! (getParent() instanceof JViewport
);
550 public void scrollRectToVisible(Rectangle r
)
552 int v
= horizontalVisibility
.getValue();
554 // The extent value is the inner width of the text field.
555 int e
= horizontalVisibility
.getExtent();
556 Insets i
= getInsets();
558 // The x value in the rectangle (usually) denotes the new location
559 // of the caret. We check whether the location lies inside the left or
560 // right border and scroll into the appropriate direction.
561 // The calculation has to be shifted by the BoundedRangeModel's value
562 // because that value was already used to calculate r.x (this happens
563 // as part of a modelToView() call in FieldView).
565 setScrollOffset(v
+ r
.x
- i
.left
);
566 else if (r
.x
> e
+ i
.left
)
567 setScrollOffset(r
.x
+ v
- e
- i
.left
);