【Flex】ポップアップメニュー


ブラウザでダウンロード
swf 上の右クリック
コンテキストメニューと呼ばれるメニューをカスタマイズ可能です。
Flex2 では、アプリケーションの下にあるルートでしか持てなかったようですが、
Flex3 では、コントロール・コンテナ毎に持つ事ができます。
最大数は、Flex2 の場合と同じ 15 とマニュアルに書かれていますが、
通常、そんなに多くは必要無いでしょう。

AIR ではさらに拡張されて、WEB 上では配列としてアクセスしていますが、
通常のメニューに対するようなメソッドが追加されています。

上記画面では、場所場所によって違ったコンテキストメニューが表示されます。
Form に設定しているメニューは、Form が完全透過の場合、その場所では
Application のメニューが表示されます。

ボタンやラベルは何も設定していないので、Form に設定したものが表示されています。


メニュー実装用の function を作成し、Application に対して実装しています。
他の メニューも、この addContextMenu を使用する事になります。

※ ちなみに、タイトルに "adobe" と言う文字が含まれるとメニューは作成されないようです
Parts.as
01.public var rootObject:Application;
02.public var param:Object;
03.public var adobe:String = "http://livedocs.adobe.com/flex/3_jp/langref/mx/";
04. 
05.// *********************************************************
06.// アプリケーションの初期化
07.// *********************************************************
08.public function initData():void {
09. 
10.    firebug("処理開始");
11. 
12.    // Root オブジェクト
13.    rootObject = Application(mx.core.Application.application);
14.    // パラメータをプロパティとして持つ Object を取得
15.    param = rootObject.parameters;
16. 
17.    // 初期フォーカス
18.    fld1.setFocus();
19. 
20.    // いかなるドメインからも OK
21.    Security.allowDomain("*");
22. 
23.    // コンテキストメニュー定義
24.    addContextMenu(
25.        rootObject,
26.        "Application : Flex3 リファレンスガイド",
27.        function():void {
28.            openUrl(
29.                adobe + "core/Application.html"
30.            );
31.        }
32.    );
33. 
34. 
35.    // ExternalInterface.call("console.open");
36.    // Alert.show("処理開始");
37.}
38. 
39.// *********************************************************
40.// ログ表示
41.// *********************************************************
42.public function firebug(data:Object):void {
43. 
44.    var fmt:DateFormatter = new DateFormatter();
45. 
46.    fmt.formatString = "YYYY/MM/DD HH:NN:SS";
47.    var logdt:String = fmt.format( new Date );
48. 
49.    ExternalInterface.call(
50.        "console.log", logdt,
51.        data+""
52.    );
53. 
54.}
55. 
56.// *********************************************************
57.// コンテキストメニュー追加
58.// *********************************************************
59.public function addContextMenu(
60.    target:Object,
61.    label:String,
62.    listener:Function
63.):void {
64. 
65.    var nativeMenu:ContextMenu;
66.    nativeMenu = new ContextMenu();
67.    nativeMenu.hideBuiltInItems();
68.    var menuItem:ContextMenuItem;
69.    menuItem = new ContextMenuItem(label);
70.    menuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,listener);
71.    nativeMenu.customItems.push(menuItem);
72.    target.contextMenu = nativeMenu;
73. 
74.}
75. 
76.// *********************************************************
77.// ブラウザで開く
78.// *********************************************************
79.public function openUrl(url:String):void {
80. 
81.    var req:URLRequest = new URLRequest(url);
82.    navigateToURL(req, "_blank");
83. 
84.}
ユーザーコントロール内部からの実装
このアプリケーション自体のクラス名である "Main" を使用して
addContextMenu を参照しています。本来はこのような記述はアプリケーション
依存となるので行いませんが、Popupmenu の実装サンプルとして行っています。
LboxText.mxml
01.<?xml version="1.0" encoding="utf-8"?>
02.<mx:TextInput
03.    xmlns:mx="http://www.adobe.com/2006/mxml"
04.    creationComplete="initControl(event)"
05.>
06. 
07.<mx:Script>
08.<![CDATA[
09. 
10.    import mx.managers.*;
11.    import mx.events.*;
12.    import mx.core.*;
13. 
14.    // *****************************************************
15.    // 初期処理
16.    // *****************************************************
17.    private function initControl(e:FlexEvent):void {
18. 
19.        // イベント追加
20.        this.addEventListener(FlexEvent.ENTER, focusControl);
21. 
22.        var rootObject:Main;
23.        // Root オブジェクト
24.        rootObject = Main(mx.core.Application.application);
25.        // コンテキストメニュー定義
26.        rootObject.addContextMenu(
27.            e.target,
28.            "TextInput : Flex3 リファレンスガイド",
29.            function():void {
30.                rootObject.openUrl(
31.                    rootObject.adobe + "controls/TextInput.html"
32.                );
33.            }
34.        );
35. 
36.    }
37. 
38.    // *************************************************
39.    // ENTER to TAB
40.    // *************************************************
41.    private function focusControl(event:FlexEvent):void{
42. 
43.        var fm:FocusManager = FocusManager(this.focusManager);
44.        var target:Object = fm.getNextFocusManagerComponent();
45.        target.setFocus();
46. 
47.    }
48. 
49.]]>
50.</mx:Script>
51. 
52.</mx:TextInput>
コンテナへの実装と、Flex としてのポップアップメニュー
Menu コントロールを使用してボタンに対するポップアップメニューを作成しています。

