Thursday Jul 02, 2009

JavaFX 1.2とインプット・メソッド

JavaFX 1.2の機能と拡張(英語)の一つとして、インプットメソッドを扱うAPIが加わりました。JavaFX 1.2以前のリリースでは、シーングラフ中のNodeはインプットメソッドで確定された文字列のみを一連のKeyEventとして受け取る事しかできませんでしたが、JavaFX 1.2で新しく加わったAPIを使う事によりNodeはインプットメソッドの変換途中の文字列の情報も受け取れるようになり、アプリケーションが自由に変換途中の状態を表示できるようになります。

JavaFXでインプットメソッドがどのように動作するかという全体のデザインは、JavaのInput Method Frameworkとほぼ同様になっています。特に何もしない場合は(上に書いた通り)、Nodeは変換結果のみをKeyEventとして受け取りますが、NodeTextInput mixinをextendして実装した場合、インプットメソッドの変換途中の状態がアプリケーションが定義したonInputMethodTextChanged()InputMethodEventとして通知されます。簡単なコードサンプルを以下に示します。このクラスはCircleのサブクラスでInputMethodEventを受け取れるサンプルです。


class InputMethodCircle extends Circle, TextInput {
    override var onInputMethodTextChanged = 
        function (e:InputMethodEvent): Void {
            println(e);
        };
}

このサンプルはInputMethodEventが通知されるごとにコンソールにその内容を書き出します。

InputMethodEventには4つの変数があります。node変数はどのNodeでこのイベントが起きたか、composed変数は変換途中の文節を表すInputMethodTextRunのシーケンスを持ち、committedは確定文字列、caretPositioncomposedテキスト中のキャレット位置をそれぞれ表現しています。アプリケーションは通常InputMethodEventを受け取るとcomposedInputMethodTextRunにあるそれぞれの文節を指定されたInputMethodHighlightに応じて表示、committedで返された確定文字列をアプリケーションのテキストに挿入、また caretPositionで指定された位置にキャレットを表示します。

以下はInputMethodEventの内容を表示する別の簡単なサンプルです。サンプルの一行目にあるカラーサンプルは、それぞれの文節の色が示すアトリビュートを示しています ("U-R"が"unselected raw"ハイライト、"S-C"が"selected converted"といった具合です)。上にあげたサンプルよりもちょっとだけ視覚に訴えるようにしてみました。

もしお使いのOSにインプットメソッドがインストールされていない場合、Javaで書かれたインプットメソッドを使ってこのサンプルを試す事もできます。Javaインプットメソッドの使い方は 昔の記事を参照ください。

しかし、もしもあなたのアプリケーションでこの様な詳細な部分まで必要ない場合はどうすれば良いのでしょう?大丈夫。TextBox UIコントロールはこれらの仕組みを既に内部で実装しているので、TextBoxを使えばそれ以上何もしなくていいでしょう。

JavaFX 1.2 and input methods

One of the Features and Enhancements in JavaFX 1.2 is the API for dealing with input methods. Prior to the JavaFX 1.2 release, Nodes in a scene graph can only receive the result of the input method composition as a series of KeyEvents. With the new API introduced in JavaFX 1.2, Nodes can directly receive the input method composition information and do whatever they want with it.

The overall design of how the input methods work in JavaFX is pretty much analogous to the Input Method Framework in Java itself. By default, Nodes receive only the result of the input method composition through KeyEvents (as noted above), but once they extend the new TextInput mixin, then they are able to receive the whole input method composition information through the new InputMethodEvent, delivered in the user defined onInputMethodTextChanged() function. Here is a simple example of a Circle subclass that receives InputMethodEvent:


class InputMethodCircle extends Circle, TextInput {
    override var onInputMethodTextChanged = 
        function (e:InputMethodEvent): Void {
            println(e);
        };
}

The above code dumps the contents of InputMethodEvents to the console, whenever they are delivered.

An InputMethodEvent contains four variables, i.e., node on which this event has occurred, composed which is a sequence of InputMethodTextRun that represents the text in composition, committed which is the result of the composition, and caretPosition which designates the caret position inside the composed text. On receiving InputMethodEvents, applications would typically display the composed text with the visual feedback according to the InputMethodHighlight in each InputMethodTextRun, insert the committed text into applications text, and display the caret as suggested by caretPosition.

Here is another simple example that displays the contents of InputMethodEvents, with the color scheme shown at the top of the application ("U-R" denotes "unselected raw" highlight, and "S-C" for "selected converted" and so on). A little visualized version than the one above.

