-
Notifications
You must be signed in to change notification settings - Fork 236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correct InputMethodTextChanged Event Handling #980
Comments
I have extracted the code needed to do this. As for InputMethodAttributes, this is too complicated and not necessary, I just removed it. import org.fxmisc.richtext.CodeArea;
import javafx.scene.input.InputMethodEvent;
import javafx.scene.input.InputMethodTextRun;
public class Setup {
private int imlength;
private int imstart;
public void setOnInputMethodTextChanged(CodeArea area){
area.setOnInputMethodTextChanged(event -> {
handleInputMethodEvent(event,area);
});
}
public void handleInputMethodEvent(InputMethodEvent event,CodeArea area) {
if (area.isEditable() && !area.isDisabled()) {
// remove previous input method text (if any) or selected text
if (imlength != 0) {
//removeHighlight(imattrs);
//imattrs.clear();
area.selectRange(imstart, imstart + imlength);
}
// Insert committed text
if (event.getCommitted().length() != 0) {
String committed = event.getCommitted();
area.replaceText(area.getSelection(), committed);
}
// Replace composed text
imstart = area.getSelection().getStart();
StringBuilder composed = new StringBuilder();
for (InputMethodTextRun run : event.getComposed()) {
composed.append(run.getText());
}
area.replaceText(area.getSelection(), composed.toString());
imlength = composed.length();
if (imlength != 0) {
int pos = imstart;
for (InputMethodTextRun run : event.getComposed()) {
int endPos = pos + run.getText().length();
//createInputMethodAttributes(run.getHighlight(), pos, endPos);
pos = endPos;
}
//addHighlight(imattrs, imstart);
// Set caret position in composed text
int caretPos = event.getCaretPosition();
if (caretPos >= 0 && caretPos < imlength) {
area.selectRange(imstart + caretPos, imstart + caretPos);
}
}
}
}
} |
Thanks for doing this and sharing. I cribbed the same code but had no way of testing it, or rather didn't know how to. area.setInputMethodRequests(new InputMethodRequests()
{
@Override public Point2D getTextLocation(int offset) {
int pos = getSelection().getStart() + offset;
Bounds charBounds = getCharacterBoundsOnScreen( pos, pos ).get();
Point2D location = new Point2D( charBounds.getMinX(), charBounds.getMaxY() );
return location;
}
@Override public int getLocationOffset(int x, int y) {
return 0;
}
@Override public void cancelLatestCommittedText() {}
@Override public String getSelectedText() {
IndexRange selection = getSelection();
return getText(selection.getStart(), selection.getEnd());
}
}); Depending on your feedback, I can maybe include this all into the next release of RichTextFX. |
According to #146, a new class should be created which implements InputMethodRequests. Here is the code I have tested okay: import java.util.Optional;
import org.fxmisc.richtext.CodeArea;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.input.InputMethodEvent;
import javafx.scene.input.InputMethodRequests;
import javafx.scene.input.InputMethodTextRun;
public class Setup {
private int imlength;
private int imstart;
public void setInputMethodRequests(CodeArea area){
InputMethodRequestsObject imRequests = new InputMethodRequestsObject(area);
area.setInputMethodRequests(imRequests);
}
public void setOnInputMethodTextChanged(CodeArea area){
area.setOnInputMethodTextChanged(event -> {
handleInputMethodEvent(event,area);
});
}
public int getimlength(){
return imlength;
}
public void handleInputMethodEvent(InputMethodEvent event,CodeArea area) {
if (area.isEditable() && !area.isDisabled()) {
// remove previous input method text (if any) or selected text
if (imlength != 0) {
//removeHighlight(imattrs);
//imattrs.clear();
area.selectRange(imstart, imstart + imlength);
}
// Insert committed text
if (event.getCommitted().length() != 0) {
String committed = event.getCommitted();
area.replaceText(area.getSelection(), committed);
}
// Replace composed text
imstart = area.getSelection().getStart();
StringBuilder composed = new StringBuilder();
for (InputMethodTextRun run : event.getComposed()) {
composed.append(run.getText());
}
area.replaceText(area.getSelection(), composed.toString());
imlength = composed.length();
if (imlength != 0) {
int pos = imstart;
for (InputMethodTextRun run : event.getComposed()) {
int endPos = pos + run.getText().length();
//createInputMethodAttributes(run.getHighlight(), pos, endPos);
pos = endPos;
}
//addHighlight(imattrs, imstart);
// Set caret position in composed text
int caretPos = event.getCaretPosition();
if (caretPos >= 0 && caretPos < imlength) {
area.selectRange(imstart + caretPos, imstart + caretPos);
}
}
}
}
public class InputMethodRequestsObject implements InputMethodRequests {
InputMethodRequestsObject(CodeArea codeArea){
area=codeArea;
}
public CodeArea area;
@Override
public
String getSelectedText() {
return area.getSelectedText();
}
@Override
public
int getLocationOffset(int x, int y) {
return 0;
}
@Override
public
void cancelLatestCommittedText() {
}
@Override
public
Point2D getTextLocation(int offset) {
// a very rough example, only tested under macOS
Optional<Bounds> caretPositionBounds = area.getCaretBounds();
if (caretPositionBounds.isPresent()) {
Bounds bounds = caretPositionBounds.get();
return new Point2D(bounds.getMaxX() - 5, bounds.getMaxY());
}
throw new NullPointerException();
}
}
} |
Thanks a lot @xulihang, I'll submit a PR in the next couple of days or so .... |
The workaround in the #146 works but it does not handle the InputMethodTextChanged event perfectly.
I searched around javafx's code and found how it is done for TextInputControl.
https://github.com/openjdk/jfx/blob/dd22cd2d97d4bfc305e44f2e77b4c104c62ff31f/modules/javafx.controls/src/main/java/javafx/scene/control/skin/TextInputControlSkin.java#L693
The text was updated successfully, but these errors were encountered: