Window の Modal 処理
10.8 までの MacRuby では、Window にひも付けされた(?)別の Window や Panel を表示させる方法は、NSApplication の
beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:
を使って次のように処理していた。
def showPanel(sender)
NSApp.beginSheet(@panel,
modalForWindow: @window,
modalDelegate: self,
didEndSelector: "sheetDidEnd:returnCode:contextInfo:",
contextInfo: nil)
end
def sheetDidEnd(sheet, returnCode: returnCode, contextInfo: info)
sheet.close
end
def closePanelModal(sender)
NSApp.endSheet(@panel)
必要なら、ここにパネルを閉じた後の処理を書く。
end
ここでは、まず、showPanel(sender) というメソッドの中で @panel という outlet のパネルを @window にひも付けて表示させている。これで、@panel 上にボタンを配置して、closePanelModal(sender) (任意の名前)というメソッドを呼び出して、NSApplication の endSheet(panel) でパネルを閉じると、seetDidEnd:returnCode:contextInfo: というメソッドを呼び出して、modal が終わる、という感じ。seetDidEnd:returnCode:contextInfo: は、3 つ情報が返ってくるということで、名前を変えても多分動く。didEndSelector: で指定したものになる。ただ、細かいことはあまりよくわかっていないのだけれども。
ただ、このメソッドは、10.9 で deprecated になったためか、RubyMotion で、10.9 上ではエラーが出てちゃんと動かない(どうも、endSheet: あたりで問題があるようだが、はっきしない)。いずれはなおるのかもしれないが、これ以降のことも考えて、別の方法を探った方がいいだろうということで、代替手段を探した。
10.9 からは、NSWindow のメソッドに beginSheet:completionHandler: というのが追加された。10.9 の RubyMotion で、上の処理と同じことをしようとすると、次のような感じになる。
def showPanel(sender)
@window.beginSheet(@panel,completionHandler:Proc.new { |returnCode| })
end
def closePanelModal(sender)
@window.endSheet(@panel)
end
ここでも、表示させた @panel 上にボタンを配置して、closePanelModal(sender) (任意の名前)というメソッドを割り当てて、NSWindow の endSheet(panel) でパネルを閉じる。completionHandler のループの中か、closePanelModal(sender) に、パネルを閉じた後の処理を書く。ちなみに、returnCode には、-1000 が返ってきた。
ただ、問題は、この方法は 10.9 じゃないと動かない。10.8 以前でも動くようにするには、OS のバージョンを判別して別の処理をしないとだめそうだ。
現在は、あまりスマートな方法ではないけど、app フォルダの中に config というフォルダを作り、constants.rb というファイルで OS のバージョンをチェックして、グローバル変数を用意している。OS X 10.9 が KCFCoreFoundationVersionNumber で 855.00 なので、それ未満の場合をチェックしている。
if KCFCoreFoundationVersionNumber < 855.00
$VerCheck = false
else
$VerCheck = true
end
def openModalPanel(sender)
NSApp.runModalForWindow(@panel)
end
def closeModalPanel(sender)
NSApp.stopModal
@panel.orderOut(nil)
end
これは、OS のバージョンではなく、RubyMotion の問題のようなので、OS X 10.8 以前用には sheet ではなく、通常の modal window で対処している。panel を modal で開くには、NSApplication.sharedApplication (NSApp) の runModalForWindow(panel) で開き、処理した後にボタンなどで panel を閉じて実行するメソッドで stopModal で modal を終了させて、NSPanel/NSWindow の orderOut(sender) で panel を閉じている。