1 /* |
|
2 * Copyright 1995-2003 Sun Microsystems, Inc. All Rights Reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 package sun.awt.motif; |
|
27 |
|
28 import java.awt.*; |
|
29 import java.awt.peer.*; |
|
30 import java.awt.datatransfer.*; |
|
31 import java.awt.event.ActionEvent; |
|
32 import java.awt.event.TextEvent; |
|
33 import java.awt.im.InputMethodRequests; |
|
34 |
|
35 |
|
36 public class MTextFieldPeer extends MComponentPeer implements TextFieldPeer { |
|
37 native void pCreate(MComponentPeer parent); |
|
38 |
|
39 private boolean firstChangeSkipped; |
|
40 |
|
41 /** |
|
42 * Initialize JNI field and method IDs |
|
43 */ |
|
44 private static native void initIDs(); |
|
45 |
|
46 static { |
|
47 initIDs(); |
|
48 } |
|
49 |
|
50 void create(MComponentPeer parent) { |
|
51 firstChangeSkipped = false; |
|
52 pCreate(parent); |
|
53 } |
|
54 |
|
55 void initialize() { |
|
56 int start, end; |
|
57 |
|
58 TextField txt = (TextField)target; |
|
59 |
|
60 setText(txt.getText()); |
|
61 if (txt.echoCharIsSet()) { |
|
62 setEchoChar(txt.getEchoChar()); |
|
63 } |
|
64 |
|
65 start = txt.getSelectionStart(); |
|
66 end = txt.getSelectionEnd(); |
|
67 |
|
68 if (end > start) { |
|
69 select(start, end); |
|
70 } else { |
|
71 setCaretPosition(start); |
|
72 } |
|
73 |
|
74 if (!target.isBackgroundSet()) { |
|
75 // This is a way to set the background color of the TextArea |
|
76 // without calling setBackground - go through native C code |
|
77 setTargetBackground(SystemColor.text); |
|
78 } |
|
79 if (!target.isForegroundSet()) { |
|
80 target.setForeground(SystemColor.textText); |
|
81 } |
|
82 |
|
83 setEditable(txt.isEditable()); |
|
84 |
|
85 // oldSelectionStart = -1; // accessibility support |
|
86 // oldSelectionEnd = -1; // accessibility support |
|
87 |
|
88 super.initialize(); |
|
89 } |
|
90 |
|
91 public MTextFieldPeer(TextField target) { |
|
92 super(target); |
|
93 } |
|
94 |
|
95 public void setEditable(boolean editable) { |
|
96 pSetEditable(editable); |
|
97 |
|
98 /* 4136955 - Calling setBackground() here works around an Xt |
|
99 * bug by forcing Xt to flush an internal widget cache |
|
100 */ |
|
101 setBackground(target.getBackground()); |
|
102 } |
|
103 |
|
104 public native void pSetEditable(boolean editable); |
|
105 public native void select(int selStart, int selEnd); |
|
106 public native int getSelectionStart(); |
|
107 public native int getSelectionEnd(); |
|
108 public native void setText(String l); |
|
109 public native void insertReplaceText(String l); |
|
110 public native void preDispose(); |
|
111 public native String getText(); |
|
112 public native void setEchoChar(char c); |
|
113 public native void setFont(Font f); |
|
114 public native void setCaretPosition(int pos); |
|
115 public native int getCaretPosition(); |
|
116 |
|
117 // CDE/Motif defaults: margin=5, shadow=2, highlight=1 -- times 2. |
|
118 // Should have asked the widgets for correct values (see MTextAreaPeer). |
|
119 private static final int padding = 16; |
|
120 |
|
121 public Dimension getMinimumSize() { |
|
122 FontMetrics fm = getFontMetrics(target.getFont()); |
|
123 return new Dimension(fm.stringWidth(((TextField)target).getText())+20, |
|
124 fm.getMaxDescent() + fm.getMaxAscent() + padding); |
|
125 } |
|
126 |
|
127 public Dimension getPreferredSize(int cols) { |
|
128 return getMinimumSize(cols); |
|
129 } |
|
130 |
|
131 public Dimension getMinimumSize(int cols) { |
|
132 FontMetrics fm = getFontMetrics(target.getFont()); |
|
133 return new Dimension(fm.charWidth('0') * cols + 20, |
|
134 fm.getMaxDescent() + fm.getMaxAscent() + padding); |
|
135 } |
|
136 |
|
137 public boolean isFocusable() { |
|
138 return true; |
|
139 } |
|
140 |
|
141 // NOTE: This method is called by privileged threads. |
|
142 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
143 public void action(final long when, final int modifiers) { |
|
144 MToolkit.executeOnEventHandlerThread(target, new Runnable() { |
|
145 public void run() { |
|
146 postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED, |
|
147 ((TextField)target).getText(), when, |
|
148 modifiers)); |
|
149 } |
|
150 }); |
|
151 } |
|
152 |
|
153 protected void disposeImpl() { |
|
154 preDispose(); |
|
155 super.disposeImpl(); |
|
156 } |
|
157 |
|
158 /* |
|
159 * Post a new TextEvent when the value of a text component changes. |
|
160 */ |
|
161 public void valueChanged() { |
|
162 postEvent(new TextEvent(target, TextEvent.TEXT_VALUE_CHANGED)); |
|
163 } |
|
164 |
|
165 // Called from native widget when paste key is pressed and we |
|
166 // already own the selection (prevents Motif from hanging while |
|
167 // waiting for the selection) |
|
168 // |
|
169 // NOTE: This method is called by privileged threads. |
|
170 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
171 public void pasteFromClipboard() { |
|
172 Clipboard clipboard = target.getToolkit().getSystemClipboard(); |
|
173 |
|
174 Transferable content = clipboard.getContents(this); |
|
175 if (content != null) { |
|
176 try { |
|
177 String data = (String)(content.getTransferData(DataFlavor.stringFlavor)); |
|
178 insertReplaceText(data); |
|
179 |
|
180 } catch (Exception e) { |
|
181 } |
|
182 } |
|
183 } |
|
184 |
|
185 /* |
|
186 * Print the native component by rendering the Motif look ourselves. |
|
187 * ToDo(aim): needs to query native motif for more accurate size and |
|
188 * color information, left text offset, and selected text. |
|
189 */ |
|
190 public final static int BORDER = 2; |
|
191 public final static int MARGIN = 4; |
|
192 |
|
193 public void print(Graphics g) { |
|
194 TextField txt = (TextField)target; |
|
195 Dimension d = txt.size(); |
|
196 int w = d.width - (2 * BORDER); |
|
197 int h = d.height - (2 * BORDER); |
|
198 Color bg = txt.getBackground(); |
|
199 Color fg = txt.getForeground(); |
|
200 Color highlight = bg.brighter(); |
|
201 String text = txt.getText(); |
|
202 int moved = 0; |
|
203 int selStart = 0; |
|
204 int selEnd = 0; |
|
205 |
|
206 g.setFont(txt.getFont()); |
|
207 g.setColor(txt.isEditable() ? highlight : bg); |
|
208 g.fillRect(BORDER, BORDER, w, h); |
|
209 |
|
210 g.setColor(bg); |
|
211 //g.drawRect(0, 0, d.width-1, d.height-1); |
|
212 draw3DRect(g, bg, 1, 1, d.width-3, d.height-3, false); |
|
213 |
|
214 if (text != null) { |
|
215 g.clipRect(BORDER, MARGIN, w, d.height - (2 * MARGIN)); |
|
216 FontMetrics fm = g.getFontMetrics(); |
|
217 |
|
218 w = d.width - BORDER; |
|
219 h = d.height - (2 * MARGIN); |
|
220 int xs = pos2x(selStart) - moved; |
|
221 int xe = pos2x(selEnd) - moved; |
|
222 |
|
223 if ((xs < MARGIN) && (xe > w)) { |
|
224 g.setColor(highlight); |
|
225 g.fillRect(BORDER, MARGIN, w - BORDER, h); |
|
226 } else { |
|
227 g.setColor(bg); |
|
228 //g.fillRect(BORDER, MARGIN, w - BORDER, h); |
|
229 |
|
230 if ((xs >= MARGIN) && (xs <= w)) { |
|
231 g.setColor(highlight); // selected text |
|
232 |
|
233 if (xe > w) { |
|
234 g.fillRect(xs, MARGIN, w - xs, h); |
|
235 } else if (xs == xe) { |
|
236 //g.fillRect(xs, MARGIN, 1, h); |
|
237 } else { |
|
238 g.fillRect(xs, MARGIN, xe - xs, h); |
|
239 } |
|
240 } else if ((xe >= MARGIN) && (xe <= w)) { |
|
241 g.setColor(highlight); |
|
242 g.fillRect(BORDER, MARGIN, xe - BORDER, h); |
|
243 } |
|
244 } |
|
245 g.setColor(fg); |
|
246 int x = MARGIN - moved; |
|
247 char echoChar = txt.getEchoChar(); |
|
248 if (echoChar == 0) { |
|
249 g.drawString(text, x, BORDER + MARGIN + fm.getMaxAscent()); |
|
250 } else { |
|
251 char data[] = new char[text.length()]; |
|
252 for (int i = 0 ; i < data.length ; i++) { |
|
253 data[i] = echoChar; |
|
254 } |
|
255 g.drawChars(data, 0, data.length, x, |
|
256 BORDER + MARGIN + fm.getMaxAscent()); |
|
257 |
|
258 } |
|
259 } |
|
260 |
|
261 target.print(g); |
|
262 } |
|
263 |
|
264 int pos2x(int pos) { |
|
265 TextField txt = (TextField)target; |
|
266 FontMetrics fm = getFontMetrics(txt.getFont()); |
|
267 int x = MARGIN, widths[] = fm.getWidths(); |
|
268 String text = txt.getText(); |
|
269 char echoChar = txt.getEchoChar(); |
|
270 if (echoChar == 0) { |
|
271 for (int i = 0 ; i < pos ; i++) { |
|
272 x += widths[text.charAt(i)]; |
|
273 } |
|
274 } else { |
|
275 x += widths[echoChar] * pos; |
|
276 } |
|
277 return x; |
|
278 } |
|
279 |
|
280 /** |
|
281 * DEPRECATED |
|
282 */ |
|
283 public void setEchoCharacter(char c) { |
|
284 setEchoChar(c); |
|
285 } |
|
286 |
|
287 /** |
|
288 * DEPRECATED |
|
289 */ |
|
290 public Dimension minimumSize() { |
|
291 return getMinimumSize(); |
|
292 } |
|
293 |
|
294 /** |
|
295 * DEPRECATED |
|
296 */ |
|
297 public Dimension minimumSize(int cols) { |
|
298 return getMinimumSize(cols); |
|
299 } |
|
300 |
|
301 /** |
|
302 * DEPRECATED |
|
303 */ |
|
304 public Dimension preferredSize(int cols) { |
|
305 return getPreferredSize(cols); |
|
306 } |
|
307 void pShow(){ |
|
308 super.pShow(); |
|
309 notifyTextComponentChange(true); |
|
310 } |
|
311 |
|
312 void pHide(){ |
|
313 notifyTextComponentChange(false); |
|
314 super.pHide(); |
|
315 } |
|
316 |
|
317 void pDispose(){ |
|
318 notifyTextComponentChange(false); |
|
319 super.pDispose(); |
|
320 } |
|
321 |
|
322 public InputMethodRequests getInputMethodRequests() { |
|
323 return null; |
|
324 } |
|
325 |
|
326 |
|
327 |
|
328 // |
|
329 // Accessibility support |
|
330 // |
|
331 |
|
332 // stub functions: to be fully implemented in a future release |
|
333 public int getIndexAtPoint(int x, int y) { return -1; } |
|
334 public Rectangle getCharacterBounds(int i) { return null; } |
|
335 public long filterEvents(long mask) { return 0; } |
|
336 |
|
337 |
|
338 /* To be fully implemented in a future release |
|
339 |
|
340 int oldSelectionStart; |
|
341 int oldSelectionEnd; |
|
342 |
|
343 public native int getIndexAtPoint(int x, int y); |
|
344 public native Rectangle getCharacterBounds(int i); |
|
345 public native long filterEvents(long mask); |
|
346 |
|
347 /** |
|
348 * Handle a change in the text selection endpoints |
|
349 * (Note: could be simply a change in the caret location) |
|
350 * |
|
351 public void selectionValuesChanged(int start, int end) { |
|
352 return; // Need to write implemetation of this. |
|
353 } |
|
354 */ |
|
355 |
|
356 } |
|