KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > swing > plaf > basic > BasicTextFieldUI


1 /*
2  * @(#)BasicTextFieldUI.java 1.95 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package javax.swing.plaf.basic;
8
9 import java.awt.*;
10 import java.awt.event.KeyEvent JavaDoc;
11 import java.awt.event.FocusEvent JavaDoc;
12 import java.awt.event.InputEvent JavaDoc;
13 import java.beans.PropertyChangeEvent JavaDoc;
14 import java.io.Reader JavaDoc;
15 import javax.swing.*;
16 import javax.swing.border.*;
17 import javax.swing.event.*;
18 import javax.swing.text.*;
19 import javax.swing.plaf.*;
20 import sun.swing.DefaultLookup;
21
22 /**
23  * Basis of a look and feel for a JTextField.
24  * <p>
25  * <strong>Warning:</strong>
26  * Serialized objects of this class will not be compatible with
27  * future Swing releases. The current serialization support is
28  * appropriate for short term storage or RMI between applications running
29  * the same version of Swing. As of 1.4, support for long term storage
30  * of all JavaBeans<sup><font size="-2">TM</font></sup>
31  * has been added to the <code>java.beans</code> package.
32  * Please see {@link java.beans.XMLEncoder}.
33  *
34  * @author Timothy Prinzing
35  * @version 1.95 12/19/03
36  */

37 public class BasicTextFieldUI extends BasicTextUI JavaDoc {
38
39     /**
40      * Creates a UI for a JTextField.
41      *
42      * @param c the text field
43      * @return the UI
44      */

45     public static ComponentUI createUI(JComponent c) {
46         return new BasicTextFieldUI JavaDoc();
47     }
48
49     /**
50      * Creates a new BasicTextFieldUI.
51      */

52     public BasicTextFieldUI() {
53     super();
54     }
55
56     public void installUI(JComponent c) {
57         super.installUI(c);
58     updateBackground((JTextComponent)c);
59     }
60
61     /**
62      * This method gets called when a bound property is changed
63      * on the associated JTextComponent. This is a hook
64      * which UI implementations may change to reflect how the
65      * UI displays bound properties of JTextComponent subclasses.
66      *
67      * @param evt the property change event
68      */

69     protected void propertyChange(PropertyChangeEvent JavaDoc evt) {
70     if (evt.getPropertyName().equals("editable") ||
71         evt.getPropertyName().equals("enabled")) {
72
73         updateBackground((JTextComponent)evt.getSource());
74     }
75     }
76
77     private void updateBackground(JTextComponent c) {
78     Color background = c.getBackground();
79     if (background instanceof UIResource) {
80         Color newColor = null;
81         String JavaDoc prefix = getPropertyPrefix();
82         if (!c.isEnabled()) {
83         newColor = DefaultLookup.getColor(c, this,
84                           prefix + ".disabledBackground",
85                           null);
86         }
87         if (newColor == null && !c.isEditable()) {
88         newColor = DefaultLookup.getColor(c, this,
89                           prefix + ".inactiveBackground",
90                           null);
91         }
92         if (newColor == null) {
93         newColor = DefaultLookup.getColor(c, this,
94                           prefix + ".background",
95                           null);
96         }
97         if (newColor != null && newColor != background) {
98         c.setBackground(newColor);
99         }
100     }
101     }
102
103     /**
104      * Fetches the name used as a key to lookup properties through the
105      * UIManager. This is used as a prefix to all the standard
106      * text properties.
107      *
108      * @return the name ("TextField")
109      */

110     protected String JavaDoc getPropertyPrefix() {
111     return "TextField";
112     }
113
114     /**
115      * Creates a view (FieldView) based on an element.
116      *
117      * @param elem the element
118      * @return the view
119      */

120     public View create(Element elem) {
121     Document doc = elem.getDocument();
122     Object JavaDoc i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);
123     if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
124         // To support bidirectional text, we build a more heavyweight
125
// representation of the field.
126
String JavaDoc kind = elem.getName();
127         if (kind != null) {
128         if (kind.equals(AbstractDocument.ContentElementName)) {
129             return new GlyphView(elem);
130         } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
131             return new I18nFieldView(elem);
132         }
133         }
134         // this shouldn't happen, should probably throw in this case.
135
}
136     return new FieldView(elem);
137     }
138
139     /**
140      * A field view that support bidirectional text via the
141      * support provided by ParagraphView.
142      */

