2007年5月11日金曜日

自前Modal Window

警告パネルを表示して、ユーザからなにかしらの入力を待ち、それによってプログラムの振る舞いを変えたいことがある。例えば、ファイヤウォールのようなアプリケーションを作成して、あるサイトからのアクセスがあった場合に、そのサイトからのアクセスを許可するかどうかをユーザに訪ねる場合だ。

このとき、NSAlertではなく、NSWindowやNSPanelを拡張して自前のクラスを用意した場合に、ユーザの入力を待ちつつ自前クラスの処理を平行して行いたいのだが、どうやってユーザの入力を待つかがむずかしい。なぜならば、単純にwhileとsleepでまわすと、そのRunLoop内のすべての処理をblockしてしまうから。

解決方法は、そのクラスをmodalSessionにして、必要な処理はタイマで回す。その際、タイマは、NSModalPanelRunModeにも追加しておく。

(NSWindowを継承したクラス内)
--- init method

timer = [NSTimer timerWithTimeInterval:0.05 target:self selector:@selector(alertWindowAppear) userInfo:nil repeats: NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSModalPanelRunLoopMode];

--- modal method
NSModalSession session = [NSApp beginModalSessionForWindow:self];
int modalResult;
do {
modalResult = [NSApp runModalSession:session];
if (modalResult == NSOKButton) {
[NSApp abortModal];
[NSApp endModalSession:session];

// related processing here

} else if (modalResult == NSCancelButton) {
[NSApp abortModal];
[NSApp endModalSession:session];

// related processing here

}
} while (modalResult == NSRunContinuesResponse);

0 件のコメント: