AIR APIがサポートするメニュー
デスクトップアプリケーションには、インタフェースの一部として独自のメニューを備えているものが多くあります。AIRアプリケーションにもメニューAPIが用意されており、OSネイティブのメニューを利用できます。今回はメニューの実装方法について解説します。
AIRアプリケーションがサポートしているメニューには次のものがあります。
アプリケーションメニュー(Mac OS Xのみ)
ウィンドウメニュー(Windowsのみ)
Dockアイコンメニュー(Mac OS Xのみ)
システムトレイアイコンメニュー(Windowsのみ)
コンテキストメニュー
ポップアップメニュー
これらのメニューは表示場所こそ違うものの、作成方法はすべて共通です。例えば、同じ内容のメニューをアプリケーションメニューとDockメニューで使いたい、という場合でも簡単に実装できます。
メニューの構成
では、メニューの構成について見ていきましょう。メニューの作成には、NativeMenuクラスとNativeMenuItemクラス(いずれもflash.displayパッケージ)を使用します。メニューの個々のアイテムにあたるNativeMenuItemオブジェクトと、それらのコンテナとなるNativeMenuオブジェクトで1セットです。サブメニューが必要であれば、その分だけセットを作ります。図にすると次のようなイメージです。
メニューの構成
NativeMenuItemオブジェクトは通常のコマンドとして使う他に、必要に応じてセパレータにしたり、サブメニューにすることができます。
なお、アプリケーションメニューおよびウィンドウメニューでは、ルートとなるNativeMenuオブジェクトの直下をサブメニューにする必要があります。いきなりコマンドやセパレータを追加しないよう注意してください。
メニューの作成とアサイン
実際にメニューを作成してみましょう。Mac OS Xではアプリケーションメニュー、Windowsではウィンドウメニューとして表示されるようにします。ウィンドウメニューはシステムクロームでのみ有効です。次のサンプルでは[File]メニューを作成し、その下に[Exit]メニューを追加します。
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="buildMenu()">
<mx:Script>
<![CDATA[
private function buildMenu():void {
var rootMenu:NativeMenu = new NativeMenu();
var fileMenu:NativeMenuItem = rootMenu.addSubmenu(new NativeMenu(), "File");
var exitMenu:NativeMenuItem = new NativeMenuItem("Exit");
fileMenu.submenu.addItem(exitMenu);
if (Shell.supportsMenu) {
Shell.shell.menu = rootMenu;
} else if (NativeWindow.supportsMenu) {
stage.nativeWindow.menu = rootMenu;
}
}
]]>
</mx:Script>
</mx:WindowedApplication>
まず、メニューのルートとなるNativeMenuオブジェクトを作成し、addSubmenu()メソッドを使って"File"というサブメニューを追加しています。addSubmenu()の第1パラメータはサブメニューとして使うNativeMenuオブジェクトです。サブメニューもこれから定義するので、新規オブジェクトを渡しています。第2パラメータがメニューのラベルです。
サブメニューの追加は、addSubmenu()メソッドの代わりにaddItem()メソッドでも可能です。その場合は、NativeMenuItemオブジェクトのsubmenuプロパティにサブメニューとなるNativeMenuオブジェクトを指定します。
var fileMenu:NativeMenuItem = new NativeMenuItem("File");
fileMenu.submenu = new NativeMenu();
rootMenu.addItem(fileMenu);
次に、[File]メニューの下に表示される[Exit]メニューを作成しています。"Exit"というラベルのNativeMenuItemオブジェクトを作成して[File]メニューのsubmenuプロパティに追加するだけです。
最後に、作成したメニューをアプリケーションにアサインします。Mac OS XのアプリケーションメニューであればShell.shell.menuプロパティに、Windowsのウィンドウメニューであればstage.nativeWindow.menuプロパティにアサインする必要があります。この判別に利用しているのがShell.supportsMenuプロパティとNativeWindow.supportsMenuプロパティです。前者はアプリケーションメニューをサポートしている場合にtrueとなり、後者はウィンドウメニューをサポートしている場合にtrueとなります。これでメニューが表示されるようになりました。
Mac OS XのアプリケーションメニューとWindowsのウィンドウメニュー
様々なタイプのメニュー
冒頭で紹介したように、アプリケーションメニューやウィンドウメニュー以外でも同様のメニューを表示できます。先のサンプルのアサイン部分だけを変更して確認してみましょう。Mac OS XのDockアイコンメニューとWindowsのシステムトレイアイコンメニューに表示するには、次のように変更します。
if (Shell.supportsDockIcon) {
var dockIcon:DockIcon = Shell.shell.icon as DockIcon;
dockIcon.menu = rootMenu;
} else if (Shell.supportsSystemTrayIcon) {
var sysTrayIcon:SystemTrayIcon = Shell.shell.icon as SystemTrayIcon;
sysTrayIcon.bitmaps = [new BitmapData(16, 16, false, 0xff0000)];
sysTrayIcon.menu = rootMenu;
}
どちらの場合も結果的にはShell.shell.icon.menuプロパティにアサインするのですが、サポートしているアイコンのタイプによってShell.shell.iconプロパティの値が異なる点に注意してください。Dockアイコンの場合はDockIcon.menuプロパティ、システムトレイアイコンの場合はSystemTrayIcon.menuプロパティにメニューをアサインすることになります。この判別にはShell.supportsDockIconプロパティとShell.supportsSystemTrayIconプロパティを使います。前者がtrueの場合はDockアイコンをサポートしており、後者がtrueの場合はシステムトレイアイコンをサポートしています。なお、ここではシステムトレイアイコンのイメージとして16×16の赤い矩形を指定しています。
Mac OS XのDockアイコンメニューとWindowsのシステムトレイアイコンメニュー
コンテキストメニューとして使いたい場合は、任意のインタラクティブオブジェクトのcontextMenuプロパティにアサインするだけです。すると、そのオブジェクト上でコンテキストメニューを表示したときに指定のメニューが表示されるようになります。
myMovieClip.contextMenu = rootMenu;
ポップアップメニューとして使いたい場合はこれまでと異なり、NativeMenu.display()メソッドを使います。第1パラメータにはメニューを表示するステージを、第2/第3パラメータにはステージを基準としたメニューの座標を指定します。
rootMenu.display(stage, 32, 32);
※ ただし、確認した範囲ではMac版での座標指定は無視され、マウス座標に表示されます。
セパレータの挿入
メニューのアイテムの間にはセパレータを挿入できます。セパレータもNativeMenuItemオブジェクトです。NativeMenuItemコンストラクタの第2パラメータにtrueを指定すると、そのアイテムはセパレータになります。
var separator:NativeMenuItem = new NativeMenuItem("", true);
fileMenu.submenu.addItem(separator);
メニュー選択時のイベント
ここまでメニューの表示について見てきましたが、表示するだけではメニューの役割を果たしません。選択されたときに発生するイベントを受けて、何らかのアクションを起こす必要があります。メニューの選択に関するイベントは次の2つがあります(flash.eventsパッケージ) 。
イベント 発生タイミング
Event.DISPLAYING メニューが表示される直前
Event.SELECT メニューが選択された時
Event.DISPLAYINGは、ユーザがメニューをクリックして表示しようとした時に発生しますが、まだメニューは表示されていない状態です。例えば、「 最近開いたドキュメント」のように動的に内容を変更したいメニューに利用できます。実際に選択された時はEvent.SELECTが発生します。次のサンプルは、[File]メニューから[Exit]を選択するとアプリケーションを終了します。
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="buildMenu()">
<mx:Script>
<![CDATA[
private function buildMenu():void {
var rootMenu:NativeMenu = new NativeMenu();
var fileMenu:NativeMenuItem = rootMenu.addSubmenu(new NativeMenu(), "File");
var exitMenu:NativeMenuItem = new NativeMenuItem("Exit");
exitMenu.addEventListener(Event.SELECT, selectExitHandler);
fileMenu.submenu.addItem(exitMenu);
if (Shell.supportsMenu) {
Shell.shell.menu = rootMenu;
} else if (NativeWindow.supportsMenu) {
stage.nativeWindow.menu = rootMenu;
}
}
private function selectExitHandler(e:Event):void {
Shell.shell.exit();
}
]]>
</mx:Script>
</mx:WindowedApplication>
メニューのオン/オフ
NativeMenuItemクラスには、checkedプロパティとenabledプロパティがあります。前者はメニューのアイテムがチェックされているかどうかを示すもので、trueにするとアイテムにチェックマークが付きます。後者はメニューのアイテムが現在選択可能かどうかを示すもので、falseにするとアイテムがグレーアウトの状態になります。
次のサンプルは、先のコードに[Lock]メニューを追加しています。[Lock]メニューを選択する度にチェックの有無が切り替わり、チェックが付いているときは[Exit]メニューを無効にします。
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="buildMenu()">
<mx:Script>
<![CDATA[
private var _exitMenu:NativeMenuItem;
private function buildMenu():void {
var rootMenu:NativeMenu = new NativeMenu();
var fileMenu:NativeMenuItem = rootMenu.addSubmenu(new NativeMenu(), "File");
var lockMenu:NativeMenuItem = new NativeMenuItem("Lock");
lockMenu.addEventListener(Event.SELECT, selectLockHandler);
fileMenu.submenu.addItem(lockMenu);
_exitMenu = new NativeMenuItem("Exit");
_exitMenu.addEventListener(Event.SELECT, selectExitHandler);
fileMenu.submenu.addItem(_exitMenu);
if (Shell.supportsMenu) {
Shell.shell.menu = rootMenu;
} else if (NativeWindow.supportsMenu) {
stage.nativeWindow.menu = rootMenu;
}
}
private function selectLockHandler(e:Event):void {
e.target.checked = !e.target.checked;
_exitMenu.enabled = !e.target.checked;
}
private function selectExitHandler(e:Event):void {
Shell.shell.exit();
}
]]>
</mx:Script>
</mx:WindowedApplication>
メニューのチェックや無効化が可能
メニューにデータを設定する
NativeMenuItemクラスのdataプロパティを使うと、メニューアイテムに任意の値を持たせることができます。次のサンプルでは[Help]メニューの下に[LiveDocs]メニューを設け、そのdataプロパティにURLを持たせてあります。[LiveDocs]メニューが選択されると、dataプロパティからURLを取得してページにジャンプします。
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="buildMenu()">
<mx:Script>
<![CDATA[
private function buildMenu():void {
var rootMenu:NativeMenu = new NativeMenu();
var helpMenu:NativeMenuItem = rootMenu.addSubmenu(new NativeMenu(), "Help");
var docMenu:NativeMenuItem = new NativeMenuItem("LiveDocs");
docMenu.data = "http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/";
docMenu.addEventListener(Event.SELECT, selectDocHandler);
helpMenu.submenu.addItem(docMenu);
if (Shell.supportsMenu) {
Shell.shell.menu = rootMenu;
} else if (NativeWindow.supportsMenu) {
stage.nativeWindow.menu = rootMenu;
}
}
private function selectDocHandler(e:Event):void {
navigateToURL(new URLRequest(e.target.data));
}
]]>
</mx:Script>
</mx:WindowedApplication>
dataプロパティには様々なオブジェクトを設定できるので、例えばドキュメントに関するメニューにFileオブジェクトを設定しておくといった使い方ができます。