If you don't have input methods on your underlying operating system, you might want to try out input methods written in Java. How to use them are described in my old article.

HOWEVER, if you do not want to deal with such details, don't worry. The TextBox UI control is your friend. It has a built-in implementation for such behavior, so use it in your application and you can just call it a day :-)

Monday Jan 26, 2009

文字列リテラルのローカリゼーション記法がJavaFX Script言語リファレンスに。

JavaFX 1.0がリリースされてから既にしばらく経ちますが、ようやく"##"シンタックスについてのセクションをJavaFXランゲージリファレンスに追加できたのでblogでご紹介します。リファレンスの"String"タイプの章の"Localization of String Literal"の部分がそれです。基本的に以前紹介したプロポーザルのままです。

もし何かお気づきの点がありましたらコメントまで。

String literal localization in JavaFX Script Language Reference

It's been a while since JavaFX 1.0 was released. Now I finally had some time writing up a section in the JavaFX language reference about the "##" syntax. Take a look at the "String" type, and look for the section named "Localization of String Literal". It's basically based on the contents of the original syntax proposal.

If you have any comments, please leave them in this entry comment area. Thanks!

Thursday Jan 10, 2008

JavaFX Scriptの簡単なローカリゼーション機能

またまたしばらく間が空いてしまいましたが、ここ最近はずっとJavaFX Scriptの国際化についての仕事をしています。JavaFX ScriptはJavaをベースにしたスクリプト言語なわけで、もちろんJavaに本来備わっている国際化に関する機能はすべて使えるわけですが、JavaFX ScriptからいちいちJavaの機能を呼び出して国際化関連のことを行うのはスクリプト言語らしくないし、さらにJava言語とJavaFX言語が混在してバグの元になりかねません。そこでJavaFX言語の仕様策定中ということもあり、その中に入れてしまいたいのがリテラル文字列を簡単にローカライズできる仕組みです。ある文字列をローカライズする場合、Javaでは普通、

    import java.util.ResourceBundle;

    static final String GREETINGS_KEY = "HELLO_WORLD";

    String greetings;
    try {
        ResourceBundle rb = ResourceBundle.getBundle("foo.bar.resources.My_Resource");
        greetings = rb.getString(GREETINGS_KEY);
    } catch (MissingResourceException mre) {
        greetings = "Hello, World!";
    }

の様に書くと思いますが、いま模索中なのがGNUのgettext()関数のように、引数となる文字列がそのままデフォルトの翻訳になるような仕組みです。上のコードをそのシンタックスで表記すると、

    var greetings = ##"Hello, World!";

たったの一行。シンプルでしょ?ここで"##"はリテラル文字列に働く単項演算子のような役割をします。この演算子がつくと実行時にこのリテラル文字列"Hello, World!"をキーとして適当な翻訳を探します。お気づきの方もいると思いますが、PropertyResourceBundleはホワイトスペース' 'をデリミタとして解釈するため、実は"Hello, World!"はキーとはなり得ないんです。そこで提案したいのがJavaFX Script用の新しいリソースバンドルのフォーマット。このフォーマットは単純に次のようなフォームを取ります。

    <JavaFX string literal> = <JavaFX string literal>
e.g.,
    "Hello, World!" = "こんにちは、世界!"

さらにボーナスとして考えているのは、このFX propertiesのデフォルトのエンコーディングを"UTF-8"にしようというもの。これで今まで頭を痛めてきた"ISO-8859-1" & native2asciiの呪縛から解放されるでしょう。他のエンコーディングを指定したい場合は、ファイルの頭にCSS形式のエンコーディング宣言(@charset "<IANA defined charset name>";)を入れてあげればそれに従うようにします。

ただこの方式には問題が一つあり、スクリプト内に同じリテラル文字列があり、それぞれ別の翻訳をさせたい場合(例えば2つの"File"というリテラル文字列をそれぞれ名詞、動詞として翻訳したい場合)に困ってしまいます。この問題を解決するためにオプションとしてキーを明示的に指定できるようにしました。#[FILE_NOUN]"File"のように、大括弧でくくって明示的なキーを指定します。

まあこんな所ですが、プロポーザル(英語です)とプロトタイプ実装をPlanet JFX wikiに置いてみたんで、どうぞおためしください。それとコメント、感想もよろしく!

About

naotoj

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
News

No bookmarks in folder

Blogroll