blob: a1e6e07ddff8dc0fe33ad5717d3bfd8e86f02e1f [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 1996-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.demo.translit;
import java.awt.event.*;
import com.ibm.icu.text.*;
import com.ibm.icu.dev.demo.impl.*;
/**
* A subclass of {@link DumbTextComponent} that passes key events through
* a {@link com.ibm.icu.text.Transliterator}.
*
* @author Alan Liu
*/
public class TransliteratingTextComponent extends DumbTextComponent {
/**
* For serialization
*/
private static final long serialVersionUID = -8672128213174154047L;
private static boolean DEBUG = false;
private Transliterator translit = null;
// NOTE: DISABLE THE START AND CURSOR UNTIL WE CAN GET IT TO WORK AT ALL
// Index into getText() where the start of transliteration is.
// As we commit text during transliteration, we advance
// this.
//private int start = 0;
// Index into getText() where the cursor is; cursor >= start
//private int cursor = 0;
// private static final String COPYRIGHT =
// "\u00A9 IBM Corporation 1999. All rights reserved.";
/**
* Constructor.
*/
public TransliteratingTextComponent() {
super();
/*
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// We get an ActionEvent only when the selection changes
resetTransliterationStart();
}
});
*/
}
/**
* {@link DumbTextComponent} API. Framework method that is called
* when a <code>KeyEvent</code> is received. This implementation
* runs the new character through the current
* <code>Transliterator</code>, if one is set, and inserts the
* transliterated text into the buffer.
*/
protected void handleKeyTyped(KeyEvent e) {
char ch = e.getKeyChar();
if (translit == null) {
setKeyStart(-1);
super.handleKeyTyped(e);
return;
}
transliterate(ch, false);
}
public void flush() {
if (translit != null) transliterate('\uFFFF', true);
}
protected void transliterate(char ch, boolean flush) {
// ------------------------------------------------------------
// The following case motivates the two lines that recompute
// start and cursor below.
// " "
// a b c q r|s t u m m
// 0 1 2 3 4 5 6 7 8 9
// 0 1 2
// start 3, cursor 5, sel 6 -> { 0, 3, 2 }
// : new int[] { 0, sel - start, cursor - start };
// sz>99|9
// " { "
// a b c q r 9 9|9 t u m m
// 0 1 2 3 4 5 6 7 8 9 a b
// 0 1 2 3 4
// { 3, 5, 4 } -> start 6, cursor 7, sel 8
// : start += index[0];
// : cursor = start + index[2] - index[0];
// ------------------------------------------------------------
// Need to save start because calls to replaceRange will update
// start and cursor.
//int saveStart = start;
int end = flush ? getSelectionEnd() : getSelectionStart();
String sourceText = getText().substring(0,end);
ReplaceableString buf = new ReplaceableString(sourceText);
/*buf.replace(0, 1, getText().substring(start,
getSelectionStart()));*/
Transliterator.Position index = new Transliterator.Position();
index.contextLimit = buf.length();
index.contextStart = 0;
index.start = getKeyStart();
if (index.start == -1) index.start = getSelectionStart();
index.limit = buf.length();
// StringBuffer log = null;
if (DEBUG) {
System.out.println("Transliterator: " + translit.getID());
System.out.println("From:\t" + '"' + buf.toString() + '"'
+ "; {cs: " + index.contextStart
+ ", s: " + index.start
+ ", l: " + index.limit
+ ", cl: " + index.contextLimit
+ "}" + "; '" + ch + "'"
+ " " + getKeyStart()
);
}
if (flush) {
translit.finishTransliteration(buf, index);
} else {
translit.transliterate(buf, index, ch);
}
if (DEBUG) {
System.out.println("To:\t" + '"' + buf.toString() + '"'
+ "; {cs: " + index.contextStart
+ ", s: " + index.start
+ ", l: " + index.limit
+ ", cl: " + index.contextLimit
+ "}"
);
System.out.println();
}
/*
buf.replace(buf.length(), buf.length(), String.valueOf(ch));
translit.transliterate(buf);
*/
String result = buf.toString();
//if (result.equals(sourceText + ch)) return;
replaceRange(result, 0, getSelectionEnd());
setKeyStart(index.start);
// At this point start has been changed by the callback to
// resetTransliteratorStart() via replaceRange() -- so use our
// local copy, saveStart.
// The START index is zero-based. On entry to transliterate(),
// it was zero. We can therefore just add it to our original
// getText()-based index value of start (in saveStart) to get
// the new getText()-based start.
// start = saveStart + index.contextStart;
// Make the cursor getText()-based. The CURSOR index is zero-based.
// cursor = start + index.start - index.contextStart;
/*
if (DEBUG) {
String out = buf.toString();
log.append(out.substring(0, index.contextStart)).
append('{').
append(out.substring(index.contextStart, index.start)).
append('|').
append(out.substring(index.start)).
append('"');
log.append(", {" + index.contextStart + ", " + index.contextLimit + ", " + index.start + "}, ");
// log.append("start " + start + ", cursor " + cursor);
log.append(", sel " + getSelectionStart());
System.out.println(escape(log.toString()));
}
*/
}
/**
* Set the {@link com.ibm.icu.text.Transliterator} and direction to
* use to process incoming <code>KeyEvent</code>s.
* @param t the {@link com.ibm.icu.text.Transliterator} to use
*/
public void setTransliterator(Transliterator t) {
/*
if (translit != t) { // [sic] pointer compare ok; singletons
resetTransliterationStart();
}
*/
translit = t;
}
public Transliterator getTransliterator() {
return translit;
}
/**
* Reset the start point at which transliteration begins. This
* needs to be done when the user moves the cursor or when the
* current {@link com.ibm.icu.text.Transliterator} is changed.
*/
/*
private void resetTransliterationStart() {
start = getSelectionStart();
cursor = start;
}
*/
/**
* Escape non-ASCII characters as Unicode.
* JUST FOR DEBUGGING OUTPUT.
*/
public static final String escape(String s) {
StringBuffer buf = new StringBuffer();
for (int i=0; i<s.length(); ++i) {
char c = s.charAt(i);
if (c >= ' ' && c <= 0x007F) {
if (c == '\\') {
buf.append("\\\\"); // That is, "\\"
} else {
buf.append(c);
}
} else {
buf.append("\\u");
if (c < 0x1000) {
buf.append('0');
if (c < 0x100) {
buf.append('0');
if (c < 0x10) {
buf.append('0');
}
}
}
buf.append(Integer.toHexString(c));
}
}
return buf.toString();
}
}