39
39
package javax.swing.text;
41
41
import java.awt.Component;
42
import java.awt.ComponentOrientation;
42
import java.awt.Container;
43
43
import java.awt.FontMetrics;
44
44
import java.awt.Graphics;
45
import java.awt.Insets;
45
46
import java.awt.Rectangle;
46
47
import java.awt.Shape;
48
import java.awt.event.ActionEvent;
49
import java.awt.event.ActionListener;
51
import javax.swing.BoundedRangeModel;
48
52
import javax.swing.JTextField;
53
import javax.swing.event.ChangeEvent;
54
import javax.swing.event.ChangeListener;
49
55
import javax.swing.event.DocumentEvent;
51
57
public class FieldView extends PlainView
59
BoundedRangeModel horizontalVisibility;
61
/** Caches the preferred span of the X axis. It is invalidated by
62
* setting it to -1f. This is done when text in the document
63
* is inserted, removed or changed. The value is corrected as
64
* soon as calculateHorizontalSpan() is called.
66
float cachedSpan = -1f;
53
68
public FieldView(Element elem)
74
/** Checks whether the given container is a JTextField. If so
75
* it retrieves the textfield's horizontalVisibility instance.
77
* <p>This method should be only called when the view's container
78
* is valid. Naturally that would be the setParent() method however
79
* that method is not overridden in the RI and that is why we chose
80
* paint() instead.</p>
82
private void checkContainer()
84
Container c = getContainer();
86
if (c instanceof JTextField)
88
horizontalVisibility = ((JTextField) c).getHorizontalVisibility();
90
// Provokes a repaint when the BoundedRangeModel's values change
91
// (which is what the RI does).
92
horizontalVisibility.addChangeListener(new ChangeListener(){
93
public void stateChanged(ChangeEvent event) {
94
getContainer().repaint();
98
// It turned out that the span calculated at this point is wrong
99
// and needs to be recalculated (e.g. a different font setting is
100
// not taken into account).
101
calculateHorizontalSpan();
103
// Initializes the BoundedRangeModel properly.
109
private void updateVisibility()
111
JTextField tf = (JTextField) getContainer();
112
Insets insets = tf.getInsets();
114
int width = tf.getWidth() - insets.left - insets.right;
116
horizontalVisibility.setMaximum(Math.max((int) ((cachedSpan != -1f)
118
: calculateHorizontalSpan()),
121
horizontalVisibility.setExtent(width - 1);
58
124
protected FontMetrics getFontMetrics()
73
139
protected Shape adjustAllocation(Shape shape)
141
// Return null when the original allocation is null (like the RI).
75
145
Rectangle rectIn = shape.getBounds();
76
146
// vertical adjustment
77
147
int height = (int) getPreferredSpan(Y_AXIS);
78
148
int y = rectIn.y + (rectIn.height - height) / 2;
79
149
// horizontal adjustment
80
150
JTextField textField = (JTextField) getContainer();
81
int halign = textField.getHorizontalAlignment();
82
int width = (int) getPreferredSpan(X_AXIS);
151
int width = (int) ((cachedSpan != -1f) ? cachedSpan : calculateHorizontalSpan());
84
ComponentOrientation orientation = textField.getComponentOrientation();
87
case JTextField.CENTER:
88
x = rectIn.x + (rectIn.width - width) / 2;
90
case JTextField.RIGHT:
91
x = rectIn.x + (rectIn.width - width);
93
case JTextField.TRAILING:
94
if (orientation.isLeftToRight())
95
x = rectIn.x + (rectIn.width - width);
99
case JTextField.LEADING:
100
if (orientation.isLeftToRight())
103
x = rectIn.x + (rectIn.width - width);
105
case JTextField.LEFT:
153
if (horizontalVisibility != null && horizontalVisibility.getExtent() < width)
154
x = rectIn.x - horizontalVisibility.getValue();
156
switch (textField.getHorizontalAlignment())
158
case JTextField.CENTER:
159
x = rectIn.x + (rectIn.width - width) / 2;
161
case JTextField.RIGHT:
162
x = rectIn.x + (rectIn.width - width - 1);
164
case JTextField.TRAILING:
165
if (textField.getComponentOrientation().isLeftToRight())
166
x = rectIn.x + (rectIn.width - width - 1);
170
case JTextField.LEADING:
171
if (textField.getComponentOrientation().isLeftToRight())
174
x = rectIn.x + (rectIn.width - width - 1);
176
case JTextField.LEFT:
110
182
return new Rectangle(x, y, width, height);
115
187
if (axis != X_AXIS && axis != Y_AXIS)
116
188
throw new IllegalArgumentException();
118
FontMetrics fm = getFontMetrics();
120
191
if (axis == Y_AXIS)
121
192
return super.getPreferredSpan(axis);
194
if (cachedSpan != -1f)
197
return calculateHorizontalSpan();
200
/** Calculates and sets the horizontal span and stores the value
203
private float calculateHorizontalSpan()
205
Segment s = getLineBuffer();
124
206
Element elem = getElement();
128
text = elem.getDocument().getText(elem.getStartOffset(),
129
elem.getEndOffset());
210
elem.getDocument().getText(elem.getStartOffset(),
211
elem.getEndOffset() - 1,
214
return cachedSpan = Utilities.getTabbedTextWidth(s, getFontMetrics(), 0, this, s.offset);
131
216
catch (BadLocationException e)
133
// This should never happen.
218
// Should never happen
219
AssertionError ae = new AssertionError();
137
return fm.stringWidth(text) + 30;
140
225
public int getResizeWeight(int axis)
152
237
public void paint(Graphics g, Shape s)
239
if (horizontalVisibility == null)
154
242
Shape newAlloc = adjustAllocation(s);
244
// Set a clip to prevent drawing outside of the allocation area.
245
// TODO: Is there a better way to achieve this?
246
Shape clip = g.getClip();
155
248
super.paint(g, newAlloc);
158
252
public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
256
if (horizontalVisibility != null)
160
259
Shape newAlloc = adjustAllocation(shape);
161
261
super.insertUpdate(ev, newAlloc, vf);
162
262
getContainer().repaint();
165
265
public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
269
if (horizontalVisibility != null)
167
272
Shape newAlloc = adjustAllocation(shape);
168
273
super.removeUpdate(ev, newAlloc, vf);
169
274
getContainer().repaint();
172
277
public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
281
if (horizontalVisibility != null)
174
284
Shape newAlloc = adjustAllocation(shape);
175
super.removeUpdate(ev, newAlloc, vf);
285
super.changedUpdate(ev, newAlloc, vf);
176
286
getContainer().repaint();
179
289
public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias)
181
return super.viewToModel(fx, fy, a, bias);
291
return super.viewToModel(fx, fy, adjustAllocation(a), bias);