SWT の StyledText について調べたまとめ

SWT の StyledText は、簡単に言えば指定した範囲に任意の色を付けられるテキスト編集コントロール

Eclipse のエディタも、上位にドキュメントフレームワークがかぶさってはいるものの、基本的にこのコントロールが使用されている。

この StyledText は、Canvas を継承していて、つまり自在に描画を行っているので、見た目にはマルチプラットフォームの影響を受けないようになっている。


さて、この StyledText は、行の折り返しという点で問題があることがわかった。

まず、StyledText 内でテキストのレイアウトを調整しているのは、TextLayout というクラスだ。このクラスはカーソルの描画や移動、描画ヒットテスト、ワードラッピング、アラインメント、タブ展開、行の折り返しなどの役割を担当していて、中身はグラフィックコンテキストへの描画コードがびっしり実装されている。

そして TextLayout を現在描画される領域の行数分だけ配列で保持しているのが StyledTextRenderer というクラス。StyledText はこの StyledTextRenderer をインスタンスとして保持している。ただし、StyledTextRenderer はパッケージプライベートで SWT API には存在しない。

どういうことかと言うと、ユーザコードは StyledText 経由で、TextLayout に直接アクセスすることができない。StyledText#setWordWrap(boolean) というメソッドが用意されてはいるが、これは TextLayout のワードラッピングを行うかどうかだけしか設定できず、以下のように画面端で折り返す、ということができない。

幸い StyledText は final ではなく、renderer フィールドはパッケージプライベートなので、StyledText を継承した MyStyledText を作成し、StyledText と同じパッケージにすることでアクセスすることは可能ではある。ただし、SWT とユーザコードがそれぞれ独立した JAR になっている場合、違う JAR で同一のパッケージにして、かつパッケージスコープのフィールドやクラスにアクセスすると SecurityException が発生するため、SWT をばらして自分の JAR に入れるなどしなければならない。

できなくはなくはない、ぐらいか。SWT が更新された場合などを考慮すると、全くおすすめできない。

ちなみに Eclipse は任意の場所を折り返しヒントとして設定はできるものの、画面端で折り返す、という機能が備わっていない。プラグインなどのオレオレエディタで無理やり StyledText#setWordWrap(true) を用いて折り返し設定すると、エディタがおかしな挙動をする。

追記

どうやら TextLayout#setJustify(boolean) は、折り返しまでで描画可能な文字をキツキツに詰めて描画するのではなく、ワープロのように文字間隔をあけつつ、右側に余白ができないようにするという機能のようだ。全くエディタ向きではないな。

メソッド名や最初のスクリーンキャプチャで気がつけよ、という感じだが。