if (! isEditable()) { return; } else { switch (e.getID()) { case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: replaceInputMethodText(e); // fall through case InputMethodEvent.CARET_POSITION_CHANGED: setInputMethodCaretPosition(e); break; } } e.consume(); } } // // Overrides this method to become an active input method client. // public InputMethodRequests getInputMethodRequests() { if (inputMethodRequestsHandler == null) { inputMethodRequestsHandler = new InputMethodRequestsHandler(); Document doc = getDocument(); if (doc != null) { doc.addDocumentListener((DocumentListener)inputMethodRequestsHandler); } } return inputMethodRequestsHandler; } // // Overrides this method to watch the listener installed. // public void addInputMethodListener(InputMethodListener l) { super.addInputMethodListener(l); if (l != null) { needToSendKeyTypedEvent = false; checkedInputOverride = true; } } // // Default implementation of the InputMethodRequests interface. // class InputMethodRequestsHandler implements InputMethodRequests, DocumentListener { // --- InputMethodRequests methods --- public AttributedCharacterIterator cancelLatestCommittedText( Attribute[] attributes) { Document doc = getDocument(); if ((doc != null) && (latestCommittedTextStart != null) && (!latestCommittedTextStart.equals(latestCommittedTextEnd))) { try { int startIndex = latestCommittedTextStart.getOffset(); int endIndex = latestCommittedTextEnd.getOffset(); String latestCommittedText = doc.getText(startIndex, endIndex - startIndex); doc.remove(startIndex, endIndex - startIndex); return new AttributedString(latestCommittedText).getIterator(); } catch (BadLocationException ble) {} } return null; } public AttributedCharacterIterator getCommittedText(int beginIndex, int endIndex, Attribute[] attributes) { int composedStartIndex = 0; int composedEndIndex = 0; if (composedTextExists()) { composedStartIndex = composedTextStart.getOffset(); composedEndIndex = composedTextEnd.getOffset(); } String committed; try { if (beginIndex < composedStartIndex) { if (endIndex <= composedStartIndex) { committed = getText(beginIndex, endIndex - beginIndex); } else { int firstPartLength = composedStartIndex - beginIndex; committed = getText(beginIndex, firstPartLength) + getText(composedEndIndex, endIndex - beginIndex - firstPartLength); } } else { committed = getText(beginIndex + (composedEndIndex - composedStartIndex), endIndex - beginIndex); } } catch (BadLocationException ble) { throw new IllegalArgumentException("Invalid range"); } return new AttributedString(committed).getIterator(); } public int getCommittedTextLength() { Document doc = getDocument(); int length = 0; if (doc != null) { length = doc.getLength(); if (composedTextContent != null) { if (composedTextEnd == null || composedTextStart == null) { /* * fix for : 6355666 * this is the case when this method is invoked * from DocumentListener. At this point * composedTextEnd and composedTextStart are * not defined yet. */ length -= composedTextContent.length(); } else { length -= composedTextEnd.getOffset() - composedTextStart.getOffset(); } } } return length; } public int getInsertPositionOffset() { int composedStartIndex = 0; int composedEndIndex = 0; if (composedTextExists()) { composedStartIndex = composedTextStart.getOffset(); composedEndIndex = composedTextEnd.getOffset(); } int caretIndex = getCaretPosition(); if (caretIndex < composedStartIndex) { return caretIndex; } else if (caretIndex < composedEndIndex) { return composedStartIndex; } else { return caretIndex - (composedEndIndex - composedStartIndex); } } public TextHitInfo getLocationOffset(int x, int y) { if (composedTextAttribute == null) { return null; } else { Point p = getLocationOnScreen(); p.x = x - p.x; p.y = y - p.y; int pos = viewToModel(p); if ((pos >= composedTextStart.getOffset()) && (pos <= composedTextEnd.getOffset())) { return TextHitInfo.leading(pos - composedTextStart.getOffset()); } else { return null; } } } public Rectangle getTextLocation(TextHitInfo offset) { Rectangle r; try { r = modelToView(getCaretPosition()); if (r != null) { Point p = getLocationOnScreen(); r.translate(p.x, p.y); } } catch (BadLocationException ble) { r = null; } if (r == null) r = new Rectangle(); return r; } public AttributedCharacterIterator getSelectedText( Attribute[] attributes) { String selection = JTextComponent.this.getSelectedText(); if (selection != null) { return new AttributedString(selection).getIterator(); } else { return null; } } // --- DocumentListener methods --- public void changedUpdate(DocumentEvent e) { latestCommittedTextStart = latestCommittedTextEnd = null; } public void insertUpdate(DocumentEvent e) { latestCommittedTextStart = latestCommittedTextEnd = null; } public void removeUpdate(DocumentEvent e) { latestCommittedTextStart = latestCommittedTextEnd = null; } } // // Replaces the current input method (composed) text according to // the passed input method event. This method also inserts the // committed text into the document. // private void replaceInputMethodText(InputMethodEvent e) { int commitCount = e.getCommittedCharacterCount(); AttributedCharacterIterator text = e.getText(); int composedTextIndex; // old composed text deletion Document doc = getDocument(); if (composedTextExists()) { try { doc.remove(composedTextStart.getOffset(), composedTextEnd.getOffset() - composedTextStart.getOffset()); } catch (BadLocationException ble) {} composedTextStart = composedTextEnd = null; composedTextAttribute = null; composedTextContent = null; } if (text != null) { text.first(); int committedTextStartIndex = 0; int committedTextEndIndex = 0; // committed text insertion if (commitCount > 0) { // Remember latest committed text start index committedTextStartIndex = caret.getDot(); // Need to generate KeyTyped events for the committed text for components // that are not aware they are active input method clients. if (shouldSynthensizeKeyEvents()) { for (char c = text.current(); commitCount > 0; c = text.next(), commitCount--) { KeyEvent ke = new KeyEvent(this, KeyEvent.KEY_TYPED, EventQueue.getMostRecentEventTime(), 0, KeyEvent.VK_UNDEFINED, c); processKeyEvent(ke); } } else { StringBuilder strBuf = new StringBuilder(); for (char c = text.current(); commitCount > 0; c = text.next(), commitCount--) { strBuf.append(c); } // map it to an ActionEvent mapCommittedTextToAction(strBuf.toString()); } // Remember latest committed text end index committedTextEndIndex = caret.getDot(); } // new composed text insertion composedTextIndex = text.getIndex(); if (composedTextIndex < text.getEndIndex()) { createComposedTextAttribute(composedTextIndex, text); try { replaceSelection(null); doc.insertString(caret.getDot(), composedTextContent, composedTextAttribute); composedTextStart = doc.createPosition(caret.getDot() - composedTextContent.length()); composedTextEnd = doc.createPosition(caret.getDot()); } catch (BadLocationException ble) { composedTextStart = composedTextEnd = null; composedTextAttribute = null; composedTextContent = null; } } // Save the latest committed text information if (committedTextStartIndex != committedTextEndIndex) { try { latestCommittedTextStart = doc. createPosition(committedTextStartIndex); latestCommittedTextEnd = doc. createPosition(committedTextEndIndex); } catch (BadLocationException ble) { latestCommittedTextStart = latestCommittedTextEnd = null; } } else { latestCommittedTextStart = latestCommittedTextEnd = null; } } } private void createComposedTextAttribute(int composedIndex, AttributedCharacterIterator text) { Document doc = getDocument(); StringBuilder strBuf = new StringBuilder(); // create attributed string with no attributes for (char c = text.setIndex(composedIndex); c != CharacterIterator.DONE; c = text.next()) { strBuf.append(c); } composedTextContent = strBuf.toString(); composedTextAttribute = new SimpleAttributeSet(); composedTextAttribute.addAttribute(StyleConstants.ComposedTextAttribute, new AttributedString(text, composedIndex, text.getEndIndex())); } /** * Saves composed text around the specified position. * * The composed text (if any) around the specified position is saved * in a backing store and removed from the document. * * @param pos document position to identify the composed text location * @return {@code true} if the composed text exists and is saved, * {@code false} otherwise * @see #restoreComposedText * @since 1.7 */ protected boolean saveComposedText(int pos) { if (composedTextExists()) { int start = composedTextStart.getOffset(); int len = composedTextEnd.getOffset() - composedTextStart.getOffset(); if (pos >= start && pos <= start + len) { try { getDocument().remove(start, len); return true; } catch (BadLocationException ble) {} } } return false; } /** * Restores composed text previously saved by {@code saveComposedText}. * * The saved composed text is inserted back into the document. This method * should be invoked only if {@code saveComposedText} returns {@code true}. * * @see #saveComposedText * @since 1.7 */ protected void restoreComposedText() { Document doc = getDocument(); try { doc.insertString(caret.getDot(), composedTextContent, composedTextAttribute); composedTextStart = doc.createPosition(caret.getDot() - composedTextContent.length()); composedTextEnd = doc.createPosition(caret.getDot()); } catch (BadLocationException ble) {} } // // Map committed text to an ActionEvent. If the committed text length is 1, // treat it as a KeyStroke, otherwise or there is no KeyStroke defined, // treat it just as a default action. // private void mapCommittedTextToAction(String committedText) { Keymap binding = getKeymap(); if (binding != null) { Action a = null; if (committedText.length() == 1) { KeyStroke k = KeyStroke.getKeyStroke(committedText.charAt(0)); a = binding.getAction(k); } if (a == null) { a = binding.getDefaultAction(); } if (a != null) { ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, committedText, EventQueue.getMostRecentEventTime(), getCurrentEventModifiers()); a.actionPerformed(ae); } } } // // Sets the caret position according to the passed input method // event. Also, sets/resets composed text caret appropriately. // private void setInputMethodCaretPosition(InputMethodEvent e) { int dot; if (composedTextExists()) { dot = composedTextStart.getOffset(); if (!(caret instanceof ComposedTextCaret)) { if (composedTextCaret == null) { composedTextCaret = new ComposedTextCaret(); } originalCaret = caret; // Sets composed text caret exchangeCaret(originalCaret, composedTextCaret); } TextHitInfo caretPos = e.getCaret(); if (caretPos != null) { int index = caretPos.getInsertionIndex(); dot += index; if (index == 0) { // Scroll the component if needed so that the composed text // becomes visible. try { Rectangle d = modelToView(dot); Rectangle end = modelToView(composedTextEnd.getOffset()); Rectangle b = getBounds(); d.x += Math.min(end.x - d.x, b.width); scrollRectToVisible(d); } catch (BadLocationException ble) {} } } caret.setDot(dot); } else if (caret instanceof ComposedTextCaret) { dot = caret.getDot(); // Restores original caret exchangeCaret(caret, originalCaret); caret.setDot(dot); } } private void exchangeCaret(Caret oldCaret, Caret newCaret) { int blinkRate = oldCaret.getBlinkRate(); setCaret(newCaret); caret.setBlinkRate(blinkRate); caret.setVisible(hasFocus()); } /** * Returns true if KeyEvents should be synthesized from an InputEvent. */ private boolean shouldSynthensizeKeyEvents() { if (!checkedInputOverride) { checkedInputOverride = true; needToSendKeyTypedEvent = !isProcessInputMethodEventOverridden(); } return needToSendKeyTypedEvent; } // // Checks whether the client code overrides processInputMethodEvent. If it is overridden, // need not to generate KeyTyped events for committed text. If it's not, behave as an // passive input method client. // private boolean isProcessInputMethodEventOverridden() { if (overrideMap == null) { overrideMap = Collections.synchronizedMap(new HashMap<String, Boolean>()); } Boolean retValue = overrideMap.get(getClass().getName()); if (retValue != null) { return retValue.booleanValue(); } Boolean ret = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { public Boolean run() { return isProcessInputMethodEventOverridden( JTextComponent.this.getClass()); } }); return ret.booleanValue(); } // // Checks whether a composed text in this text component // boolean composedTextExists() { return (composedTextStart != null); } // // Caret implementation for editing the composed text. // class ComposedTextCaret extends DefaultCaret implements Serializable { Color bg; // // Get the background color of the component // public void install(JTextComponent c) { super.install(c); Document doc = c.getDocument(); if (doc instanceof StyledDocument) { StyledDocument sDoc = (StyledDocument)doc;Lines 4501–5000 of 5073. Previous lines Load more
if (! isEditable()) { return; } else { switch (e.getID()) { case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED: replaceInputMethodText(e); // fall through case InputMethodEvent.CARET_POSITION_CHANGED: setInputMethodCaretPosition(e); break; } } e.consume(); } } // // Overrides this method to become an active input method client. // public InputMethodRequests getInputMethodRequests() { if (inputMethodRequestsHandler == null) { inputMethodRequestsHandler = new InputMethodRequestsHandler(); Document doc = getDocument(); if (doc != null) { doc.addDocumentListener((DocumentListener)inputMethodRequestsHandler); } } return inputMethodRequestsHandler; } // // Overrides this method to watch the listener installed. // public void addInputMethodListener(InputMethodListener l) { super.addInputMethodListener(l); if (l != null) { needToSendKeyTypedEvent = false; checkedInputOverride = true; } } // // Default implementation of the InputMethodRequests interface. // class InputMethodRequestsHandler implements InputMethodRequests, DocumentListener { // --- InputMethodRequests methods --- public AttributedCharacterIterator cancelLatestCommittedText( Attribute[] attributes) { Document doc = getDocument(); if ((doc != null) && (latestCommittedTextStart != null) && (!latestCommittedTextStart.equals(latestCommittedTextEnd))) { try { int startIndex = latestCommittedTextStart.getOffset(); int endIndex = latestCommittedTextEnd.getOffset(); String latestCommittedText = doc.getText(startIndex, endIndex - startIndex); doc.remove(startIndex, endIndex - startIndex); return new AttributedString(latestCommittedText).getIterator(); } catch (BadLocationException ble) {} } return null; } public AttributedCharacterIterator getCommittedText(int beginIndex, int endIndex, Attribute[] attributes) { int composedStartIndex = 0; int composedEndIndex = 0; if (composedTextExists()) { composedStartIndex = composedTextStart.getOffset(); composedEndIndex = composedTextEnd.getOffset(); } String committed; try { if (beginIndex < composedStartIndex) { if (endIndex <= composedStartIndex) { committed = getText(beginIndex, endIndex - beginIndex); } else { int firstPartLength = composedStartIndex - beginIndex; committed = getText(beginIndex, firstPartLength) + getText(composedEndIndex, endIndex - beginIndex - firstPartLength); } } else { committed = getText(beginIndex + (composedEndIndex - composedStartIndex), endIndex - beginIndex); } } catch (BadLocationException ble) { throw new IllegalArgumentException("Invalid range"); } return new AttributedString(committed).getIterator(); } public int getCommittedTextLength() { Document doc = getDocument(); int length = 0; if (doc != null) { length = doc.getLength(); if (composedTextContent != null) { if (composedTextEnd == null || composedTextStart == null) { /* * fix for : 6355666 * this is the case when this method is invoked * from DocumentListener. At this point * composedTextEnd and composedTextStart are * not defined yet. */ length -= composedTextContent.length(); } else { length -= composedTextEnd.getOffset() - composedTextStart.getOffset(); } } } return length; } public int getInsertPositionOffset() { int composedStartIndex = 0; int composedEndIndex = 0; if (composedTextExists()) { composedStartIndex = composedTextStart.getOffset(); composedEndIndex = composedTextEnd.getOffset(); } int caretIndex = getCaretPosition(); if (caretIndex < composedStartIndex) { return caretIndex; } else if (caretIndex < composedEndIndex) { return composedStartIndex; } else { return caretIndex - (composedEndIndex - composedStartIndex); } } public TextHitInfo getLocationOffset(int x, int y) { if (composedTextAttribute == null) { return null; } else { Point p = getLocationOnScreen(); p.x = x - p.x; p.y = y - p.y; int pos = viewToModel(p); if ((pos >= composedTextStart.getOffset()) && (pos <= composedTextEnd.getOffset())) { return TextHitInfo.leading(pos - composedTextStart.getOffset()); } else { return null; } } } public Rectangle getTextLocation(TextHitInfo offset) { Rectangle r; try { r = modelToView(getCaretPosition()); if (r != null) { Point p = getLocationOnScreen(); r.translate(p.x, p.y); } } catch (BadLocationException ble) { r = null; } if (r == null) r = new Rectangle(); return r; } public AttributedCharacterIterator getSelectedText( Attribute[] attributes) { String selection = JTextComponent.this.getSelectedText(); if (selection != null) { return new AttributedString(selection).getIterator(); } else { return null; } } // --- DocumentListener methods --- public void changedUpdate(DocumentEvent e) { latestCommittedTextStart = latestCommittedTextEnd = null; } public void insertUpdate(DocumentEvent e) { latestCommittedTextStart = latestCommittedTextEnd = null; } public void removeUpdate(DocumentEvent e) { latestCommittedTextStart = latestCommittedTextEnd = null; } } // // Replaces the current input method (composed) text according to // the passed input method event. This method also inserts the // committed text into the document. // private void replaceInputMethodText(InputMethodEvent e) { int commitCount = e.getCommittedCharacterCount(); AttributedCharacterIterator text = e.getText(); int composedTextIndex; // old composed text deletion Document doc = getDocument(); if (composedTextExists()) { try { doc.remove(composedTextStart.getOffset(), composedTextEnd.getOffset() - composedTextStart.getOffset()); } catch (BadLocationException ble) {} composedTextStart = composedTextEnd = null; composedTextAttribute = null; composedTextContent = null; } if (text != null) { text.first(); int committedTextStartIndex = 0; int committedTextEndIndex = 0; // committed text insertion if (commitCount > 0) { // Remember latest committed text start index committedTextStartIndex = caret.getDot(); // Need to generate KeyTyped events for the committed text for components // that are not aware they are active input method clients. if (shouldSynthensizeKeyEvents()) { for (char c = text.current(); commitCount > 0; c = text.next(), commitCount--) { KeyEvent ke = new KeyEvent(this, KeyEvent.KEY_TYPED, EventQueue.getMostRecentEventTime(), 0, KeyEvent.VK_UNDEFINED, c); processKeyEvent(ke); } } else { StringBuilder strBuf = new StringBuilder(); for (char c = text.current(); commitCount > 0; c = text.next(), commitCount--) { strBuf.append(c); } // map it to an ActionEvent mapCommittedTextToAction(strBuf.toString()); } // Remember latest committed text end index committedTextEndIndex = caret.getDot(); } // new composed text insertion composedTextIndex = text.getIndex(); if (composedTextIndex < text.getEndIndex()) { createComposedTextAttribute(composedTextIndex, text); try { replaceSelection(null); doc.insertString(caret.getDot(), composedTextContent, composedTextAttribute); composedTextStart = doc.createPosition(caret.getDot() - composedTextContent.length()); composedTextEnd = doc.createPosition(caret.getDot()); } catch (BadLocationException ble) { composedTextStart = composedTextEnd = null; composedTextAttribute = null; composedTextContent = null; } } // Save the latest committed text information if (committedTextStartIndex != committedTextEndIndex) { try { latestCommittedTextStart = doc. createPosition(committedTextStartIndex); latestCommittedTextEnd = doc. createPosition(committedTextEndIndex); } catch (BadLocationException ble) { latestCommittedTextStart = latestCommittedTextEnd = null; } } else { latestCommittedTextStart = latestCommittedTextEnd = null; } } } private void createComposedTextAttribute(int composedIndex, AttributedCharacterIterator text) { Document doc = getDocument(); StringBuilder strBuf = new StringBuilder(); // create attributed string with no attributes for (char c = text.setIndex(composedIndex); c != CharacterIterator.DONE; c = text.next()) { strBuf.append(c); } composedTextContent = strBuf.toString(); composedTextAttribute = new SimpleAttributeSet(); composedTextAttribute.addAttribute(StyleConstants.ComposedTextAttribute, new AttributedString(text, composedIndex, text.getEndIndex())); } /** * Saves composed text around the specified position. * * The composed text (if any) around the specified position is saved * in a backing store and removed from the document. * * @param pos document position to identify the composed text location * @return {@code true} if the composed text exists and is saved, * {@code false} otherwise * @see #restoreComposedText * @since 1.7 */ protected boolean saveComposedText(int pos) { if (composedTextExists()) { int start = composedTextStart.getOffset(); int len = composedTextEnd.getOffset() - composedTextStart.getOffset(); if (pos >= start && pos <= start + len) { try { getDocument().remove(start, len); return true; } catch (BadLocationException ble) {} } } return false; } /** * Restores composed text previously saved by {@code saveComposedText}. * * The saved composed text is inserted back into the document. This method * should be invoked only if {@code saveComposedText} returns {@code true}. * * @see #saveComposedText * @since 1.7 */ protected void restoreComposedText() { Document doc = getDocument(); try { doc.insertString(caret.getDot(), composedTextContent, composedTextAttribute); composedTextStart = doc.createPosition(caret.getDot() - composedTextContent.length()); composedTextEnd = doc.createPosition(caret.getDot()); } catch (BadLocationException ble) {} } // // Map committed text to an ActionEvent. If the committed text length is 1, // treat it as a KeyStroke, otherwise or there is no KeyStroke defined, // treat it just as a default action. // private void mapCommittedTextToAction(String committedText) { Keymap binding = getKeymap(); if (binding != null) { Action a = null; if (committedText.length() == 1) { KeyStroke k = KeyStroke.getKeyStroke(committedText.charAt(0)); a = binding.getAction(k); } if (a == null) { a = binding.getDefaultAction(); } if (a != null) { ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, committedText, EventQueue.getMostRecentEventTime(), getCurrentEventModifiers()); a.actionPerformed(ae); } } } // // Sets the caret position according to the passed input method // event. Also, sets/resets composed text caret appropriately. // private void setInputMethodCaretPosition(InputMethodEvent e) { int dot; if (composedTextExists()) { dot = composedTextStart.getOffset(); if (!(caret instanceof ComposedTextCaret)) { if (composedTextCaret == null) { composedTextCaret = new ComposedTextCaret(); } originalCaret = caret; // Sets composed text caret exchangeCaret(originalCaret, composedTextCaret); } TextHitInfo caretPos = e.getCaret(); if (caretPos != null) { int index = caretPos.getInsertionIndex(); dot += index; if (index == 0) { // Scroll the component if needed so that the composed text // becomes visible. try { Rectangle d = modelToView(dot); Rectangle end = modelToView(composedTextEnd.getOffset()); Rectangle b = getBounds(); d.x += Math.min(end.x - d.x, b.width); scrollRectToVisible(d); } catch (BadLocationException ble) {} } } caret.setDot(dot); } else if (caret instanceof ComposedTextCaret) { dot = caret.getDot(); // Restores original caret exchangeCaret(caret, originalCaret); caret.setDot(dot); } } private void exchangeCaret(Caret oldCaret, Caret newCaret) { int blinkRate = oldCaret.getBlinkRate(); setCaret(newCaret); caret.setBlinkRate(blinkRate); caret.setVisible(hasFocus()); } /** * Returns true if KeyEvents should be synthesized from an InputEvent. */ private boolean shouldSynthensizeKeyEvents() { if (!checkedInputOverride) { checkedInputOverride = true; needToSendKeyTypedEvent = !isProcessInputMethodEventOverridden(); } return needToSendKeyTypedEvent; } // // Checks whether the client code overrides processInputMethodEvent. If it is overridden, // need not to generate KeyTyped events for committed text. If it's not, behave as an // passive input method client. // private boolean isProcessInputMethodEventOverridden() { if (overrideMap == null) { overrideMap = Collections.synchronizedMap(new HashMap<String, Boolean>()); } Boolean retValue = overrideMap.get(getClass().getName()); if (retValue != null) { return retValue.booleanValue(); } Boolean ret = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { public Boolean run() { return isProcessInputMethodEventOverridden( JTextComponent.this.getClass()); } }); return ret.booleanValue(); } // // Checks whether a composed text in this text component // boolean composedTextExists() { return (composedTextStart != null); } // // Caret implementation for editing the composed text. // class ComposedTextCaret extends DefaultCaret implements Serializable { Color bg; // // Get the background color of the component // public void install(JTextComponent c) { super.install(c); Document doc = c.getDocument(); if (doc instanceof StyledDocument) { StyledDocument sDoc = (StyledDocument)doc;