1- package processing .app .syntax ;
1+ package processing .app .syntax . im ;
22
3- import java .awt .Font ;
4- import java .awt .FontMetrics ;
5- import java .awt .Graphics ;
6- import java .awt .Graphics2D ;
7- import java .awt .Point ;
83import java .awt .Rectangle ;
94import java .awt .event .InputMethodEvent ;
105import java .awt .event .InputMethodListener ;
11- import java .awt .font .FontRenderContext ;
12- import java .awt .font .TextAttribute ;
136import java .awt .font .TextHitInfo ;
14- import java .awt .font .TextLayout ;
157import java .awt .im .InputMethodRequests ;
168import java .text .AttributedCharacterIterator ;
17- import java .text .AttributedString ;
18-
19- import javax .swing .text .BadLocationException ;
209
10+ import processing .app .syntax .JEditTextArea ;
11+
12+ /**
13+ * Support in-line Japanese input for PDE. (Maybe Chinese, Korean and more)
14+ * This class is implemented by Java Input Method Framework and handles
15+ * If you would like to know more about Java Input Method Framework,
16+ * Please see http://java.sun.com/j2se/1.5.0/docs/guide/imf/
17+ *
18+ * This class is implemented to fix Bug 854.
19+ *
20+ * @author Takashi Maekawa (takachin@generative.info)
21+ */
2122public class InputMethodSupport implements InputMethodRequests ,
2223 InputMethodListener {
2324
24- private JEditTextArea textArea ;
25-
26- private TextLayout composedTextLayout = null ;
27-
2825 private int committed_count = 0 ;
29-
30- private static final int COMPOSING_UNDERBAR_HEIGHT = 5 ;
31-
32- private boolean isComposing ;
26+ private CompositionTextManager textManager ;
3327
3428 public InputMethodSupport (JEditTextArea textArea ) {
35- this . textArea = textArea ;
29+ textManager = new CompositionTextManager ( textArea ) ;
3630 textArea .enableInputMethods (true );
3731 textArea .addInputMethodListener (this );
38- isComposing = false ;
39- }
40-
41- public boolean getIsComposing () {
42- return isComposing ;
43- }
44-
45- private Point getCaretLocation () {
46- Point loc = new Point ();
47- TextAreaPainter painter = textArea .getPainter ();
48- FontMetrics fm = painter .getFontMetrics ();
49- int offsetY = fm .getHeight () - 5 ;
50- int lineIndex = textArea .getCaretLine ();
51- loc .y = lineIndex * fm .getHeight () + offsetY ;
52- int offsetX = textArea .getCaretPosition ()
53- - textArea .getLineStartOffset (lineIndex );
54- loc .x = textArea .offsetToX (lineIndex , offsetX );
55- return loc ;
5632 }
5733
5834 public Rectangle getTextLocation (TextHitInfo offset ) {
59- Point caret = getCaretLocation ();
60- return getCaretRectangle (caret .x , caret .y );
61- }
62-
63- private Rectangle getCaretRectangle (int x , int y ) {
64- TextAreaPainter painter = textArea .getPainter ();
65- Point origin = painter .getLocationOnScreen ();
66- int height = painter .getFontMetrics ().getHeight ();
67- return new Rectangle (origin .x + x , origin .y + y , 0 , height );
35+ return textManager .getTextLocation ();
6836 }
6937
7038 public TextHitInfo getLocationOffset (int x , int y ) {
7139 return null ;
7240 }
7341
7442 public int getInsertPositionOffset () {
75- if (isComposing ) {
76- isComposing = false ;
77- }
78- return textArea .getCaretPosition ();
43+ return textManager .getInsertPositionOffset ();
7944 }
8045
8146 public AttributedCharacterIterator getCommittedText (int beginIndex ,
8247 int endIndex , AttributedCharacterIterator .Attribute [] attributes ) {
83- return (new AttributedString (textArea .getText (beginIndex , endIndex
84- - beginIndex ))).getIterator ();
48+ return textManager .getCommittedText (beginIndex , endIndex );
8549 }
8650
8751 public int getCommittedTextLength () {
@@ -98,73 +62,144 @@ public AttributedCharacterIterator getSelectedText(
9862 return null ;
9963 }
10064
65+ /**
66+ * Handles events from InputMethod.
67+ * This method judges whether beginning of input or
68+ * progress of input or end and call related method.
69+ *
70+ * @param event event from Input Method.
71+ */
10172 public void inputMethodTextChanged (InputMethodEvent event ) {
102- composedTextLayout = null ;
10373 AttributedCharacterIterator text = event .getText ();
10474 committed_count = event .getCommittedCharacterCount ();
105- if (committed_count == 0 ) {
106- if (text .getEndIndex () == 0 ) {
107- caretPositionChanged (event );
108- return ;
109- }
110- if (text .getEndIndex () < text .getBeginIndex ()) {
111- caretPositionChanged (event );
112- return ;
113- }
114- isComposing = true ;
115- drawComposingText (text , committed_count );
75+ if (isBeginInputProcess (text , textManager )){
76+ textManager .beginCompositionText (text , committed_count );
77+ caretPositionChanged (event );
78+ return ;
79+ }
80+ if (isInputProcess (text )){
81+ textManager .processCompositionText (text , committed_count );
11682 caretPositionChanged (event );
11783 return ;
11884 }
119- commitText (text , committed_count );
120- isComposing = false ;
85+ textManager .endCompositionText (text , committed_count );
12186 caretPositionChanged (event );
12287 }
12388
124- private void drawComposingText (AttributedCharacterIterator text , int count ) {
125- assert ((count == 0 && text .getEndIndex () > 0 ));
126- Point textLocation = getCaretLocation ();
127- invalidateComposingLine (textArea .getPainter (), textLocation .x ,
128- textLocation .y );
129- composedTextLayout = getTextLayout (text , count );
130- composedTextLayout .draw ((Graphics2D ) (textArea .getPainter ().getGraphics ()),
131- textLocation .x , textLocation .y );
89+ private boolean isBeginInputProcess (AttributedCharacterIterator text , CompositionTextManager textManager ){
90+ if (text == null )
91+ return false ;
92+ return (isInputProcess (text ) && !textManager .getIsInputProcess ());
93+ }
94+
95+ private boolean isInputProcess (AttributedCharacterIterator text ){
96+ if (text == null )
97+ return false ;
98+ return (text .getEndIndex () - (text .getBeginIndex () + committed_count ) > 0 );
99+ }
100+
101+ public void caretPositionChanged (InputMethodEvent event ) {
102+ event .consume ();
132103 }
104+ }
105+ package processing .app .syntax .im ;
106+
107+ import java .awt .Rectangle ;
108+ import java .awt .event .InputMethodEvent ;
109+ import java .awt .event .InputMethodListener ;
110+ import java .awt .font .TextHitInfo ;
111+ import java .awt .im .InputMethodRequests ;
112+ import java .text .AttributedCharacterIterator ;
133113
134- private void invalidateComposingLine (TextAreaPainter painter , int x , int y ) {
135- Graphics gfx = painter .getGraphics ();
136- gfx .setColor (painter .lineHighlightColor );
137- gfx .fillRect (x , y
138- - (painter .getFontMetrics ().getHeight () - COMPOSING_UNDERBAR_HEIGHT ), //
139- painter .getWidth (), painter .getFontMetrics ().getHeight ());
114+ import processing .app .syntax .JEditTextArea ;
115+
116+ /**
117+ * Support in-line Japanese input for PDE. (Maybe Chinese, Korean and more)
118+ * This class is implemented by Java Input Method Framework and handles
119+ * If you would like to know more about Java Input Method Framework,
120+ * Please see http://java.sun.com/j2se/1.5.0/docs/guide/imf/
121+ *
122+ * This class is implemented to fix Bug 854.
123+ *
124+ * @author Takashi Maekawa (takachin@generative.info)
125+ */
126+ public class InputMethodSupport implements InputMethodRequests ,
127+ InputMethodListener {
128+
129+ private int committed_count = 0 ;
130+ private CompositionTextManager textManager ;
131+
132+ public InputMethodSupport (JEditTextArea textArea ) {
133+ textManager = new CompositionTextManager (textArea );
134+ textArea .enableInputMethods (true );
135+ textArea .addInputMethodListener (this );
140136 }
141137
142- private void commitText (AttributedCharacterIterator text , int count ) {
143- char c ;
144- StringBuffer committing = new StringBuffer (count );
145- for (c = text .first (); c != AttributedCharacterIterator .DONE && count > 0 ; c = text
146- .next (), --count ) {
147- committing .append (c );
138+ public Rectangle getTextLocation (TextHitInfo offset ) {
139+ return textManager .getTextLocation ();
140+ }
141+
142+ public TextHitInfo getLocationOffset (int x , int y ) {
143+ return null ;
144+ }
145+
146+ public int getInsertPositionOffset () {
147+ return textManager .getInsertPositionOffset ();
148+ }
149+
150+ public AttributedCharacterIterator getCommittedText (int beginIndex ,
151+ int endIndex , AttributedCharacterIterator .Attribute [] attributes ) {
152+ return textManager .getCommittedText (beginIndex , endIndex );
153+ }
154+
155+ public int getCommittedTextLength () {
156+ return committed_count ;
157+ }
158+
159+ public AttributedCharacterIterator cancelLatestCommittedText (
160+ AttributedCharacterIterator .Attribute [] attributes ) {
161+ return null ;
162+ }
163+
164+ public AttributedCharacterIterator getSelectedText (
165+ AttributedCharacterIterator .Attribute [] attributes ) {
166+ return null ;
167+ }
168+
169+ /**
170+ * Handles events from InputMethod.
171+ * This method judges whether beginning of input or
172+ * progress of input or end and call related method.
173+ *
174+ * @param event event from Input Method.
175+ */
176+ public void inputMethodTextChanged (InputMethodEvent event ) {
177+ AttributedCharacterIterator text = event .getText ();
178+ committed_count = event .getCommittedCharacterCount ();
179+ if (isBeginInputProcess (text , textManager )){
180+ textManager .beginCompositionText (text , committed_count );
181+ caretPositionChanged (event );
182+ return ;
148183 }
149- int caret = textArea .getCaretPosition ();
150- String committing_text = committing .toString ();
151- try {
152- textArea .getDocument ().insertString (caret , committing_text , null );
153- } catch (BadLocationException e ) {
154- e .printStackTrace ();
184+ if (isInputProcess (text )){
185+ textManager .processCompositionText (text , committed_count );
186+ caretPositionChanged (event );
187+ return ;
155188 }
189+ textManager .endCompositionText (text , committed_count );
190+ caretPositionChanged (event );
191+ }
192+
193+ private boolean isBeginInputProcess (AttributedCharacterIterator text , CompositionTextManager textManager ){
194+ if (text == null )
195+ return false ;
196+ return (isInputProcess (text ) && !textManager .getIsInputProcess ());
156197 }
157198
158- private TextLayout getTextLayout (AttributedCharacterIterator text ,
159- int committed_count ) {
160- AttributedString composed = new AttributedString (text , committed_count ,
161- text .getEndIndex ());
162- Font font = textArea .getPainter ().getFont ();
163- FontRenderContext context = ((Graphics2D ) (textArea .getPainter ()
164- .getGraphics ())).getFontRenderContext ();
165- composed .addAttribute (TextAttribute .FONT , font );
166- TextLayout layout = new TextLayout (composed .getIterator (), context );
167- return layout ;
199+ private boolean isInputProcess (AttributedCharacterIterator text ){
200+ if (text == null )
201+ return false ;
202+ return (text .getEndIndex () - (text .getBeginIndex () + committed_count ) > 0 );
168203 }
169204
170205 public void caretPositionChanged (InputMethodEvent event ) {
0 commit comments