1 /* 2 * Copyright (c) 2011, 2012, 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 27 package sun.lwawt; 28 29 import java.awt.Dimension; 30 import java.awt.FontMetrics; 31 import java.awt.Insets; 32 import java.awt.SystemColor; 33 import java.awt.TextComponent; 34 import java.awt.event.TextEvent; 35 import java.awt.event.InputMethodListener; 36 import java.awt.event.InputMethodEvent; 37 import java.awt.im.InputMethodRequests; 38 import java.awt.peer.TextComponentPeer; 39 import sun.awt.AWTAccessor; 40 41 import javax.swing.JComponent; 42 import javax.swing.event.DocumentEvent; 43 import javax.swing.event.DocumentListener; 44 import javax.swing.text.Document; 45 import javax.swing.text.JTextComponent; 46 47 abstract class LWTextComponentPeer<T extends TextComponent, D extends JComponent> 48 extends LWComponentPeer<T, D> 49 implements DocumentListener, TextComponentPeer, InputMethodListener { 50 51 52 private volatile boolean firstChangeSkipped; 53 54 LWTextComponentPeer(final T target, 55 final PlatformComponent platformComponent) { 56 super(target, platformComponent); 57 if (!getTarget().isBackgroundSet()) { 58 getTarget().setBackground(SystemColor.text); 59 } 60 } 61 62 @Override 63 void initializeImpl() { 64 super.initializeImpl(); 65 synchronized (getDelegateLock()) { 66 // This listener should be added before setText(). 67 getTextComponent().getDocument().addDocumentListener(this); 68 } 69 setEditable(getTarget().isEditable()); 70 setText(getTarget().getText()); 71 getTarget().addInputMethodListener(this); 72 final int start = getTarget().getSelectionStart(); 73 final int end = getTarget().getSelectionEnd(); 74 if (end > start) { 75 select(start, end); 76 } 77 setCaretPosition(getTarget().getCaretPosition()); 78 firstChangeSkipped = true; 79 } 80 81 @Override 82 protected final void disposeImpl() { 83 synchronized (getDelegateLock()) { 84 // visible caret has a timer thread which must be stopped 85 getTextComponent().getCaret().setVisible(false); 86 } 87 super.disposeImpl(); 88 } 89 90 /** 91 * This method should be called under getDelegateLock(). 92 */ 93 abstract JTextComponent getTextComponent(); 94 95 public Dimension getMinimumSize(final int rows, final int columns) { 96 final Insets insets; 97 synchronized (getDelegateLock()) { 98 insets = getTextComponent().getInsets(); 99 } 100 final int borderHeight = insets.top + insets.bottom; 101 final int borderWidth = insets.left + insets.right; 102 final FontMetrics fm = getFontMetrics(getFont()); 103 return new Dimension(fm.charWidth(WIDE_CHAR) * columns + borderWidth, 104 fm.getHeight() * rows + borderHeight); 105 } 106 107 @Override 108 public final void setEditable(final boolean editable) { 109 synchronized (getDelegateLock()) { 110 getTextComponent().setEditable(editable); 111 } 112 } 113 114 @Override 115 public final String getText() { 116 synchronized (getDelegateLock()) { 117 return getTextComponent().getText(); 118 } 119 } 120 121 @Override 122 public final void setText(final String l) { 123 synchronized (getDelegateLock()) { 124 // JTextArea.setText() posts two different events (remove & insert). 125 // Since we make no differences between text events, 126 // the document listener has to be disabled while 127 // JTextArea.setText() is called. 128 final Document document = getTextComponent().getDocument(); 129 document.removeDocumentListener(this); 130 getTextComponent().setText(l); 131 revalidate(); 132 if (firstChangeSkipped) { 133 postEvent(new TextEvent(getTarget(), 134 TextEvent.TEXT_VALUE_CHANGED)); 135 } 136 document.addDocumentListener(this); 137 } 138 repaintPeer(); 139 } 140 141 @Override 142 public final int getSelectionStart() { 143 synchronized (getDelegateLock()) { 144 return getTextComponent().getSelectionStart(); 145 } 146 } 147 148 @Override 149 public final int getSelectionEnd() { 150 synchronized (getDelegateLock()) { 151 return getTextComponent().getSelectionEnd(); 152 } 153 } 154 155 @Override 156 public final void select(final int selStart, final int selEnd) { 157 synchronized (getDelegateLock()) { 158 getTextComponent().select(selStart, selEnd); 159 } 160 repaintPeer(); 161 } 162 163 @Override 164 public final void setCaretPosition(final int pos) { 165 synchronized (getDelegateLock()) { 166 getTextComponent().setCaretPosition(pos); 167 } 168 repaintPeer(); 169 } 170 171 @Override 172 public final int getCaretPosition() { 173 synchronized (getDelegateLock()) { 174 return getTextComponent().getCaretPosition(); 175 } 176 } 177 178 @Override 179 public final InputMethodRequests getInputMethodRequests() { 180 synchronized (getDelegateLock()) { 181 return getTextComponent().getInputMethodRequests(); 182 } 183 } 184 185 //TODO IN XAWT we just return true.. 186 @Override 187 public final boolean isFocusable() { 188 return getTarget().isFocusable(); 189 } 190 191 protected final void revalidate() { 192 synchronized (getDelegateLock()) { 193 getTextComponent().invalidate(); 194 getDelegate().validate(); 195 } 196 } 197 198 protected final void postTextEvent() { 199 postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED)); 200 synchronized (getDelegateLock()) { 201 revalidate(); 202 } 203 } 204 205 @Override 206 public final void changedUpdate(final DocumentEvent e) { 207 postTextEvent(); 208 } 209 210 @Override 211 public final void insertUpdate(final DocumentEvent e) { 212 postTextEvent(); 213 } 214 215 @Override 216 public final void removeUpdate(final DocumentEvent e) { 217 postTextEvent(); 218 } 219 220 @Override 221 public void inputMethodTextChanged(InputMethodEvent event) { 222 synchronized (getDelegateLock()) { 223 AWTAccessor.getComponentAccessor().processEvent(getTextComponent(), event); 224 } 225 } 226 227 @Override 228 public void caretPositionChanged(InputMethodEvent event) { 229 synchronized (getDelegateLock()) { 230 AWTAccessor.getComponentAccessor().processEvent(getTextComponent(), event); 231 } 232 } 233 }