1 /*
2 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.awt.X11;
27
28 import java.awt.*;
29 import java.awt.peer.*;
30 import java.awt.event.*;
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.awt.event.TextEvent;
34 import javax.swing.text.*;
35 import javax.swing.event.DocumentListener;
36 import javax.swing.event.DocumentEvent;
37 import javax.swing.plaf.ComponentUI;
38 import javax.swing.InputMap;
39 import javax.swing.JPasswordField;
40 import javax.swing.SwingUtilities;
41 import javax.swing.TransferHandler;
42
43 import java.awt.event.MouseEvent;
44 import java.awt.event.FocusEvent;
45 import java.awt.event.KeyEvent;
46
47 import javax.swing.plaf.UIResource;
48 import javax.swing.UIDefaults;
49 import javax.swing.JTextField;
50 import javax.swing.JComponent;
51 import javax.swing.border.Border;
52 import com.sun.java.swing.plaf.motif.*;
53 import java.awt.im.InputMethodRequests;
54
55 import sun.util.logging.PlatformLogger;
56
57 import sun.awt.CausedFocusEvent;
58 import sun.awt.AWTAccessor;
59
60 public class XTextFieldPeer extends XComponentPeer implements TextFieldPeer {
61 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XTextField");
62
63 String text;
64 XAWTTextField xtext;
65
66 boolean firstChangeSkipped;
67
68 public XTextFieldPeer(TextField target) {
69 super(target);
70 int start, end;
71 firstChangeSkipped = false;
72 text = target.getText();
73 xtext = new XAWTTextField(text,this, target.getParent());
74 xtext.getDocument().addDocumentListener(xtext);
75 xtext.setCursor(target.getCursor());
76 XToolkit.specialPeerMap.put(xtext,this);
77
78 TextField txt = (TextField) target;
79 initTextField();
80 setText(txt.getText());
81 if (txt.echoCharIsSet()) {
82 setEchoChar(txt.getEchoChar());
83 }
84 else setEchoChar((char)0);
85
86 start = txt.getSelectionStart();
87 end = txt.getSelectionEnd();
88
89 if (end > start) {
90 select(start, end);
91 }
92 // Fix for 5100200
93 // Restoring Motif behaviour
94 // Since the end position of the selected text can be greater then the length of the text,
95 // so we should set caret to max position of the text
96 int caretPosition = Math.min(end, text.length());
97 setCaretPosition(caretPosition);
98
99 setEditable(txt.isEditable());
100
101 // After this line we should not change the component's text
102 firstChangeSkipped = true;
103 }
104
105 public void dispose() {
106 XToolkit.specialPeerMap.remove(xtext);
107 // visible caret has a timer thread which must be stopped
108 xtext.getCaret().setVisible(false);
109 xtext.removeNotify();
110 super.dispose();
111 }
112
113 void initTextField() {
114 setVisible(target.isVisible());
115
116 setBounds(x, y, width, height, SET_BOUNDS);
117
118 AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
119 foreground = compAccessor.getForeground(target);
120 if (foreground == null)
121 foreground = SystemColor.textText;
122
123 setForeground(foreground);
124
125 background = compAccessor.getBackground(target);
126 if (background == null) {
127 if (((TextField)target).isEditable()) background = SystemColor.text;
128 else background = SystemColor.control;
129 }
130 setBackground(background);
131
132 if (!target.isBackgroundSet()) {
133 // This is a way to set the background color of the TextArea
134 // without calling setBackground - go through accessor
135 compAccessor.setBackground(target, background);
136 }
137 if (!target.isForegroundSet()) {
138 target.setForeground(SystemColor.textText);
139 }
140
141 setFont(font);
142 }
143
144
145 /**
146 * @see java.awt.peer.TextComponentPeer
147 */
148 public void setEditable(boolean editable) {
149 if (xtext != null) {
150 xtext.setEditable(editable);
151 xtext.repaint();
152 }
153 }
154
155 /**
156 * @see java.awt.peer.ComponentPeer
157 */
158 public void setEnabled(boolean enabled) {
159 super.setEnabled(enabled);
160 if (xtext != null) {
161 xtext.setEnabled(enabled);
162 xtext.repaint();
163 }
164 }
165
166 /**
167 * @see java.awt.peer.TextComponentPeer
168 */
169
170 public InputMethodRequests getInputMethodRequests() {
171 if (xtext != null) return xtext.getInputMethodRequests();
172 else return null;
173
174 }
175
176 void handleJavaInputMethodEvent(InputMethodEvent e) {
177 if (xtext != null)
178 xtext.processInputMethodEventImpl(e);
179 }
180
181
182 /**
183 * @see java.awt.peer.TextFieldPeer
184 */
185 public void setEchoChar(char c) {
186 if (xtext != null) {
187 xtext.setEchoChar(c);
188 xtext.putClientProperty("JPasswordField.cutCopyAllowed",
189 xtext.echoCharIsSet() ? Boolean.FALSE : Boolean.TRUE);
190 }
191 }
192
193 /**
194 * @see java.awt.peer.TextComponentPeer
195 */
196 public int getSelectionStart() {
197 return xtext.getSelectionStart();
198 }
199
200 /**
201 * @see java.awt.peer.TextComponentPeer
202 */
203 public int getSelectionEnd() {
204 return xtext.getSelectionEnd();
205 }
206
207 /**
208 * @see java.awt.peer.TextComponentPeer
209 */
210 public String getText() {
211 return xtext.getText();
212 }
213
214 /**
215 * @see java.awt.peer.TextComponentPeer
216 */
217 public void setText(String txt) {
218 setXAWTTextField(txt);
219 repaint();
220 }
221
222 protected boolean setXAWTTextField(String txt) {
223 text = txt;
224 if (xtext != null) {
225 // JTextField.setText() posts two different events (remove & insert).
226 // Since we make no differences between text events,
227 // the document listener has to be disabled while
228 // JTextField.setText() is called.
229 xtext.getDocument().removeDocumentListener(xtext);
230 xtext.setText(txt);
231 if (firstChangeSkipped) {
232 postEvent(new TextEvent(target, TextEvent.TEXT_VALUE_CHANGED));
233 }
234 xtext.getDocument().addDocumentListener(xtext);
235 xtext.setCaretPosition(0);
236 }
237 return true;
238 }
239
240 /**
241 * to be implemented.
242 * @see java.awt.peer.TextComponentPeer
243 */
244 public void setCaretPosition(int position) {
245 if (xtext != null) xtext.setCaretPosition(position);
246 }
247
248 /**
249 * DEPRECATED
250 * @see java.awt.peer.TextFieldPeer
251 */
252 public void setEchoCharacter(char c) {
253 setEchoChar(c);
254 }
255
256 void repaintText() {
257 xtext.repaintNow();
258 }
259
260 public void setBackground(Color c) {
261 if (log.isLoggable(PlatformLogger.Level.FINE)) {
262 log.fine("target="+ target + ", old=" + background + ", new=" + c);
263 }
264 background = c;
265 if (xtext != null) {
266 xtext.setBackground(c);
267 xtext.setSelectedTextColor(c);
268 }
269 repaintText();
270 }
271
272 public void setForeground(Color c) {
273 foreground = c;
274 if (xtext != null) {
275 xtext.setForeground(foreground);
276 xtext.setSelectionColor(foreground);
277 xtext.setCaretColor(foreground);
278 }
279 repaintText();
280 }
281
282 public void setFont(Font f) {
283 synchronized (getStateLock()) {
284 font = f;
285 if (xtext != null) {
286 xtext.setFont(font);
287 }
288 }
289 xtext.validate();
290 }
291
292 /**
293 * DEPRECATED
294 * @see java.awt.peer.TextFieldPeer
295 */
296 public Dimension preferredSize(int cols) {
297 return getPreferredSize(cols);
298 }
299
300 /**
301 * Deselects the the highlighted text.
302 */
303 public void deselect() {
304 int selStart=xtext.getSelectionStart();
305 int selEnd=xtext.getSelectionEnd();
306 if (selStart != selEnd) {
307 xtext.select(selStart,selStart);
308 }
309 }
310
311
312 /**
313 * to be implemented.
314 * @see java.awt.peer.TextComponentPeer
315 */
316 public int getCaretPosition() {
317 return xtext.getCaretPosition();
318 }
319
320
321
322 /**
323 * @see java.awt.peer.TextComponentPeer
324 */
325 public void select(int s, int e) {
326 xtext.select(s,e);
327 // Fixed 5100806
328 // We must take care that Swing components repainted correctly
329 xtext.repaint();
330 }
331
332
333 public Dimension getMinimumSize() {
334 return xtext.getMinimumSize();
335 }
336
337 public Dimension getPreferredSize() {
338 return xtext.getPreferredSize();
339 }
340
341 public Dimension getPreferredSize(int cols) {
342 return getMinimumSize(cols);
343 }
344
345 private static final int PADDING = 16;
346
347 public Dimension getMinimumSize(int cols) {
348 Font f = xtext.getFont();
349 FontMetrics fm = xtext.getFontMetrics(f);
350 return new Dimension(fm.charWidth('0') * cols + 10,
351 fm.getMaxDescent() + fm.getMaxAscent() + PADDING);
352
353 }
354
355 public boolean isFocusable() {
356 return true;
357 }
358
359 // NOTE: This method is called by privileged threads.
360 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
361 public void action(final long when, final int modifiers) {
362 postEvent(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
363 text, when,
364 modifiers));
365 }
366
367
368 protected void disposeImpl() {
369 }
370
371
372 public void repaint() {
373 if (xtext != null) xtext.repaint();
374 }
375 @Override
376 void paintPeer(final Graphics g) {
377 if (xtext != null) xtext.paint(g);
378 }
379
380 public void print(Graphics g) {
381 if (xtext != null) {
382 xtext.print(g);
383 }
384 }
385
386 public void focusLost(FocusEvent e) {
387 super.focusLost(e);
388 xtext.forwardFocusLost(e);
389 }
390
391 public void focusGained(FocusEvent e) {
392 super.focusGained(e);
393 xtext.forwardFocusGained(e);
394 }
395
396 void handleJavaKeyEvent(KeyEvent e) {
397 AWTAccessor.getComponentAccessor().processEvent(xtext,e);
398 }
399
400
401 public void handleJavaMouseEvent( MouseEvent mouseEvent ) {
402 super.handleJavaMouseEvent(mouseEvent);
403 if (xtext != null) {
404 mouseEvent.setSource(xtext);
405 int id = mouseEvent.getID();
406 if (id == MouseEvent.MOUSE_DRAGGED || id == MouseEvent.MOUSE_MOVED)
407 xtext.processMouseMotionEventImpl(mouseEvent);
408 else
409 xtext.processMouseEventImpl(mouseEvent);
410 }
411 }
412
413
414 /**
415 * DEPRECATED
416 */
417 public Dimension minimumSize() {
418 return getMinimumSize();
419 }
420
421 /**
422 * DEPRECATED
423 */
424 public Dimension minimumSize(int cols) {
425 return getMinimumSize(cols);
426 }
427
428 public void setVisible(boolean b) {
429 super.setVisible(b);
430 if (xtext != null) xtext.setVisible(b);
431 }
432
433 public void setBounds(int x, int y, int width, int height, int op) {
434 super.setBounds(x, y, width, height, op);
435 if (xtext != null) {
436 /*
437 * Fixed 6277332, 6198290:
438 * the coordinates is coming (to peer): relatively to closest HW parent
439 * the coordinates is setting (to textField): relatively to closest ANY parent
440 * the parent of peer is target.getParent()
441 * the parent of textField is the same
442 * see 6277332, 6198290 for more information
443 */
444 int childX = x;
445 int childY = y;
446 Component parent = target.getParent();
447 // we up to heavyweight parent in order to be sure
448 // that the coordinates of the text pane is relatively to closest parent
449 while (parent.isLightweight()){
450 childX -= parent.getX();
451 childY -= parent.getY();
452 parent = parent.getParent();
453 }
454 xtext.setBounds(childX,childY,width,height);
455 xtext.validate();
456 }
457 }
458
459
460 //
461 // Accessibility support
462 //
463
464 // stub functions: to be fully implemented in a future release
465 public int getIndexAtPoint(int x, int y) { return -1; }
466 public Rectangle getCharacterBounds(int i) { return null; }
467 public long filterEvents(long mask) { return 0; }
468
469
470 /* To be fully implemented in a future release
471
472 int oldSelectionStart;
473 int oldSelectionEnd;
474
475 public native int getIndexAtPoint(int x, int y);
476 public native Rectangle getCharacterBounds(int i);
477 public native long filterEvents(long mask);
478
479 /**
480 * Handle a change in the text selection endpoints
481 * (Note: could be simply a change in the caret location)
482 *
483 public void selectionValuesChanged(int start, int end) {
484 return; // Need to write implemetation of this.
485 }
486 */
487
488
489 class AWTTextFieldUI extends MotifPasswordFieldUI {
490
491 /**
492 * Creates a UI for a JTextField.
493 *
494 * @param c the text field
495 * @return the UI
496 */
497 JTextField jtf;
498
499
500 protected String getPropertyPrefix() {
501 JTextComponent comp = getComponent();
502 if (comp instanceof JPasswordField && ((JPasswordField)comp).echoCharIsSet()) {
503 return "PasswordField";
504 } else {
505 return "TextField";
506 }
507 }
508
509 public void installUI(JComponent c) {
510 super.installUI(c);
511
512 jtf = (JTextField) c;
513
514 JTextField editor = jtf;
515
516 UIDefaults uidefaults = XToolkit.getUIDefaults();
517
518 String prefix = getPropertyPrefix();
519 Font f = editor.getFont();
520 if ((f == null) || (f instanceof UIResource)) {
521 editor.setFont(uidefaults.getFont(prefix + ".font"));
522 }
523
524 Color bg = editor.getBackground();
525 if ((bg == null) || (bg instanceof UIResource)) {
526 editor.setBackground(uidefaults.getColor(prefix + ".background"));
527 }
528
529 Color fg = editor.getForeground();
530 if ((fg == null) || (fg instanceof UIResource)) {
531 editor.setForeground(uidefaults.getColor(prefix + ".foreground"));
532 }
533
534 Color color = editor.getCaretColor();
535 if ((color == null) || (color instanceof UIResource)) {
536 editor.setCaretColor(uidefaults.getColor(prefix + ".caretForeground"));
537 }
538
539 Color s = editor.getSelectionColor();
540 if ((s == null) || (s instanceof UIResource)) {
541 editor.setSelectionColor(uidefaults.getColor(prefix + ".selectionBackground"));
542 }
543
544 Color sfg = editor.getSelectedTextColor();
545 if ((sfg == null) || (sfg instanceof UIResource)) {
546 editor.setSelectedTextColor(uidefaults.getColor(prefix + ".selectionForeground"));
547 }
548
549 Color dfg = editor.getDisabledTextColor();
550 if ((dfg == null) || (dfg instanceof UIResource)) {
551 editor.setDisabledTextColor(uidefaults.getColor(prefix + ".inactiveForeground"));
552 }
553
554 Border b = editor.getBorder();
555 if ((b == null) || (b instanceof UIResource)) {
556 editor.setBorder(uidefaults.getBorder(prefix + ".border"));
557 }
558
559 Insets margin = editor.getMargin();
560 if (margin == null || margin instanceof UIResource) {
561 editor.setMargin(uidefaults.getInsets(prefix + ".margin"));
562 }
563 }
564
565 protected void installKeyboardActions() {
566 super.installKeyboardActions();
567
568 JTextComponent comp = getComponent();
569
570 UIDefaults uidefaults = XToolkit.getUIDefaults();
571
572 String prefix = getPropertyPrefix();
573
574 InputMap map = (InputMap)uidefaults.get(prefix + ".focusInputMap");
575
576 if (map != null) {
577 SwingUtilities.replaceUIInputMap(comp, JComponent.WHEN_FOCUSED,
578 map);
579 }
580 }
581
582 protected Caret createCaret() {
583 return new XTextAreaPeer.XAWTCaret();
584 }
585 }
586
587 class XAWTTextField extends JPasswordField
588 implements ActionListener,
589 DocumentListener
590 {
591
592 boolean isFocused = false;
593
594 XComponentPeer peer;
595
596 public XAWTTextField(String text, XComponentPeer peer, Container parent) {
597 super(text);
598 this.peer = peer;
599 setDoubleBuffered(true);
600 setFocusable(false);
601 AWTAccessor.getComponentAccessor().setParent(this,parent);
602 setBackground(peer.getPeerBackground());
603 setForeground(peer.getPeerForeground());
604 setFont(peer.getPeerFont());
605 setCaretPosition(0);
606 addActionListener(this);
607 addNotify();
608
609 }
610
611 public void actionPerformed( ActionEvent actionEvent ) {
612 peer.postEvent(new ActionEvent(peer.target,
613 ActionEvent.ACTION_PERFORMED,
614 getText(),
615 actionEvent.getWhen(),
616 actionEvent.getModifiers()));
617
618 }
619
620 public void insertUpdate(DocumentEvent e) {
621 if (peer != null) {
622 peer.postEvent(new TextEvent(peer.target,
623 TextEvent.TEXT_VALUE_CHANGED));
624 }
625 }
626
627 public void removeUpdate(DocumentEvent e) {
628 if (peer != null) {
629 peer.postEvent(new TextEvent(peer.target,
630 TextEvent.TEXT_VALUE_CHANGED));
631 }
632 }
633
634 public void changedUpdate(DocumentEvent e) {
635 if (peer != null) {
636 peer.postEvent(new TextEvent(peer.target,
637 TextEvent.TEXT_VALUE_CHANGED));
638 }
639 }
640
641 public ComponentPeer getPeer() {
642 return (ComponentPeer) peer;
643 }
644
645
646 public void repaintNow() {
647 paintImmediately(getBounds());
648 }
649
650 public Graphics getGraphics() {
651 return peer.getGraphics();
652 }
653
654 public void updateUI() {
655 ComponentUI ui = new AWTTextFieldUI();
656 setUI(ui);
657 }
658
659
660 void forwardFocusGained( FocusEvent e) {
661 isFocused = true;
662 FocusEvent fe = CausedFocusEvent.retarget(e, this);
663 super.processFocusEvent(fe);
664
665 }
666
667
668 void forwardFocusLost( FocusEvent e) {
669 isFocused = false;
670 FocusEvent fe = CausedFocusEvent.retarget(e, this);
671 super.processFocusEvent(fe);
672
673 }
674
675 public boolean hasFocus() {
676 return isFocused;
677 }
678
679
680 public void processInputMethodEventImpl(InputMethodEvent e) {
681 processInputMethodEvent(e);
682 }
683
684 public void processMouseEventImpl(MouseEvent e) {
685 processMouseEvent(e);
686 }
687
688 public void processMouseMotionEventImpl(MouseEvent e) {
689 processMouseMotionEvent(e);
690 }
691
692 // Fix for 4915454 - override the default implementation to avoid
693 // loading SystemFlavorMap and associated classes.
694 public void setTransferHandler(TransferHandler newHandler) {
695 TransferHandler oldHandler = (TransferHandler)
696 getClientProperty(AWTAccessor.getClientPropertyKeyAccessor()
697 .getJComponent_TRANSFER_HANDLER());
698 putClientProperty(AWTAccessor.getClientPropertyKeyAccessor()
699 .getJComponent_TRANSFER_HANDLER(),
700 newHandler);
701
702 firePropertyChange("transferHandler", oldHandler, newHandler);
703 }
704
705 public void setEchoChar(char c) {
706 super.setEchoChar(c);
707 ((AWTTextFieldUI)ui).installKeyboardActions();
708 }
709 }
710 }
--- EOF ---