目的
タイトルが長いけど、NSFontPanel (もしくは NSColorPanel)みたいな挙動をする NSPanelを作りたい。
メモ.appなんかでフォントパネルを操作してみると以下のような動きをする。
- アクティブなのは常にメインウィンドウ (タイトルバーの文字がグレーアウトしていない)
- パネルの上をクリックしてもパネルがアクティブにならない
- パネルのタイトルバーをクリックするとパネルがアクティブになる
- 非アクティブ状態でもパネル上のテーブルやボタンなどの部品は操作できる
これをどう作るか、という話
方法
大げさに書いているが実際のところは簡単だった。
- パネルのサブクラスを作る (MyPanelとか)
- インターフェースビルダで配置したパネルの Custom Classを MyPanelにする
- MyPanelの awakeFromNibの中などで setBecomesKeyOnlyIfNeeded: メソッドを呼ぶ
-(void)awakeFromNib
{
[self setBecomesKeyOnlyIfNeeded:YES];
}
これだけ。
http://cocoaapi.hatenablog.com/entry/00000226/recID37326 によれば
必要な時だけキーウインドウになるかを返します。
初期設定はNOを返します。
とのこと。
「アクティブなウィンドウ = キーウィンドウ」という理解でいいんだろうか。確かにキーイベントを受け取るのはアクティブなウィンドウだから合ってる気がする。
ソース
[TODO]
補足1
setBecomesKeyOnlyIfNeededは本来 NSViewの needsPanelToBecomeKeyメソッドと対で使うものらしい。
パネルがキーウインドウになるかを制御する
サブクラスでオーバーライドして使います。
「パネルの中にあるビューから要求を受けた時だけアクティブになる」ということ。今回は要求を出すビューがないからパネルがアクティブにならない。
フォントパネルの右上にあるフォントサイズ指定の NSTextFieldをクリックすると、パネルがアクティブになる。数値を入力するためにパネルがキーウィンドウになったということだが、おそらく NSTextFieldの needsPanelToBecomeKeyは YESを返すようになっているんだと推測できる。
補足2:カスタムビューをパネルに乗せるとき
この方法で独自のUI部品をパネルに載せて使いたいときは、NSViewの acceptsFirstMouseメソッドをオーバーライドする。これを使うことで、パネルのアクティブ化だけに使われていた最初のマウスイベントもビューに通知されるようになる。逆に、これを実装しとかないとUI部品に対するクリックイベントを拾ってもらえない。
-(BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
return YES;
}
アクティブでない時、マトリックスをマウスダウンしたときに呼ばれます。
サブクラスでオーバーライドします。YESを返すと、アクティブでない時、マトリックスをクリックすると、アプリケーションはアクティブになりウインドウは前面にきて、マトリックスがクリックされメッセージを送信します。NOを返すとアプリケーションはアクティブになり、ウインドウは前面になりますが、マトリックスをクリックしません。