1 /*
2 * Copyright (c) 2011, 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 * Character with reasonable value between the minimum width and maximum.
53 */
54 protected static final char WIDE_CHAR = 'w';
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 public void initialize() {
67 super.initialize();
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 abstract JTextComponent getTextComponent();
85
86 public Dimension getPreferredSize(final int rows, final int columns) {
87 final Insets insets;
88 synchronized (getDelegateLock()) {
89 insets = getDelegate().getInsets();
90 }
91 final int borderHeight = insets.top + insets.bottom;
92 final int borderWidth = insets.left + insets.right;
93 final FontMetrics fm = getFontMetrics(getFont());
94 final int charWidth = (fm != null) ? fm.charWidth(WIDE_CHAR) : 10;
95 final int itemHeight = (fm != null) ? fm.getHeight() : 10;
96 return new Dimension(columns * charWidth + borderWidth,
97 rows * itemHeight + borderHeight);
98 }
99
100 @Override
101 public final void setEditable(final boolean editable) {
102 synchronized (getDelegateLock()) {
103 getTextComponent().setEditable(editable);
104 }
105 }
106
107 @Override
108 public final String getText() {
109 synchronized (getDelegateLock()) {
110 return getTextComponent().getText();
111 }
112 }
113
114 @Override
115 public void setText(final String l) {
116 synchronized (getDelegateLock()) {
117 // JTextArea.setText() posts two different events (remove & insert).
118 // Since we make no differences between text events,
119 // the document listener has to be disabled while
120 // JTextArea.setText() is called.
121 final Document document = getTextComponent().getDocument();
122 document.removeDocumentListener(this);
123 getTextComponent().setText(l);
124 revalidate();
125 if (firstChangeSkipped) {
126 postEvent(new TextEvent(getTarget(),
127 TextEvent.TEXT_VALUE_CHANGED));
128 }
129 document.addDocumentListener(this);
130 }
131 repaintPeer();
132 }
133
134 @Override
135 public final int getSelectionStart() {
136 synchronized (getDelegateLock()) {
137 return getTextComponent().getSelectionStart();
138 }
139 }
140
141 @Override
142 public final int getSelectionEnd() {
143 synchronized (getDelegateLock()) {
144 return getTextComponent().getSelectionEnd();
145 }
146 }
147
148 @Override
149 public final void select(final int selStart, final int selEnd) {
150 synchronized (getDelegateLock()) {
151 getTextComponent().select(selStart, selEnd);
152 }
153 repaintPeer();
154 }
155
156 @Override
157 public final void setCaretPosition(final int pos) {
158 synchronized (getDelegateLock()) {
159 getTextComponent().setCaretPosition(pos);
160 }
161 repaintPeer();
162 }
163
164 @Override
165 public final int getCaretPosition() {
166 synchronized (getDelegateLock()) {
167 return getTextComponent().getCaretPosition();
168 }
169 }
170
171 @Override
172 public final InputMethodRequests getInputMethodRequests() {
173 synchronized (getDelegateLock()) {
174 return getTextComponent().getInputMethodRequests();
175 }
176 }
177
178 @Override
179 public final boolean isFocusable() {
180 return getTarget().isFocusable();
181 }
182
183 protected final void revalidate() {
184 synchronized (getDelegateLock()) {
185 getTextComponent().invalidate();
186 getDelegate().validate();
187 }
188 }
189
190 private void sendTextEvent(final DocumentEvent e) {
191 postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED));
192 synchronized (getDelegateLock()) {
193 revalidate();
194 }
195 }
196
197 @Override
198 public final void changedUpdate(final DocumentEvent e) {
199 sendTextEvent(e);
200 }
201
202 @Override
203 public final void insertUpdate(final DocumentEvent e) {
204 sendTextEvent(e);
205 }
206
207 @Override
208 public final void removeUpdate(final DocumentEvent e) {
209 sendTextEvent(e);
210 }
211
212 @Override
213 public void inputMethodTextChanged(InputMethodEvent event) {
214 synchronized (getDelegateLock()) {
215 AWTAccessor.getComponentAccessor().processEvent(getTextComponent(), event);
216 }
217 }
218
219 @Override
220 public void caretPositionChanged(InputMethodEvent event) {
221 synchronized (getDelegateLock()) {
222 AWTAccessor.getComponentAccessor().processEvent(getTextComponent(), event);
223 }
224 }
225 }
--- EOF ---