※ メニュー構造は、XML で定義して使用します。
Script.as
01.import mx.controls.*;
02.import mx.events.*;
03.import mx.rpc.events.*;
04.import mx.formatters.*;
05.import flash.external.*;
06.import flash.events.*;
07. 
08.include "Parts.as"
09. 
10.// *********************************************************
11.// フォームの初期処理
12.// *********************************************************
13.private function initForm( event:mx.events.FlexEvent ):void {
14. 
15.    // コンテキストメニュー定義
16.    addContextMenu(
17.        event.target,
18.        "Form : Flex3 リファレンスガイド",
19.        callAdobe
20.    );
21. 
22.}
23. 
24.// *********************************************************
25.// パネルの初期処理
26.// *********************************************************
27.private function initPanel( event:mx.events.FlexEvent ):void {
28. 
29.    // コンテキストメニュー定義
30.    addContextMenu(
31.        event.target,
32.        "Panel : Flex3 リファレンスガイド",
33.        function():void {
34.            openUrl(
35.                adobe + "containers/Panel.html"
36.            );
37.        }
38.    );
39. 
40.}
41. 
42.// *********************************************************
43.// URL を開く
44.// *********************************************************
45.private function callAdobe(event:ContextMenuEvent):void {
46. 
47.    openUrl(
48.        adobe + "containers/Form.html"
49.    );
50. 
51.}
52. 
53.// *********************************************************
54.// ポップアップメニューを開く
55.// *********************************************************
56.private function showPopupMenu():void {
57. 
58.    var popupMenu:Menu;
59. 
60.    // メニューをフォームコンテナに対して、XMLで定義された(popupMenu) 構造で追加する
61.    popupMenu = Menu.createMenu( mainForm, xmlPopupMenu, false);
62.    // 表示する内容を XML の属性に対応させる
63.    popupMenu.labelField = "@label";
64.    // イベントを登録
65.    popupMenu.addEventListener("itemClick", popupMenuHandler);
66. 
67.    // 表示位置の調整
68.    var locData:Point = new Point();
69.    locData.x = btn.x;
70.    locData.y = btn.y;
71.    locData = btn.localToGlobal(locData);
72. 
73.    popupMenu.setStyle( "backgroundColor", "0x000000" );
74.    popupMenu.width = 150;
75.    popupMenu.show(locData.x + btn.width, locData.y);
76.}
77. 
78.// *********************************************************
79.// ポップアップメニューの処理
80.// *********************************************************
81.private function popupMenuHandler(event:MenuEvent):void  {
82. 
83.    Alert.show( event.item.@label + " と " + event.item.@eventName);
84. 
85.}


※ ボタンに画像を使用しています( 背景透過 png )
Main.mxml
01.<?xml version="1.0" encoding="utf-8"?>
02.<mx:Application
03.    xmlns:mx="http://www.adobe.com/2006/mxml"
04.    initialize="initData();"
05.    xmlns="control.*"
06.>
07. 
08.<!-- *************************************************** -->
09.<!-- 外部ソース -->
10.<!-- *************************************************** -->
11.<mx:Style source="extern/Style.css" />
12.<mx:Script source="extern/Script.as" />
13. 
14.<!-- *************************************************** -->
15.<!-- 入力フォーム -->
16.<!-- *************************************************** -->
17.<mx:Form
18.    id="mainForm"
19.    width="90%"
20.    height="90%"
21.    backgroundColor="0x8A0029"
22.    backgroundAlpha="0.3"
23.    creationComplete="initForm(event)"
24.>
25.    <mx:FormHeading height="40" label="社員データ登録"/>
26.     
27.    <mx:FormItem
28.        label="社員コード"
29.        labelStyleName="labelAlign"
30.        paddingBottom="30"
31.    >
32.        <LboxText
33.            id="fld1"
34.            maxChars="4"
35.            width="50"
36.        />
37. 
38.    </mx:FormItem>
39.    <mx:FormItem
40.        label="氏名"
41.        labelStyleName="labelAlign"
42.         paddingBottom="30"
43.    >
44.        <LboxText
45.            id="fld2"
46.            width="300"
47.        />
48. 
49.    </mx:FormItem>
50.    <mx:FormItem
51.        label="フリガナ"
52.        labelStyleName="labelAlign"
53.         paddingBottom="30"
54.    >
55.        <LboxText
56.            id="fld3"
57.            width="300"
58.        />
59. 
60.    </mx:FormItem>
61. 
62.    <mx:FormItem
63.        label=""
64.        labelStyleName="labelAlign"
65.         paddingBottom="30"
66.    >
67.        <mx:HBox>
68.            <mx:Button
69.                id="btn"
70.                icon="@Embed('icon.png')"
71.                label=""
72.                styleName="orangeButton"
73.                click="showPopupMenu()"
74.            />
75.        </mx:HBox>
76.    </mx:FormItem>
77. 
78. 
79.</mx:Form>
80. 
81.<mx:Panel
82.    width="90%"
83.    height="50"
84.    title="ここは Panel です"
85.    creationComplete="initPanel(event)"
86.>
87.</mx:Panel>
88. 
89.<mx:XML id="xmlPopupMenu">
90.    <root>
91.        <menuitem label="本人" eventName="popupMenu_01"/>
92.        <menuitem label="管理者" eventName="popupMenu_02"/>
93.    </root>
94.</mx:XML>
95. 
96.</mx:Application>