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