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 setCaretPosition(getTarget().getCaretPosition());
75 getTarget().addInputMethodListener(this);
76 final int start = getTarget().getSelectionStart();
77 final int end = getTarget().getSelectionEnd();
78 if (end > start) {
79 select(start, end);
80 }
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 }
--- EOF ---