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