-
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
Add support for Input Methods #146
Comments
Hi Jordan, |
Sorry, I only meant input methods. I'm using a US keyboard layout, but if I wanted to quickly hop over to a Spanish/Greek/Chinese input method, it won't register. |
I don't have any experience using input methods. A good place to start would be to look at what JavaFX's TextArea does. |
I looked into TextArea and input methods in general. Here's what I found. First, there's a specific Event for this: InputMethodEvent. |
The problem is that an area's InputMethodRequests value is null. Any InputMethodEvent won't be registered until this gets taken care of. My workaround was to "steal" a TextArea's InputMethodRequests (an instance of TextInputControlSkin). After trying a few things, I just decided to try a blank object that implemented InputMethodRequests. Turns out it works. It doesn't insert the text that a user is composing before replacing it with the actual text inserted, but it does allow a user to change Input Methods and insert whatever text they desire (basic functionality). Here's the code below: class InputMethodRequestsObject implements InputMethodRequests {
@Override
String getSelectedText() {
return ""
}
@Override
int getLocationOffset(int x, int y) {
return 0
}
@Override
void cancelLatestCommittedText() {
}
@Override
Point2D getTextLocation(int offset) {
return new Point2D(0, 0)
}
}
import static groovyx.javafx.GroovyFX.start
start {
stage(id: "stage", title: "Hello", primary: true, visible: true) {
scene(width: 500, height: 500) {
vbox(id: "vbox")
}
}
def richArea = new InlineCssTextArea()
richArea.setInputMethodRequests(new InputMethodRequestsObject())
richArea.setOnInputMethodTextChanged({ e ->
if (e.committed != "") {
richArea.insertText(richArea.caretPosition, e.committed)
}
})
vbox.getChildren().add(richArea)
} |
Thanks for posting back your workaround! |
No problem! |
I'm reopening this to add official support for this out-of-box. |
As a Chinese user, I guess people who use the most commonly used input method of China, Pinyin, would like to see the candidate window (for picking possible words) just below the caret. Below is a sample input of Chinese characters “你好” (Greetings) using Pinyin in macOS Pages, the candidate window appears just below the caret and before the first input character (which is also the initial caret position). The workaround above works pretty well! But it doesn't show the candidate window in the place where the candidate window should be. To fix this, @JordanMartinez points out that @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();
} |
Hi there, I tested the workaround and it works. Great thanks. I modified the code a bit to replace selected text with text commited richArea.setOnInputMethodTextChanged({ e ->
if (e.committed != "") {
richArea.replaceSelection("")
richArea.insertText(richArea.caretPosition, e.committed)
}
}) As for the candidate window, I found that only macOS can display it correctly. Native TextArea has this problem as well. The candidate window is at the lower-right under Windows 10 and is at the lower-left area of the application under Linux. I tested on JRE 1.8. |
Another problem is that the composed text is not showing correctly. I then changed the TextChanged Event (code is in B4X) to show the composed text. But it is not underlined as above. Sub InputMethodTextChanged_Event(MethodName As String,Args() As Object) As Object 'ignore
Dim e As JavaObject=Args(0)
JO.RunMethod("replaceSelection",Array(""))
Dim startIndex,endIndex As Int
startIndex=JO.RunMethod("getCaretPosition",Null)-previousComposedText.Length
endIndex=JO.RunMethod("getCaretPosition",Null)
JO.RunMethod("deleteText",Array(startIndex, endIndex))
If e.RunMethod("getCommitted",Null)<>"" Then
JO.RunMethod("insertText",Array(JO.RunMethod("getCaretPosition",Null), e.RunMethod("getCommitted",Null)))
previousComposedText=""
Else
Dim sb As StringBuilder
sb.Initialize
Dim composed As List=e.RunMethod("getComposed",Null)
For Each run As JavaObject In composed
sb.Append(run.RunMethod("getText",Null))
Next
previousComposedText=sb.ToString
JO.RunMethod("insertText",Array(JO.RunMethod("getCaretPosition",Null), sb.ToString))
End If
End Sub |
Hello Tomas,
What would be the best way to incorporate multiple language inputs? What would be the best way to handle this?
I think languages like Spanish or Greek wouldn't be too hard to do. One could remap the KeyTyped events to insert the correct letter in their respective alphabets.
For other languages (like Chinese using PinYin or some other input method), this wouldn't work. For my purposes, I don't need support for a more complex language, just the simpler ones. However, finding a way to incorporate the system's input method would prevent each developer from having to create 1) a separate KeyTyped events remapping for each language used and 2) a method to switch from one keyboard layout to another, depending on what the user needs.
The text was updated successfully, but these errors were encountered: