blob: f11f5597c7cd88c3bd0829173b4bfb0cead6ca46 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
26package sun.awt.motif;
27
28import java.awt.*;
29import java.awt.peer.*;
30import java.awt.datatransfer.*;
31import java.awt.event.ActionEvent;
32import java.awt.event.TextEvent;
33import java.awt.im.InputMethodRequests;
34
35
36public 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}