1 23 24 package org.gjt.sp.jedit.textarea; 25 26 import java.text.AttributedString ; 28 import java.text.AttributedCharacterIterator ; 29 import java.awt.Point ; 30 import java.awt.Rectangle ; 31 import java.awt.Graphics2D ; 32 import java.awt.FontMetrics ; 33 import java.awt.im.InputMethodRequests ; 34 import java.awt.event.InputMethodListener ; 35 import java.awt.event.InputMethodEvent ; 36 import java.awt.font.TextLayout ; 37 import java.awt.font.TextAttribute ; 38 import java.awt.font.TextHitInfo ; 39 41 47 48 class InputMethodSupport 49 extends TextAreaExtension 50 implements InputMethodRequests , InputMethodListener 51 { 52 private TextArea owner; 54 private TextLayout composedTextLayout = null; 56 private int composedCaretX = 0; 58 private int lastCommittedAt = 0; 60 private String lastCommittedText = null; 61 62 public InputMethodSupport(TextArea owner) 63 { 64 this.owner = owner; 65 owner.addInputMethodListener(this); 66 owner.getPainter().addExtension(TextAreaPainter.HIGHEST_LAYER, this); 67 } 68 69 70 private Rectangle getCaretRectangle(int x, int y) 73 { 74 TextAreaPainter painter = owner.getPainter(); 75 Point origin = painter.getLocationOnScreen(); 76 int height = painter.getFontMetrics().getHeight(); 77 return new Rectangle (origin.x + x, origin.y + y, 0, height); 78 } 79 81 82 public void paintValidLine(Graphics2D gfx, int screenLine, 84 int physicalLine, int start, int end, int y) 85 { 86 if(composedTextLayout != null) 87 { 88 int caret = owner.getCaretPosition(); 89 if(start <= caret && caret < end) 90 { 91 TextAreaPainter painter = owner.getPainter(); 92 FontMetrics fm = painter.getFontMetrics(); 97 int x = owner.offsetToXY(caret).x; 98 int width = Math.round(composedTextLayout.getAdvance()); 99 int height = fm.getHeight(); 100 int offset_to_baseline = height 101 - fm.getLeading() - fm.getDescent(); 102 int caret_x = x + composedCaretX; 103 104 gfx.setColor(painter.getBackground()); 105 gfx.fillRect(x, y, width, height); 106 gfx.setColor(painter.getForeground()); 107 composedTextLayout.draw(gfx, x, y + offset_to_baseline); 108 gfx.setColor(painter.getCaretColor()); 109 gfx.drawLine(caret_x, y, caret_x, y + height - 1); 110 } 111 } 112 } 113 115 116 public Rectangle getTextLocation(TextHitInfo offset) 118 { 119 if(composedTextLayout != null) 120 { 121 Point caret = owner.offsetToXY(owner.getCaretPosition()); 123 return getCaretRectangle(caret.x + composedCaretX, caret.y); 124 } 125 else 126 { 127 Selection selection_on_caret = owner.getSelectionAtOffset(owner.getCaretPosition()); 129 if(selection_on_caret != null) 130 { 131 Point selection_start = owner.offsetToXY(selection_on_caret.getStart()); 132 return getCaretRectangle(selection_start.x, selection_start.y); 133 } 134 } 135 return null; 136 } 137 138 public TextHitInfo getLocationOffset(int x, int y) 139 { 140 if(composedTextLayout != null) 141 { 142 Point origin = owner.getPainter().getLocationOnScreen(); 143 Point caret = owner.offsetToXY(owner.getCaretPosition()); 144 float local_x = x - origin.x - caret.x; 145 float local_y = y - origin.y - caret.y 146 - composedTextLayout.getLeading() 147 - composedTextLayout.getAscent(); 148 return composedTextLayout.hitTestChar(local_x, local_y); 149 } 150 return null; 151 } 152 153 public int getInsertPositionOffset() 154 { 155 return owner.getCaretPosition(); 156 } 157 158 public AttributedCharacterIterator getCommittedText(int beginIndex , int endIndex 159 , AttributedCharacterIterator.Attribute [] attributes) 160 { 161 return (new AttributedString (owner.getText(beginIndex, endIndex - beginIndex))).getIterator(); 162 } 163 164 public int getCommittedTextLength() 165 { 166 return owner.getBufferLength(); 167 } 168 169 public AttributedCharacterIterator cancelLatestCommittedText(AttributedCharacterIterator.Attribute [] attributes) 170 { 171 if(lastCommittedText != null) 172 { 173 int offset = lastCommittedAt; 174 int length = lastCommittedText.length(); 175 String sample = owner.getText(offset, length); 176 if(sample != null && sample.equals(lastCommittedText)) 177 { 178 AttributedCharacterIterator canceled = (new AttributedString (sample)).getIterator(); 179 owner.getBuffer().remove(offset, length); 180 owner.setCaretPosition(offset); 181 lastCommittedText = null; 182 return canceled; 183 } 184 lastCommittedText = null; 187 } 188 return null; 189 } 190 191 public AttributedCharacterIterator getSelectedText(AttributedCharacterIterator.Attribute [] attributes) 192 { 193 Selection selection_on_caret = owner.getSelectionAtOffset(owner.getCaretPosition()); 194 if(selection_on_caret != null) 195 { 196 return (new AttributedString (owner.getSelectedText(selection_on_caret))).getIterator(); 197 } 198 return null; 199 } 200 202 203 public void inputMethodTextChanged(InputMethodEvent event) 205 { 206 composedTextLayout = null; 207 AttributedCharacterIterator text = event.getText(); 208 if(text != null) 209 { 210 int committed_count = event.getCommittedCharacterCount(); 211 if(committed_count > 0) 212 { 213 lastCommittedText = null; 214 lastCommittedAt = owner.getCaretPosition(); 215 StringBuffer committed = new StringBuffer (committed_count); 216 char c; 217 int count; 218 for(c = text.first(), count = committed_count 219 ; c != AttributedCharacterIterator.DONE && count > 0 220 ; c = text.next(), --count) 221 { 222 owner.userInput(c); 223 committed.append(c); 224 } 225 lastCommittedText = committed.toString(); 226 } 227 int end_index = text.getEndIndex(); 228 if(committed_count < end_index) 229 { 230 AttributedString composed = new AttributedString (text, committed_count, end_index); 231 TextAreaPainter painter = owner.getPainter(); 232 composed.addAttribute(TextAttribute.FONT, painter.getFont()); 233 composedTextLayout = new TextLayout (composed.getIterator() 234 , painter.getFontRenderContext()); 235 } 236 } 237 caretPositionChanged(event); 239 } 240 241 public void caretPositionChanged(InputMethodEvent event) 242 { 243 composedCaretX = 0; 244 if(composedTextLayout != null) 245 { 246 TextHitInfo caret = event.getCaret(); 247 if(caret != null) 248 { 249 composedCaretX = Math.round(composedTextLayout.getCaretInfo(caret)[0]); 250 } 251 int insertion_x = owner.offsetToXY(owner.getCaretPosition()).x; 253 TextHitInfo visible = event.getVisiblePosition(); 254 int composed_visible_x = (visible != null) 255 ? Math.round(composedTextLayout.getCaretInfo(visible)[0]) 256 : composedCaretX; 257 int visible_x = insertion_x + composed_visible_x; 258 int painter_width = owner.getPainter().getWidth(); 259 int adjustment = 0; 260 if(visible_x < 0) 261 { 262 adjustment = visible_x; 263 } 264 if(visible_x >= painter_width) 265 { 266 adjustment = visible_x - (painter_width - 1); 267 } 268 if(adjustment != 0) 269 { 270 owner.setHorizontalOffset(owner.getHorizontalOffset() - adjustment); 271 } 272 } 273 else 274 { 275 280 owner.scrollToCaret(false); 281 } 282 285 int caret_line = owner.getCaretLine(); 286 owner.invalidateLineRange(caret_line, caret_line + 1); 287 event.consume(); 288 } 289 } 291 | Popular Tags |