2005-05-28

NSTokenField の使い方

post : 2005-05-28 11:00 |

NSTokenField の中身をプログラムから設定する方法。setTokenizingCharacterSet: で区切り文字を設定して setStringValue: すれば良いのかな、と思ったけどできなかった。答えは NSString が入った NSArray を作って setObjectValue: するのだった。ただし任意のオブジェクトの NSArray でも、delegate で - (NSString *)tokenField:(NStokenField *)tokenField displayStringForRepresentedObject:(id)representedObject を実装しておけば、ここで指定することができそうだ。
次は選択範囲を調べたい。NSTextField のサブクラスだから NSTextField の選択範囲を得るメソッドでできるかなと思ったんだけど、そもそも NSTextField の選択範囲を得るメソッドてあったっけ? NSText (NSTextView) からは selectedRange を取れるので、field editor から取得すればいいのか。いつ取得するかは、NSTextView の選択範囲が変わると、NSTextViewDidChangeSelectionNotification と delegate メソッドが投げられるのでそこでつかまえる。さて問題は、対象の NSTextView が field editor だということだ。

・NSControl(NSTokenField)の delegate で controlTextDidBeginEditing: をつかまえる
・Notification の userInfo から @"NSFieldEditor" を得る。これが対象の NSTextView
・その NSTextView の NSTextViewDidChangeSelectionNotification を addObserver
 (delegate はおそらく NSControl なので、delegate を乗っ取るのは良くなかろう)
・NSControl(NSTokenField)が controlTextDidEndEditing: したら removeObserver

delegate と Notification を駆使すればこういう手順になるが、非常に面倒くさい。NSTokenField をサブクラス化することで済ませた。
NSControl には - (void)textViewDidChangeSelection:(NSNotification *)note という隠しメソッドが実装されている。隠しメソッドというか、NSTextView の delegate メソッドだ。ここで何をやっているかというと、自身の cell が textViewDidChangeSelection: を respondsToSelector: するならメソッドを呼んでいる。なので NSTokenFieldCell をサブクラス化し、textViewDidChangeSelection: を実装すれば良い。あるいは、NSTokenField をサブクラス化し、textViewDidChangeSelection: をオーバーライド。僕はこっちを選んだ。

@implementation MyTokenField //NSTokenField のサブクラス
- (void)textViewDidChangeSelection:(NSNotification *)aNotification
{
    //いちおう super を呼ぶ
    [super textViewDidChangeSelection:aNotification];
    //[aNotification object] == NSTextField
    [[self delegate] myTokenField:self didChangeSelection:aNotification];
}
@end

MyTokenField の delegate で - (void)myTokenField:(MyTokenField*)ctl didChangeSelection:(NSNotification *)aNotification を実装しておけば、選択範囲が変化するたびに呼ばれ、[[aNotification object]selectedRange] で現在の選択範囲を取得できる。めでたしめでたし。
取得できる NSRange は、ひとつの token が length=1 となっており非常に使いやすい。4個目の token を選択している場合、selectedRange は{location=3, length=1} だ。

こんな感じ。 本来想定されている使い方じゃない気もしますが(笑)。
NSTokenField test

Trackback 現在、受付は中止しています

No Trackbacks

Comment

No Comments