89 * Marks the last integer id for the range of input method event ids.
90 */
91 @Native public static final int INPUT_METHOD_LAST = INPUT_METHOD_FIRST + 1;
92
93 /**
94 * The time stamp that indicates when the event was created.
95 *
96 * @serial
97 * @see #getWhen
98 * @since 1.4
99 */
100 long when;
101
102 // Text object
103 private transient AttributedCharacterIterator text;
104 private transient int committedCharacterCount;
105 private transient TextHitInfo caret;
106 private transient TextHitInfo visiblePosition;
107
108 /**
109 * Constructs an <code>InputMethodEvent</code> with the specified
110 * source component, type, time, text, caret, and visiblePosition.
111 * <p>
112 * The offsets of caret and visiblePosition are relative to the current
113 * composed text; that is, the composed text within <code>text</code>
114 * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
115 * the composed text within the <code>text</code> of the
116 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
117 * <p>Note that passing in an invalid <code>id</code> results in
118 * unspecified behavior. This method throws an
119 * <code>IllegalArgumentException</code> if <code>source</code>
120 * is <code>null</code>.
121 *
122 * @param source the object where the event originated
123 * @param id the event type
124 * @param when a long integer that specifies the time the event occurred
125 * @param text the combined committed and composed text,
126 * committed text first; must be <code>null</code>
127 * when the event type is <code>CARET_POSITION_CHANGED</code>;
128 * may be <code>null</code> for
129 * <code>INPUT_METHOD_TEXT_CHANGED</code> if there's no
130 * committed or composed text
131 * @param committedCharacterCount the number of committed
132 * characters in the text
133 * @param caret the caret (a.k.a. insertion point);
134 * <code>null</code> if there's no caret within current
135 * composed text
136 * @param visiblePosition the position that's most important
137 * to be visible; <code>null</code> if there's no
138 * recommendation for a visible position within current
139 * composed text
140 * @throws IllegalArgumentException if <code>id</code> is not
141 * in the range
142 * <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>;
143 * or if id is <code>CARET_POSITION_CHANGED</code> and
144 * <code>text</code> is not <code>null</code>;
145 * or if <code>committedCharacterCount</code> is not in the range
146 * <code>0</code>..<code>(text.getEndIndex() - text.getBeginIndex())</code>
147 * @throws IllegalArgumentException if <code>source</code> is null
148 *
149 * @since 1.4
150 */
151 public InputMethodEvent(Component source, int id, long when,
152 AttributedCharacterIterator text, int committedCharacterCount,
153 TextHitInfo caret, TextHitInfo visiblePosition) {
154 super(source, id);
155 if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST) {
156 throw new IllegalArgumentException("id outside of valid range");
157 }
158
159 if (id == CARET_POSITION_CHANGED && text != null) {
160 throw new IllegalArgumentException("text must be null for CARET_POSITION_CHANGED");
161 }
162
163 this.when = when;
164 this.text = text;
165 int textLength = 0;
166 if (text != null) {
167 textLength = text.getEndIndex() - text.getBeginIndex();
168 }
169
170 if (committedCharacterCount < 0 || committedCharacterCount > textLength) {
171 throw new IllegalArgumentException("committedCharacterCount outside of valid range");
172 }
173 this.committedCharacterCount = committedCharacterCount;
174
175 this.caret = caret;
176 this.visiblePosition = visiblePosition;
177 }
178
179 /**
180 * Constructs an <code>InputMethodEvent</code> with the specified
181 * source component, type, text, caret, and visiblePosition.
182 * <p>
183 * The offsets of caret and visiblePosition are relative to the current
184 * composed text; that is, the composed text within <code>text</code>
185 * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
186 * the composed text within the <code>text</code> of the
187 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
188 * The time stamp for this event is initialized by invoking
189 * {@link java.awt.EventQueue#getMostRecentEventTime()}.
190 * <p>Note that passing in an invalid <code>id</code> results in
191 * unspecified behavior. This method throws an
192 * <code>IllegalArgumentException</code> if <code>source</code>
193 * is <code>null</code>.
194 *
195 * @param source the object where the event originated
196 * @param id the event type
197 * @param text the combined committed and composed text,
198 * committed text first; must be <code>null</code>
199 * when the event type is <code>CARET_POSITION_CHANGED</code>;
200 * may be <code>null</code> for
201 * <code>INPUT_METHOD_TEXT_CHANGED</code> if there's no
202 * committed or composed text
203 * @param committedCharacterCount the number of committed
204 * characters in the text
205 * @param caret the caret (a.k.a. insertion point);
206 * <code>null</code> if there's no caret within current
207 * composed text
208 * @param visiblePosition the position that's most important
209 * to be visible; <code>null</code> if there's no
210 * recommendation for a visible position within current
211 * composed text
212 * @throws IllegalArgumentException if <code>id</code> is not
213 * in the range
214 * <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>;
215 * or if id is <code>CARET_POSITION_CHANGED</code> and
216 * <code>text</code> is not <code>null</code>;
217 * or if <code>committedCharacterCount</code> is not in the range
218 * <code>0</code>..<code>(text.getEndIndex() - text.getBeginIndex())</code>
219 * @throws IllegalArgumentException if <code>source</code> is null
220 */
221 public InputMethodEvent(Component source, int id,
222 AttributedCharacterIterator text, int committedCharacterCount,
223 TextHitInfo caret, TextHitInfo visiblePosition) {
224 this(source, id,
225 getMostRecentEventTimeForSource(source),
226 text, committedCharacterCount,
227 caret, visiblePosition);
228 }
229
230 /**
231 * Constructs an <code>InputMethodEvent</code> with the
232 * specified source component, type, caret, and visiblePosition.
233 * The text is set to <code>null</code>,
234 * <code>committedCharacterCount</code> to 0.
235 * <p>
236 * The offsets of <code>caret</code> and <code>visiblePosition</code>
237 * are relative to the current composed text; that is,
238 * the composed text within the <code>text</code> of the
239 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event if the
240 * event being constructed as a <code>CARET_POSITION_CHANGED</code> event.
241 * For an <code>INPUT_METHOD_TEXT_CHANGED</code> event without text,
242 * <code>caret</code> and <code>visiblePosition</code> must be
243 * <code>null</code>.
244 * The time stamp for this event is initialized by invoking
245 * {@link java.awt.EventQueue#getMostRecentEventTime()}.
246 * <p>Note that passing in an invalid <code>id</code> results in
247 * unspecified behavior. This method throws an
248 * <code>IllegalArgumentException</code> if <code>source</code>
249 * is <code>null</code>.
250 *
251 * @param source the object where the event originated
252 * @param id the event type
253 * @param caret the caret (a.k.a. insertion point);
254 * <code>null</code> if there's no caret within current
255 * composed text
256 * @param visiblePosition the position that's most important
257 * to be visible; <code>null</code> if there's no
258 * recommendation for a visible position within current
259 * composed text
260 * @throws IllegalArgumentException if <code>id</code> is not
261 * in the range
262 * <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>
263 * @throws IllegalArgumentException if <code>source</code> is null
264 */
265 public InputMethodEvent(Component source, int id, TextHitInfo caret,
266 TextHitInfo visiblePosition) {
267 this(source, id,
268 getMostRecentEventTimeForSource(source),
269 null, 0, caret, visiblePosition);
270 }
271
272 /**
273 * Gets the combined committed and composed text.
274 * Characters from index 0 to index <code>getCommittedCharacterCount() - 1</code> are committed
275 * text, the remaining characters are composed text.
276 *
277 * @return the text.
278 * Always null for CARET_POSITION_CHANGED;
279 * may be null for INPUT_METHOD_TEXT_CHANGED if there's no composed or committed text.
280 */
281 public AttributedCharacterIterator getText() {
282 return text;
283 }
284
285 /**
286 * Gets the number of committed characters in the text.
287 * @return the number of committed characters in the text
288 */
289 public int getCommittedCharacterCount() {
290 return committedCharacterCount;
291 }
292
293 /**
294 * Gets the caret.
295 * <p>
296 * The offset of the caret is relative to the current
297 * composed text; that is, the composed text within getText()
298 * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
299 * the composed text within getText() of the
300 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
301 *
302 * @return the caret (a.k.a. insertion point).
303 * Null if there's no caret within current composed text.
304 */
305 public TextHitInfo getCaret() {
306 return caret;
307 }
308
309 /**
310 * Gets the position that's most important to be visible.
311 * <p>
312 * The offset of the visible position is relative to the current
313 * composed text; that is, the composed text within getText()
314 * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
315 * the composed text within getText() of the
316 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
317 *
318 * @return the position that's most important to be visible.
319 * Null if there's no recommendation for a visible position within current composed text.
320 */
321 public TextHitInfo getVisiblePosition() {
322 return visiblePosition;
323 }
324
325 /**
326 * Consumes this event so that it will not be processed
327 * in the default manner by the source which originated it.
328 */
329 public void consume() {
330 consumed = true;
331 }
332
333 /**
334 * Returns whether or not this event has been consumed.
335 * @see #consume
336 */
394 String countString = committedCharacterCount + " characters committed";
395
396 String caretString;
397 if (caret == null) {
398 caretString = "no caret";
399 } else {
400 caretString = "caret: " + caret.toString();
401 }
402
403 String visiblePositionString;
404 if (visiblePosition == null) {
405 visiblePositionString = "no visible position";
406 } else {
407 visiblePositionString = "visible position: " + visiblePosition.toString();
408 }
409
410 return typeStr + ", " + textString + ", " + countString + ", " + caretString + ", " + visiblePositionString;
411 }
412
413 /**
414 * Initializes the <code>when</code> field if it is not present in the
415 * object input stream. In that case, the field will be initialized by
416 * invoking {@link java.awt.EventQueue#getMostRecentEventTime()}.
417 */
418 private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
419 s.defaultReadObject();
420 if (when == 0) {
421 // Can't use getMostRecentEventTimeForSource because source is always null during deserialization
422 when = EventQueue.getMostRecentEventTime();
423 }
424 }
425
426 /**
427 * Get the most recent event time in the {@code EventQueue} which the {@code source}
428 * belongs to.
429 *
430 * @param source the source of the event
431 * @exception IllegalArgumentException if source is null.
432 * @return most recent event time in the {@code EventQueue}
433 */
434 private static long getMostRecentEventTimeForSource(Object source) {
|
89 * Marks the last integer id for the range of input method event ids.
90 */
91 @Native public static final int INPUT_METHOD_LAST = INPUT_METHOD_FIRST + 1;
92
93 /**
94 * The time stamp that indicates when the event was created.
95 *
96 * @serial
97 * @see #getWhen
98 * @since 1.4
99 */
100 long when;
101
102 // Text object
103 private transient AttributedCharacterIterator text;
104 private transient int committedCharacterCount;
105 private transient TextHitInfo caret;
106 private transient TextHitInfo visiblePosition;
107
108 /**
109 * Constructs an {@code InputMethodEvent} with the specified
110 * source component, type, time, text, caret, and visiblePosition.
111 * <p>
112 * The offsets of caret and visiblePosition are relative to the current
113 * composed text; that is, the composed text within {@code text}
114 * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event,
115 * the composed text within the {@code text} of the
116 * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise.
117 * <p>Note that passing in an invalid {@code id} results in
118 * unspecified behavior. This method throws an
119 * {@code IllegalArgumentException} if {@code source}
120 * is {@code null}.
121 *
122 * @param source the object where the event originated
123 * @param id the event type
124 * @param when a long integer that specifies the time the event occurred
125 * @param text the combined committed and composed text,
126 * committed text first; must be {@code null}
127 * when the event type is {@code CARET_POSITION_CHANGED};
128 * may be {@code null} for
129 * {@code INPUT_METHOD_TEXT_CHANGED} if there's no
130 * committed or composed text
131 * @param committedCharacterCount the number of committed
132 * characters in the text
133 * @param caret the caret (a.k.a. insertion point);
134 * {@code null} if there's no caret within current
135 * composed text
136 * @param visiblePosition the position that's most important
137 * to be visible; {@code null} if there's no
138 * recommendation for a visible position within current
139 * composed text
140 * @throws IllegalArgumentException if {@code id} is not
141 * in the range
142 * {@code INPUT_METHOD_FIRST}..{@code INPUT_METHOD_LAST};
143 * or if id is {@code CARET_POSITION_CHANGED} and
144 * {@code text} is not {@code null};
145 * or if {@code committedCharacterCount} is not in the range
146 * {@code 0}..{@code (text.getEndIndex() - text.getBeginIndex())}
147 * @throws IllegalArgumentException if {@code source} is null
148 *
149 * @since 1.4
150 */
151 public InputMethodEvent(Component source, int id, long when,
152 AttributedCharacterIterator text, int committedCharacterCount,
153 TextHitInfo caret, TextHitInfo visiblePosition) {
154 super(source, id);
155 if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST) {
156 throw new IllegalArgumentException("id outside of valid range");
157 }
158
159 if (id == CARET_POSITION_CHANGED && text != null) {
160 throw new IllegalArgumentException("text must be null for CARET_POSITION_CHANGED");
161 }
162
163 this.when = when;
164 this.text = text;
165 int textLength = 0;
166 if (text != null) {
167 textLength = text.getEndIndex() - text.getBeginIndex();
168 }
169
170 if (committedCharacterCount < 0 || committedCharacterCount > textLength) {
171 throw new IllegalArgumentException("committedCharacterCount outside of valid range");
172 }
173 this.committedCharacterCount = committedCharacterCount;
174
175 this.caret = caret;
176 this.visiblePosition = visiblePosition;
177 }
178
179 /**
180 * Constructs an {@code InputMethodEvent} with the specified
181 * source component, type, text, caret, and visiblePosition.
182 * <p>
183 * The offsets of caret and visiblePosition are relative to the current
184 * composed text; that is, the composed text within {@code text}
185 * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event,
186 * the composed text within the {@code text} of the
187 * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise.
188 * The time stamp for this event is initialized by invoking
189 * {@link java.awt.EventQueue#getMostRecentEventTime()}.
190 * <p>Note that passing in an invalid {@code id} results in
191 * unspecified behavior. This method throws an
192 * {@code IllegalArgumentException} if {@code source}
193 * is {@code null}.
194 *
195 * @param source the object where the event originated
196 * @param id the event type
197 * @param text the combined committed and composed text,
198 * committed text first; must be {@code null}
199 * when the event type is {@code CARET_POSITION_CHANGED};
200 * may be {@code null} for
201 * {@code INPUT_METHOD_TEXT_CHANGED} if there's no
202 * committed or composed text
203 * @param committedCharacterCount the number of committed
204 * characters in the text
205 * @param caret the caret (a.k.a. insertion point);
206 * {@code null} if there's no caret within current
207 * composed text
208 * @param visiblePosition the position that's most important
209 * to be visible; {@code null} if there's no
210 * recommendation for a visible position within current
211 * composed text
212 * @throws IllegalArgumentException if {@code id} is not
213 * in the range
214 * {@code INPUT_METHOD_FIRST}..{@code INPUT_METHOD_LAST};
215 * or if id is {@code CARET_POSITION_CHANGED} and
216 * {@code text} is not {@code null};
217 * or if {@code committedCharacterCount} is not in the range
218 * {@code 0}..{@code (text.getEndIndex() - text.getBeginIndex())}
219 * @throws IllegalArgumentException if {@code source} is null
220 */
221 public InputMethodEvent(Component source, int id,
222 AttributedCharacterIterator text, int committedCharacterCount,
223 TextHitInfo caret, TextHitInfo visiblePosition) {
224 this(source, id,
225 getMostRecentEventTimeForSource(source),
226 text, committedCharacterCount,
227 caret, visiblePosition);
228 }
229
230 /**
231 * Constructs an {@code InputMethodEvent} with the
232 * specified source component, type, caret, and visiblePosition.
233 * The text is set to {@code null},
234 * {@code committedCharacterCount} to 0.
235 * <p>
236 * The offsets of {@code caret} and {@code visiblePosition}
237 * are relative to the current composed text; that is,
238 * the composed text within the {@code text} of the
239 * preceding {@code INPUT_METHOD_TEXT_CHANGED} event if the
240 * event being constructed as a {@code CARET_POSITION_CHANGED} event.
241 * For an {@code INPUT_METHOD_TEXT_CHANGED} event without text,
242 * {@code caret} and {@code visiblePosition} must be
243 * {@code null}.
244 * The time stamp for this event is initialized by invoking
245 * {@link java.awt.EventQueue#getMostRecentEventTime()}.
246 * <p>Note that passing in an invalid {@code id} results in
247 * unspecified behavior. This method throws an
248 * {@code IllegalArgumentException} if {@code source}
249 * is {@code null}.
250 *
251 * @param source the object where the event originated
252 * @param id the event type
253 * @param caret the caret (a.k.a. insertion point);
254 * {@code null} if there's no caret within current
255 * composed text
256 * @param visiblePosition the position that's most important
257 * to be visible; {@code null} if there's no
258 * recommendation for a visible position within current
259 * composed text
260 * @throws IllegalArgumentException if {@code id} is not
261 * in the range
262 * {@code INPUT_METHOD_FIRST}..{@code INPUT_METHOD_LAST}
263 * @throws IllegalArgumentException if {@code source} is null
264 */
265 public InputMethodEvent(Component source, int id, TextHitInfo caret,
266 TextHitInfo visiblePosition) {
267 this(source, id,
268 getMostRecentEventTimeForSource(source),
269 null, 0, caret, visiblePosition);
270 }
271
272 /**
273 * Gets the combined committed and composed text.
274 * Characters from index 0 to index {@code getCommittedCharacterCount() - 1} are committed
275 * text, the remaining characters are composed text.
276 *
277 * @return the text.
278 * Always null for CARET_POSITION_CHANGED;
279 * may be null for INPUT_METHOD_TEXT_CHANGED if there's no composed or committed text.
280 */
281 public AttributedCharacterIterator getText() {
282 return text;
283 }
284
285 /**
286 * Gets the number of committed characters in the text.
287 * @return the number of committed characters in the text
288 */
289 public int getCommittedCharacterCount() {
290 return committedCharacterCount;
291 }
292
293 /**
294 * Gets the caret.
295 * <p>
296 * The offset of the caret is relative to the current
297 * composed text; that is, the composed text within getText()
298 * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event,
299 * the composed text within getText() of the
300 * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise.
301 *
302 * @return the caret (a.k.a. insertion point).
303 * Null if there's no caret within current composed text.
304 */
305 public TextHitInfo getCaret() {
306 return caret;
307 }
308
309 /**
310 * Gets the position that's most important to be visible.
311 * <p>
312 * The offset of the visible position is relative to the current
313 * composed text; that is, the composed text within getText()
314 * if this is an {@code INPUT_METHOD_TEXT_CHANGED} event,
315 * the composed text within getText() of the
316 * preceding {@code INPUT_METHOD_TEXT_CHANGED} event otherwise.
317 *
318 * @return the position that's most important to be visible.
319 * Null if there's no recommendation for a visible position within current composed text.
320 */
321 public TextHitInfo getVisiblePosition() {
322 return visiblePosition;
323 }
324
325 /**
326 * Consumes this event so that it will not be processed
327 * in the default manner by the source which originated it.
328 */
329 public void consume() {
330 consumed = true;
331 }
332
333 /**
334 * Returns whether or not this event has been consumed.
335 * @see #consume
336 */
394 String countString = committedCharacterCount + " characters committed";
395
396 String caretString;
397 if (caret == null) {
398 caretString = "no caret";
399 } else {
400 caretString = "caret: " + caret.toString();
401 }
402
403 String visiblePositionString;
404 if (visiblePosition == null) {
405 visiblePositionString = "no visible position";
406 } else {
407 visiblePositionString = "visible position: " + visiblePosition.toString();
408 }
409
410 return typeStr + ", " + textString + ", " + countString + ", " + caretString + ", " + visiblePositionString;
411 }
412
413 /**
414 * Initializes the {@code when} field if it is not present in the
415 * object input stream. In that case, the field will be initialized by
416 * invoking {@link java.awt.EventQueue#getMostRecentEventTime()}.
417 */
418 private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
419 s.defaultReadObject();
420 if (when == 0) {
421 // Can't use getMostRecentEventTimeForSource because source is always null during deserialization
422 when = EventQueue.getMostRecentEventTime();
423 }
424 }
425
426 /**
427 * Get the most recent event time in the {@code EventQueue} which the {@code source}
428 * belongs to.
429 *
430 * @param source the source of the event
431 * @exception IllegalArgumentException if source is null.
432 * @return most recent event time in the {@code EventQueue}
433 */
434 private static long getMostRecentEventTimeForSource(Object source) {
|