143     static class I18nFieldView extends ParagraphView {
144
145     I18nFieldView(Element elem) {
146         super(elem);
147     }
148
149     /**
150      * Fetch the constraining span to flow against for
151      * the given child index. There is no limit for
152      * a field since it scrolls, so this is implemented to
153      * return <code>Integer.MAX_VALUE</code>.
154      */

155         public int getFlowSpan(int index) {
156         return Integer.MAX_VALUE;
157     }
158
159     protected void setJustification(int j) {
160         // Justification is done in adjustAllocation(), so disable
161
// ParagraphView's justification handling by doing nothing here.
162
}
163
164     static boolean isLeftToRight( java.awt.Component JavaDoc c ) {
165         return c.getComponentOrientation().isLeftToRight();
166     }
167
168     /**
169      * Adjusts the allocation given to the view
170      * to be a suitable allocation for a text field.
171      * If the view has been allocated more than the
172      * preferred span vertically, the allocation is
173      * changed to be centered vertically. Horizontally
174      * the view is adjusted according to the horizontal
175      * alignment property set on the associated JTextField
176      * (if that is the type of the hosting component).
177      *
178      * @param a the allocation given to the view, which may need
179      * to be adjusted.
180      * @return the allocation that the superclass should use.
181      */

182         Shape adjustAllocation(Shape a) {
183         if (a != null) {
184         Rectangle bounds = a.getBounds();
185         int vspan = (int) getPreferredSpan(Y_AXIS);
186         int hspan = (int) getPreferredSpan(X_AXIS);
187         if (bounds.height != vspan) {
188             int slop = bounds.height - vspan;
189             bounds.y += slop / 2;
190             bounds.height -= slop;
191         }
192         
193         // horizontal adjustments
194
Component c = getContainer();
195         if (c instanceof JTextField) {
196             JTextField field = (JTextField) c;
197             BoundedRangeModel vis = field.getHorizontalVisibility();
198             int max = Math.max(hspan, bounds.width);
199             int value = vis.getValue();
200             int extent = Math.min(max, bounds.width - 1);
201             if ((value + extent) > max) {
202             value = max - extent;
203             }
204             vis.setRangeProperties(value, extent, vis.getMinimum(),
205                        max, false);
206             if (hspan < bounds.width) {
207             // horizontally align the interior
208
int slop = bounds.width - 1 - hspan;
209             
210             int align = ((JTextField)c).getHorizontalAlignment();
211             if(isLeftToRight(c)) {
212                 if(align==LEADING) {
213                 align = LEFT;
214                 }
215                 else if(align==TRAILING) {
216                 align = RIGHT;
217                 }
218             }
219             else {
220                 if(align==LEADING) {
221                 align = RIGHT;
222                 }
223                 else if(align==TRAILING) {
224                 align = LEFT;
225                 }
226             }
227
228             switch (align) {
229             case SwingConstants.CENTER:
230                 bounds.x += slop / 2;
231                 bounds.width -= slop;
232                 break;
233             case SwingConstants.RIGHT:
234                 bounds.x += slop;
235                 bounds.width -= slop;
236                 break;
237             }
238             } else {
239             // adjust the allocation to match the bounded range.
240
bounds.width = hspan;
241             bounds.x -= vis.getValue();
242             }
243         }
244         return bounds;
245         }
246         return null;
247     }
248
249     /**
250      * Update the visibility model with the associated JTextField
251      * (if there is one) to reflect the current visibility as a
252      * result of changes to the document model. The bounded
253      * range properties are updated. If the view hasn't yet been
254      * shown the extent will be zero and we just set it to be full
255      * until determined otherwise.
256      */

257     void updateVisibilityModel() {
258         Component c = getContainer();
259         if (c instanceof JTextField) {
260         JTextField field = (JTextField) c;
261         BoundedRangeModel vis = field.getHorizontalVisibility();
262         int hspan = (int) getPreferredSpan(X_AXIS);
263         int extent = vis.getExtent();
264         int maximum = Math.max(hspan, extent);
265         extent = (extent == 0) ? maximum : extent;
266         int value = maximum - extent;
267         int oldValue = vis.getValue();
268         if ((oldValue + extent) > maximum) {
269             oldValue = maximum - extent;
270         }
271         value = Math.max(0, Math.min(value, oldValue));
272         vis.setRangeProperties(value, extent, 0, maximum, false);
273         }
274     }
275
276     // --- View methods -------------------------------------------
277

278     /**
279      * Renders using the given rendering surface and area on that surface.
280      * The view may need to do layout and create child views to enable
281      * itself to render into the given allocation.
282      *
283      * @param g the rendering surface to use
284      * @param a the allocated region to render into
285      *
286      * @see View#paint
287      */

288         public void paint(Graphics g, Shape a) {
289         Rectangle r = (Rectangle) a;
290         g.clipRect(r.x, r.y, r.width, r.height);
291         super.paint(g, adjustAllocation(a));
292     }
293     
294     /**
295      * Determines the resizability of the view along the
296      * given axis. A value of 0 or less is not resizable.
297      *
298      * @param axis View.X_AXIS or View.Y_AXIS
299      * @return the weight -> 1 for View.X_AXIS, else 0
300      */

301         public int getResizeWeight(int axis) {
302         if (axis == View.X_AXIS) {
303         return 1;
304         }
305         return 0;
306     }
307     
308     /**
309      * Provides a mapping from the document model coordinate space
310      * to the coordinate space of the view mapped to it.
311      *
312      * @param pos the position to convert >= 0
313      * @param a the allocated region to render into
314      * @return the bounding box of the given position
315      * @exception BadLocationException if the given position does not
316      * represent a valid location in the associated document
317      * @see View#modelToView
318      */

319         public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
320         return super.modelToView(pos, adjustAllocation(a), b);
321     }
322     
323         /**
324          * Provides a mapping from the document model coordinate space
325          * to the coordinate space of the view mapped to it.
326          *
327          * @param p0 the position to convert >= 0
328          * @param b0 the bias toward the previous character or the
329          * next character represented by p0, in case the
330          * position is a boundary of two views.
331          * @param p1 the position to convert >= 0
332          * @param b1 the bias toward the previous character or the
333          * next character represented by p1, in case the
334          * position is a boundary of two views.
335          * @param a the allocated region to render into
336          * @return the bounding box of the given position is returned
337          * @exception BadLocationException if the given position does
338          * not represent a valid location in the associated document
339          * @exception IllegalArgumentException for an invalid bias argument
340          * @see View#viewToModel
341          */

