87
88 /**
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>
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
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
332
333 /**
334 * Returns whether or not this event has been consumed.
335 * @see #consume
336 */
337 public boolean isConsumed() {
338 return consumed;
339 }
340
341 /**
342 * Returns the time stamp of when this event occurred.
343 *
344 * @return this event's timestamp
345 * @since 1.4
346 */
347 public long getWhen() {
348 return when;
349 }
350
351 /**
352 * Returns a parameter string identifying this event.
353 * This method is useful for event-logging and for debugging.
354 * It contains the event ID in text form, the characters of the
355 * committed and composed text
356 * separated by "+", the number of committed characters,
357 * the caret, and the visible position.
358 *
359 * @return a string identifying the event and its attributes
360 */
361 public String paramString() {
362 String typeStr;
363 switch(id) {
364 case INPUT_METHOD_TEXT_CHANGED:
365 typeStr = "INPUT_METHOD_TEXT_CHANGED";
366 break;
367 case CARET_POSITION_CHANGED:
368 typeStr = "CARET_POSITION_CHANGED";
369 break;
370 default:
371 typeStr = "unknown type";
390 textBuffer.append("\"");
391 textString = textBuffer.toString();
392 }
393
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
|
87
88 /**
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 private transient int replaceStart;
108 private transient int replaceEnd;
109
110
111 /**
112 * Constructs an <code>InputMethodEvent</code> with the specified
113 * source component, type, time, text, caret, and visiblePosition.
114 * <p>
115 * The offsets of caret and visiblePosition are relative to the current
116 * composed text; that is, the composed text within <code>text</code>
117 * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
118 * the composed text within the <code>text</code> of the
119 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
120 * <p>Note that passing in an invalid <code>id</code> results in
121 * unspecified behavior. This method throws an
122 * <code>IllegalArgumentException</code> if <code>source</code>
123 * is <code>null</code>.
124 *
125 * @param source the object where the event originated
126 * @param id the event type
127 * @param when a long integer that specifies the time the event occurred
128 * @param text the combined committed and composed text,
129 * committed text first; must be <code>null</code>
137 * <code>null</code> if there's no caret within current
138 * composed text
139 * @param visiblePosition the position that's most important
140 * to be visible; <code>null</code> if there's no
141 * recommendation for a visible position within current
142 * composed text
143 * @throws IllegalArgumentException if <code>id</code> is not
144 * in the range
145 * <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>;
146 * or if id is <code>CARET_POSITION_CHANGED</code> and
147 * <code>text</code> is not <code>null</code>;
148 * or if <code>committedCharacterCount</code> is not in the range
149 * <code>0</code>..<code>(text.getEndIndex() - text.getBeginIndex())</code>
150 * @throws IllegalArgumentException if <code>source</code> is null
151 *
152 * @since 1.4
153 */
154 public InputMethodEvent(Component source, int id, long when,
155 AttributedCharacterIterator text, int committedCharacterCount,
156 TextHitInfo caret, TextHitInfo visiblePosition) {
157
158 this(source, id, when, text, committedCharacterCount,
159 caret, visiblePosition, -1, -1);
160 }
161
162 private InputMethodEvent(Component source, int id, long when,
163 AttributedCharacterIterator text, int committedCharacterCount,
164 TextHitInfo caret, TextHitInfo visiblePosition,
165 int replaceStart, int replaceEnd) {
166
167 super(source, id);
168 if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST) {
169 throw new IllegalArgumentException("id outside of valid range");
170 }
171
172 if (id == CARET_POSITION_CHANGED && text != null) {
173 throw new IllegalArgumentException("text must be null for CARET_POSITION_CHANGED");
174 }
175
176 this.when = when;
177 this.text = text;
178 int textLength = 0;
179 if (text != null) {
180 textLength = text.getEndIndex() - text.getBeginIndex();
181 }
182
183 if (committedCharacterCount < 0 || committedCharacterCount > textLength) {
184 throw new IllegalArgumentException("committedCharacterCount outside of valid range");
185 }
186 this.committedCharacterCount = committedCharacterCount;
187
188 this.caret = caret;
189 this.visiblePosition = visiblePosition;
190 this.replaceStart = replaceStart;
191 this.replaceEnd = replaceEnd;
192 }
193
194 /**
195 * Constructs an <code>InputMethodEvent</code> with the specified
196 * source component, type, text, caret, and visiblePosition.
197 * <p>
198 * The offsets of caret and visiblePosition are relative to the current
199 * composed text; that is, the composed text within <code>text</code>
200 * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
201 * the composed text within the <code>text</code> of the
202 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
203 * The time stamp for this event is initialized by invoking
204 * {@link java.awt.EventQueue#getMostRecentEventTime()}.
205 * <p>Note that passing in an invalid <code>id</code> results in
206 * unspecified behavior. This method throws an
207 * <code>IllegalArgumentException</code> if <code>source</code>
208 * is <code>null</code>.
209 *
210 * @param source the object where the event originated
211 * @param id the event type
268 * @param caret the caret (a.k.a. insertion point);
269 * <code>null</code> if there's no caret within current
270 * composed text
271 * @param visiblePosition the position that's most important
272 * to be visible; <code>null</code> if there's no
273 * recommendation for a visible position within current
274 * composed text
275 * @throws IllegalArgumentException if <code>id</code> is not
276 * in the range
277 * <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>
278 * @throws IllegalArgumentException if <code>source</code> is null
279 */
280 public InputMethodEvent(Component source, int id, TextHitInfo caret,
281 TextHitInfo visiblePosition) {
282 this(source, id,
283 getMostRecentEventTimeForSource(source),
284 null, 0, caret, visiblePosition);
285 }
286
287 /**
288 * Constructs an <code>InputMethodEvent</code> with the
289 * specified source component, type, caret, and visiblePosition.
290 * The text is set to <code>null</code>,
291 * <code>committedCharacterCount</code> to 0.
292 * <p>
293 * The offsets of <code>caret</code> and <code>visiblePosition</code>
294 * are relative to the current composed text; that is,
295 * the composed text within the <code>text</code> of the
296 * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event if the
297 * event being constructed as a <code>CARET_POSITION_CHANGED</code> event.
298 * For an <code>INPUT_METHOD_TEXT_CHANGED</code> event without text,
299 * <code>caret</code> and <code>visiblePosition</code> must be
300 * <code>null</code>.
301 * The time stamp for this event is initialized by invoking
302 * {@link java.awt.EventQueue#getMostRecentEventTime()}.
303 * <p>Note that passing in an invalid <code>id</code> results in
304 * unspecified behavior. This method throws an
305 * <code>IllegalArgumentException</code> if <code>source</code>
306 * is <code>null</code>.
307 *
308 * @param source the object where the event originated
309 * @param id the event type
310 * @param caret the caret (a.k.a. insertion point);
311 * <code>null</code> if there's no caret within current
312 * composed text
313 * @param visiblePosition the position that's most important
314 * to be visible; <code>null</code> if there's no
315 * recommendation for a visible position within current
316 * composed text
317 * @param replaceStart start of the text range in the text document
318 * which this IM event content should replace.
319 * -1 if no content should be replaced
320 * @param replaceEnd end of the text range in the text document
321 * which this IM event content should replace.
322 * -1 if no content should be replaced
323 * @throws IllegalArgumentException if <code>id</code> is not
324 * in the range
325 * <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>
326 * @throws IllegalArgumentException if <code>source</code> is null
327 */
328 public InputMethodEvent(Component source, int id, AttributedCharacterIterator text,
329 int committedCharacterCount, TextHitInfo caret, TextHitInfo visiblePosition,
330 int replaceStart, int replaceEnd) {
331
332 this(source, id, getMostRecentEventTimeForSource(source), text,
333 committedCharacterCount, caret, visiblePosition,
334 replaceStart, replaceEnd);
335 }
336
337
338 /**
339 * Gets the combined committed and composed text.
340 * Characters from index 0 to index <code>getCommittedCharacterCount() - 1</code> are committed
341 * text, the remaining characters are composed text.
342 *
343 * @return the text.
344 * Always null for CARET_POSITION_CHANGED;
345 * may be null for INPUT_METHOD_TEXT_CHANGED if there's no composed or committed text.
346 */
347 public AttributedCharacterIterator getText() {
348 return text;
349 }
350
351 /**
352 * Gets the number of committed characters in the text.
353 * @return the number of committed characters in the text
354 */
355 public int getCommittedCharacterCount() {
356 return committedCharacterCount;
357 }
358
398
399 /**
400 * Returns whether or not this event has been consumed.
401 * @see #consume
402 */
403 public boolean isConsumed() {
404 return consumed;
405 }
406
407 /**
408 * Returns the time stamp of when this event occurred.
409 *
410 * @return this event's timestamp
411 * @since 1.4
412 */
413 public long getWhen() {
414 return when;
415 }
416
417 /**
418 * Returns start of the text range in the text document
419 * which this IM event content should replace.
420 * @return -1 if no content should be replaced
421 */
422 public int getReplaceStart() {
423 return replaceStart;
424 }
425
426 /**
427 * Returns end of the text range in the text document
428 * which this IM event content should replace.
429 * @return -1 if no content should be replaced
430 */
431 public int getReplaceEnd() {
432 return replaceEnd;
433 }
434
435 /**
436 * Returns a parameter string identifying this event.
437 * This method is useful for event-logging and for debugging.
438 * It contains the event ID in text form, the characters of the
439 * committed and composed text
440 * separated by "+", the number of committed characters,
441 * the caret, and the visible position.
442 *
443 * @return a string identifying the event and its attributes
444 */
445 public String paramString() {
446 String typeStr;
447 switch(id) {
448 case INPUT_METHOD_TEXT_CHANGED:
449 typeStr = "INPUT_METHOD_TEXT_CHANGED";
450 break;
451 case CARET_POSITION_CHANGED:
452 typeStr = "CARET_POSITION_CHANGED";
453 break;
454 default:
455 typeStr = "unknown type";
474 textBuffer.append("\"");
475 textString = textBuffer.toString();
476 }
477
478 String countString = committedCharacterCount + " characters committed";
479
480 String caretString;
481 if (caret == null) {
482 caretString = "no caret";
483 } else {
484 caretString = "caret: " + caret.toString();
485 }
486
487 String visiblePositionString;
488 if (visiblePosition == null) {
489 visiblePositionString = "no visible position";
490 } else {
491 visiblePositionString = "visible position: " + visiblePosition.toString();
492 }
493
494 String replacementRangeString = "";
495 if (replaceStart >= 0) {
496 replacementRangeString = ", replacement range (" + replaceStart +
497 ", " + replaceEnd + ")";
498 }
499
500 return typeStr + ", " + textString + ", " + countString + ", "
501 + caretString + ", " + visiblePositionString + replacementRangeString;
502 }
503
504 /**
505 * Initializes the <code>when</code> field if it is not present in the
506 * object input stream. In that case, the field will be initialized by
507 * invoking {@link java.awt.EventQueue#getMostRecentEventTime()}.
508 */
509 private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
510 s.defaultReadObject();
511 if (when == 0) {
512 // Can't use getMostRecentEventTimeForSource because source is always null during deserialization
513 when = EventQueue.getMostRecentEventTime();
514 }
515 }
516
517 /**
518 * Get the most recent event time in the {@code EventQueue} which the {@code source}
519 * belongs to.
520 *
521 * @param source the source of the event
|