2 *******************************************************************************
\r
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.dev.demo.translit;
\r
9 import java.awt.event.KeyEvent;
\r
11 import com.ibm.icu.dev.demo.impl.DumbTextComponent;
\r
12 import com.ibm.icu.text.ReplaceableString;
\r
13 import com.ibm.icu.text.Transliterator;
\r
16 * A subclass of {@link DumbTextComponent} that passes key events through
\r
17 * a {@link com.ibm.icu.text.Transliterator}.
\r
21 public class TransliteratingTextComponent extends DumbTextComponent {
\r
26 private static final long serialVersionUID = -8672128213174154047L;
\r
28 private static boolean DEBUG = false;
\r
30 private Transliterator translit = null;
\r
32 // NOTE: DISABLE THE START AND CURSOR UNTIL WE CAN GET IT TO WORK AT ALL
\r
34 // Index into getText() where the start of transliteration is.
\r
35 // As we commit text during transliteration, we advance
\r
37 //private int start = 0;
\r
39 // Index into getText() where the cursor is; cursor >= start
\r
40 //private int cursor = 0;
\r
42 // private static final String COPYRIGHT =
\r
43 // "\u00A9 IBM Corporation 1999. All rights reserved.";
\r
48 public TransliteratingTextComponent() {
\r
51 addActionListener(new ActionListener() {
\r
52 public void actionPerformed(ActionEvent e) {
\r
53 // We get an ActionEvent only when the selection changes
\r
54 resetTransliterationStart();
\r
61 * {@link DumbTextComponent} API. Framework method that is called
\r
62 * when a <code>KeyEvent</code> is received. This implementation
\r
63 * runs the new character through the current
\r
64 * <code>Transliterator</code>, if one is set, and inserts the
\r
65 * transliterated text into the buffer.
\r
67 protected void handleKeyTyped(KeyEvent e) {
\r
68 char ch = e.getKeyChar();
\r
70 if (translit == null) {
\r
72 super.handleKeyTyped(e);
\r
76 transliterate(ch, false);
\r
79 public void flush() {
\r
80 if (translit != null) transliterate('\uFFFF', true);
\r
84 protected void transliterate(char ch, boolean flush) {
\r
86 // ------------------------------------------------------------
\r
87 // The following case motivates the two lines that recompute
\r
88 // start and cursor below.
\r
91 // a b c q r|s t u m m
\r
92 // 0 1 2 3 4 5 6 7 8 9
\r
95 // start 3, cursor 5, sel 6 -> { 0, 3, 2 }
\r
96 // : new int[] { 0, sel - start, cursor - start };
\r
101 // a b c q r 9 9|9 t u m m
\r
102 // 0 1 2 3 4 5 6 7 8 9 a b
\r
105 // { 3, 5, 4 } -> start 6, cursor 7, sel 8
\r
106 // : start += index[0];
\r
107 // : cursor = start + index[2] - index[0];
\r
108 // ------------------------------------------------------------
\r
110 // Need to save start because calls to replaceRange will update
\r
111 // start and cursor.
\r
112 //int saveStart = start;
\r
114 int end = flush ? getSelectionEnd() : getSelectionStart();
\r
115 String sourceText = getText().substring(0,end);
\r
116 ReplaceableString buf = new ReplaceableString(sourceText);
\r
117 /*buf.replace(0, 1, getText().substring(start,
\r
118 getSelectionStart()));*/
\r
120 Transliterator.Position index = new Transliterator.Position();
\r
121 index.contextLimit = buf.length();
\r
122 index.contextStart = 0;
\r
123 index.start = getKeyStart();
\r
124 if (index.start == -1) index.start = getSelectionStart();
\r
125 index.limit = buf.length();
\r
127 // StringBuffer log = null;
\r
129 System.out.println("Transliterator: " + translit.getID());
\r
130 System.out.println("From:\t" + '"' + buf.toString() + '"'
\r
131 + "; {cs: " + index.contextStart
\r
132 + ", s: " + index.start
\r
133 + ", l: " + index.limit
\r
134 + ", cl: " + index.contextLimit
\r
135 + "}" + "; '" + ch + "'"
\r
136 + " " + getKeyStart()
\r
141 translit.finishTransliteration(buf, index);
\r
143 translit.transliterate(buf, index, ch);
\r
147 System.out.println("To:\t" + '"' + buf.toString() + '"'
\r
148 + "; {cs: " + index.contextStart
\r
149 + ", s: " + index.start
\r
150 + ", l: " + index.limit
\r
151 + ", cl: " + index.contextLimit
\r
154 System.out.println();
\r
157 buf.replace(buf.length(), buf.length(), String.valueOf(ch));
\r
158 translit.transliterate(buf);
\r
161 String result = buf.toString();
\r
162 //if (result.equals(sourceText + ch)) return;
\r
164 replaceRange(result, 0, getSelectionEnd());
\r
165 setKeyStart(index.start);
\r
167 // At this point start has been changed by the callback to
\r
168 // resetTransliteratorStart() via replaceRange() -- so use our
\r
169 // local copy, saveStart.
\r
171 // The START index is zero-based. On entry to transliterate(),
\r
172 // it was zero. We can therefore just add it to our original
\r
173 // getText()-based index value of start (in saveStart) to get
\r
174 // the new getText()-based start.
\r
175 // start = saveStart + index.contextStart;
\r
177 // Make the cursor getText()-based. The CURSOR index is zero-based.
\r
178 // cursor = start + index.start - index.contextStart;
\r
182 String out = buf.toString();
\r
183 log.append(out.substring(0, index.contextStart)).
\r
185 append(out.substring(index.contextStart, index.start)).
\r
187 append(out.substring(index.start)).
\r
189 log.append(", {" + index.contextStart + ", " + index.contextLimit + ", " + index.start + "}, ");
\r
190 // log.append("start " + start + ", cursor " + cursor);
\r
191 log.append(", sel " + getSelectionStart());
\r
192 System.out.println(escape(log.toString()));
\r
198 * Set the {@link com.ibm.icu.text.Transliterator} and direction to
\r
199 * use to process incoming <code>KeyEvent</code>s.
\r
200 * @param t the {@link com.ibm.icu.text.Transliterator} to use
\r
202 public void setTransliterator(Transliterator t) {
\r
204 if (translit != t) { // [sic] pointer compare ok; singletons
\r
205 resetTransliterationStart();
\r
211 public Transliterator getTransliterator() {
\r
216 * Reset the start point at which transliteration begins. This
\r
217 * needs to be done when the user moves the cursor or when the
\r
218 * current {@link com.ibm.icu.text.Transliterator} is changed.
\r
221 private void resetTransliterationStart() {
\r
222 start = getSelectionStart();
\r
228 * Escape non-ASCII characters as Unicode.
\r
229 * JUST FOR DEBUGGING OUTPUT.
\r
231 public static final String escape(String s) {
\r
232 StringBuffer buf = new StringBuffer();
\r
233 for (int i=0; i<s.length(); ++i) {
\r
234 char c = s.charAt(i);
\r
235 if (c >= ' ' && c <= 0x007F) {
\r
237 buf.append("\\\\"); // That is, "\\"
\r
252 buf.append(Integer.toHexString(c));
\r
255 return buf.toString();
\r