342         public Shape modelToView(int p0, Position.Bias b0,
343                                  int p1, Position.Bias b1, Shape a)
344             throws BadLocationException
345         {
346             return super.modelToView(p0, b0, p1, b1, adjustAllocation(a));
347         }
348
349     /**
350      * Provides a mapping from the view coordinate space to the logical
351      * coordinate space of the model.
352      *
353      * @param fx the X coordinate >= 0.0f
354      * @param fy the Y coordinate >= 0.0f
355      * @param a the allocated region to render into
356      * @return the location within the model that best represents the
357      * given point in the view
358      * @see View#viewToModel
359      */

360         public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {
361         return super.viewToModel(fx, fy, adjustAllocation(a), bias);
362     }
363     
364     /**
365      * Gives notification that something was inserted into the document
366      * in a location that this view is responsible for.
367      *
368      * @param changes the change information from the associated document
369      * @param a the current allocation of the view
370      * @param f the factory to use to rebuild if the view has children
371      * @see View#insertUpdate
372      */

373         public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
374         super.insertUpdate(changes, adjustAllocation(a), f);
375         updateVisibilityModel();
376     }
377     
378     /**
379      * Gives notification that something was removed from the document
380      * in a location that this view is responsible for.
381      *
382      * @param changes the change information from the associated document
383      * @param a the current allocation of the view
384      * @param f the factory to use to rebuild if the view has children
385      * @see View#removeUpdate
386      */

387         public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
388         super.removeUpdate(changes, adjustAllocation(a), f);
389         updateVisibilityModel();
390     }
391     
392     }
393
394 }
395
Popular Tags