1. /*
  2. * @(#)InputMethodEvent.java 1.16 00/02/02
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.awt.event;
  11. import java.awt.AWTEvent;
  12. import java.awt.Component;
  13. import java.lang.Integer;
  14. import java.awt.font.TextHitInfo;
  15. import java.text.AttributedCharacterIterator;
  16. import java.text.CharacterIterator;
  17. /**
  18. * Input method events contain information about text that is being
  19. * composed using an input method. Whenever the text changes, the
  20. * input method sends an event. If the text component that's currently
  21. * using the input method is an active client, the event is dispatched
  22. * to that component. Otherwise, it is dispatched to a separate
  23. * composition window.
  24. *
  25. * <p>
  26. * The text included with the input method event consists of two parts:
  27. * committed text and composed text. Either part may be empty. The two
  28. * parts together replace any uncommitted composed text sent in previous events,
  29. * or the currently selected committed text.
  30. * Committed text should be integrated into the text component's persistent
  31. * data, it will not be sent again. Composed text may be sent repeatedly,
  32. * with changes to reflect the user's editing operations. Committed text
  33. * always precedes composed text.
  34. *
  35. * @author JavaSoft Asia/Pacific
  36. * @version 1.16 02/02/00
  37. * @since 1.2
  38. */
  39. public class InputMethodEvent extends AWTEvent {
  40. /**
  41. * Marks the first integer id for the range of input method event ids.
  42. */
  43. public static final int INPUT_METHOD_FIRST = 1100;
  44. /**
  45. * The event type indicating changed input method text. This event is
  46. * generated by input methods while processing input.
  47. */
  48. public static final int INPUT_METHOD_TEXT_CHANGED = INPUT_METHOD_FIRST;
  49. /**
  50. * The event type indicating a changed insertion point in input method text.
  51. * This event is
  52. * generated by input methods while processing input if only the caret changed.
  53. */
  54. public static final int CARET_POSITION_CHANGED = INPUT_METHOD_FIRST + 1;
  55. /**
  56. * Marks the last integer id for the range of input method event ids.
  57. */
  58. public static final int INPUT_METHOD_LAST = INPUT_METHOD_FIRST + 1;
  59. // Text object
  60. private transient AttributedCharacterIterator text;
  61. private transient int committedCharacterCount;
  62. private transient TextHitInfo caret;
  63. private transient TextHitInfo visiblePosition;
  64. /**
  65. * Constructs an InputMethodEvent with the specified source component, type,
  66. * text, caret, and visiblePosition.
  67. * <p>
  68. * The offsets of caret and visiblePosition are relative to the current
  69. * composed text; that is, the composed text within <code>text</code>
  70. * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
  71. * the composed text within the <code>text</code> of the
  72. * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
  73. *
  74. * @param source The object where the event originated.
  75. * @param id The event type.
  76. * @param text The combined committed and composed text, committed text first.
  77. * Must be <code>null</code> when the event type is
  78. * <code>CARET_POSITION_CHANGED</code>
  79. * may be null for <code>INPUT_METHOD_TEXT_CHANGED</code> if there's no committed or composed text.
  80. * @param committedCharacterCount The number of committed characters in the text.
  81. * @param caret the caret (a.k.a. insertion point).
  82. * Null if there's no caret within current composed text.
  83. * @param visiblePosition The position that's most important to be visible.
  84. * Null if there's no recommendation for a visible position within current composed text.
  85. * @exception IllegalArgumentException
  86. * if <code>id</code> is not in the range <code>INPUT_METHOD_FIRST</code>..<code>INPUT_METHOD_LAST</code>,
  87. * if id is <code>CARET_POSITION_CHANGED</code> and <code>text</code> is not null,
  88. * or if <code>committedCharacterCount</code> is not in the range <code>0</code>..<code>(text.getEndIndex() - text.getBeginIndex())</code>
  89. */
  90. public InputMethodEvent(Component source, int id,
  91. AttributedCharacterIterator text, int committedCharacterCount,
  92. TextHitInfo caret, TextHitInfo visiblePosition) {
  93. super(source, id);
  94. if (id < INPUT_METHOD_FIRST || id > INPUT_METHOD_LAST) {
  95. throw new IllegalArgumentException("id outside of valid range");
  96. }
  97. if (id == CARET_POSITION_CHANGED && text != null) {
  98. throw new IllegalArgumentException("text must be null for CARET_POSITION_CHANGED");
  99. }
  100. this.text = text;
  101. int textLength = 0;
  102. if (text != null) {
  103. textLength = text.getEndIndex() - text.getBeginIndex();
  104. }
  105. if (committedCharacterCount < 0 || committedCharacterCount > textLength) {
  106. throw new IllegalArgumentException("committedCharacterCount outside of valid range");
  107. }
  108. this.committedCharacterCount = committedCharacterCount;
  109. this.caret = caret;
  110. this.visiblePosition = visiblePosition;
  111. }
  112. /**
  113. * Constructs an InputMethodEvent with the specified source component, type,
  114. * caret, and visiblePosition. The text is set to null, committedCharacterCount to 0.
  115. * <p>
  116. * The offsets of caret and visiblePosition are relative to the current
  117. * composed text; that is,
  118. * the composed text within the <code>text</code> of the
  119. * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event
  120. * if the event being constructed as a <code>CARET_POSITION_CHANGED</code> event.
  121. * For an <code>INPUT_METHOD_TEXT_CHANGED</code> event without text, caret
  122. * and visiblePosition must be null.
  123. *
  124. * @param source The object where the event originated.
  125. * @param id The event type.
  126. * @param caret the caret (a.k.a. insertion point).
  127. * Null if there's no caret within current composed text.
  128. * @param visiblePosition The position that's most important to be visible.
  129. * Null if there's no recommendation for a visible position within current composed text.
  130. */
  131. public InputMethodEvent(Component source, int id, TextHitInfo caret,
  132. TextHitInfo visiblePosition) {
  133. this(source, id, null, 0, caret, visiblePosition);
  134. }
  135. /**
  136. * Gets the combined committed and composed text.
  137. * Characters from index 0 to index <code>getCommittedCharacterCount() - 1</code> are committed
  138. * text, the remaining characters are composed text.
  139. *
  140. * @return the text.
  141. * Always null for CARET_POSITION_CHANGED;
  142. * may be null for INPUT_METHOD_TEXT_CHANGED if there's no composed or committed text.
  143. */
  144. public AttributedCharacterIterator getText() {
  145. return text;
  146. }
  147. /**
  148. * Gets the number of committed characters in the text.
  149. */
  150. public int getCommittedCharacterCount() {
  151. return committedCharacterCount;
  152. }
  153. /**
  154. * Gets the caret.
  155. * <p>
  156. * The offset of the caret is relative to the current
  157. * composed text; that is, the composed text within getText()
  158. * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
  159. * the composed text within getText() of the
  160. * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
  161. *
  162. * @return the caret (a.k.a. insertion point).
  163. * Null if there's no caret within current composed text.
  164. */
  165. public TextHitInfo getCaret() {
  166. return caret;
  167. }
  168. /**
  169. * Gets the position that's most important to be visible.
  170. * <p>
  171. * The offset of the visible position is relative to the current
  172. * composed text; that is, the composed text within getText()
  173. * if this is an <code>INPUT_METHOD_TEXT_CHANGED</code> event,
  174. * the composed text within getText() of the
  175. * preceding <code>INPUT_METHOD_TEXT_CHANGED</code> event otherwise.
  176. *
  177. * @return the position that's most important to be visible.
  178. * Null if there's no recommendation for a visible position within current composed text.
  179. */
  180. public TextHitInfo getVisiblePosition() {
  181. return visiblePosition;
  182. }
  183. /**
  184. * Consumes this event so that it will not be processed
  185. * in the default manner by the source which originated it.
  186. */
  187. public void consume() {
  188. consumed = true;
  189. }
  190. /**
  191. * Returns whether or not this event has been consumed.
  192. * @see #consume
  193. */
  194. public boolean isConsumed() {
  195. return consumed;
  196. }
  197. /**
  198. * Returns a parameter string identifying this event.
  199. * This method is useful for event-logging and for debugging.
  200. * It contains the event ID in text form, the characters of the
  201. * committed and composed text
  202. * separated by "+", the number of committed characters,
  203. * the caret, and the visible position.
  204. *
  205. * @return a string identifying the event and its attributes
  206. */
  207. public String paramString() {
  208. String typeStr;
  209. switch(id) {
  210. case INPUT_METHOD_TEXT_CHANGED:
  211. typeStr = "INPUT_METHOD_TEXT_CHANGED";
  212. break;
  213. case CARET_POSITION_CHANGED:
  214. typeStr = "CARET_POSITION_CHANGED";
  215. break;
  216. default:
  217. typeStr = "unknown type";
  218. }
  219. String textString;
  220. if (text == null) {
  221. textString = "no text";
  222. } else {
  223. StringBuffer textBuffer = new StringBuffer("\"");
  224. int committedCharacterCount = this.committedCharacterCount;
  225. char c = text.first();
  226. while (committedCharacterCount-- > 0) {
  227. textBuffer.append(c);
  228. c = text.next();
  229. }
  230. textBuffer.append("\" + \"");
  231. while (c != CharacterIterator.DONE) {
  232. textBuffer.append(c);
  233. c = text.next();
  234. }
  235. textBuffer.append("\"");
  236. textString = textBuffer.toString();
  237. }
  238. String countString = committedCharacterCount + " characters committed";
  239. String caretString;
  240. if (caret == null) {
  241. caretString = "no caret";
  242. } else {
  243. caretString = "caret: " + caret.toString();
  244. }
  245. String visiblePositionString;
  246. if (visiblePosition == null) {
  247. visiblePositionString = "no visible position";
  248. } else {
  249. visiblePositionString = "visible position: " + visiblePosition.toString();
  250. }
  251. return typeStr + ", " + textString + ", " + countString + ", " + caretString + ", " + visiblePositionString;
  252. }
  253. }