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


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

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

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

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


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

※ ちなみに、タイトルに "adobe" と言う文字が含まれるとメニューは作成されないようです
Parts.as
public var rootObject:Application;
public var param:Object;
public var adobe:String = "http://livedocs.adobe.com/flex/3_jp/langref/mx/";

// *********************************************************
// アプリケーションの初期化
// *********************************************************
public function initData():void {

	firebug("処理開始");

	// Root オブジェクト
	rootObject = Application(mx.core.Application.application);
	// パラメータをプロパティとして持つ Object を取得
	param = rootObject.parameters;

	// 初期フォーカス
	fld1.setFocus();

	// いかなるドメインからも OK
	Security.allowDomain("*");

	// コンテキストメニュー定義
	addContextMenu(
		rootObject,
		"Application : Flex3 リファレンスガイド",
		function():void {
			openUrl(
				adobe + "core/Application.html"
			);
		}
	);


	// ExternalInterface.call("console.open");
	// Alert.show("処理開始");
}

// *********************************************************
// ログ表示
// *********************************************************
public function firebug(data:Object):void {

	var fmt:DateFormatter = new DateFormatter();

	fmt.formatString = "YYYY/MM/DD HH:NN:SS";
	var logdt:String = fmt.format( new Date );

	ExternalInterface.call(
		"console.log", logdt,
		data+""
	);

}

// *********************************************************
// コンテキストメニュー追加
// *********************************************************
public function addContextMenu(
	target:Object,
	label:String,
	listener:Function
):void {

	var nativeMenu:ContextMenu;
	nativeMenu = new ContextMenu();
	nativeMenu.hideBuiltInItems();
	var menuItem:ContextMenuItem;
	menuItem = new ContextMenuItem(label);
	menuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,listener);
	nativeMenu.customItems.push(menuItem);
	target.contextMenu = nativeMenu;

}

// *********************************************************
// ブラウザで開く
// *********************************************************
public function openUrl(url:String):void {

	var req:URLRequest = new URLRequest(url);
	navigateToURL(req, "_blank");

}
ユーザーコントロール内部からの実装
このアプリケーション自体のクラス名である "Main" を使用して
addContextMenu を参照しています。本来はこのような記述はアプリケーション
依存となるので行いませんが、Popupmenu の実装サンプルとして行っています。
LboxText.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:TextInput
	xmlns:mx="http://www.adobe.com/2006/mxml"
	creationComplete="initControl(event)"
>

<mx:Script>
<![CDATA[

	import mx.managers.*;
	import mx.events.*;
	import mx.core.*;

	// *****************************************************
	// 初期処理
	// *****************************************************
	private function initControl(e:FlexEvent):void {

		// イベント追加
		this.addEventListener(FlexEvent.ENTER, focusControl);

		var rootObject:Main;
		// Root オブジェクト
		rootObject = Main(mx.core.Application.application);
		// コンテキストメニュー定義
		rootObject.addContextMenu(
			e.target,
			"TextInput : Flex3 リファレンスガイド",
			function():void {
				rootObject.openUrl(
					rootObject.adobe + "controls/TextInput.html"
				);
			}
		);

	}

	// *************************************************
	// ENTER to TAB
	// *************************************************
	private function focusControl(event:FlexEvent):void{

		var fm:FocusManager = FocusManager(this.focusManager);
		var target:Object = fm.getNextFocusManagerComponent();
		target.setFocus();

	}

]]>
</mx:Script>

</mx:TextInput>
コンテナへの実装と、Flex としてのポップアップメニュー
Menu コントロールを使用してボタンに対するポップアップメニューを作成しています。

※ メニュー構造は、XML で定義して使用します。
Script.as
import mx.controls.*;
import mx.events.*; 
import mx.rpc.events.*;
import mx.formatters.*;
import flash.external.*;
import flash.events.*; 

include "Parts.as"

// *********************************************************
// フォームの初期処理
// *********************************************************
private function initForm( event:mx.events.FlexEvent ):void {

	// コンテキストメニュー定義
	addContextMenu(
		event.target,
		"Form : Flex3 リファレンスガイド",
		callAdobe
	);

}

// *********************************************************
// パネルの初期処理
// *********************************************************
private function initPanel( event:mx.events.FlexEvent ):void {

	// コンテキストメニュー定義
	addContextMenu(
		event.target,
		"Panel : Flex3 リファレンスガイド",
		function():void {
			openUrl(
				adobe + "containers/Panel.html"
			);
		}
	);

}

// *********************************************************
// URL を開く
// *********************************************************
private function callAdobe(event:ContextMenuEvent):void {

	openUrl(
		adobe + "containers/Form.html"
	);

}

// *********************************************************
// ポップアップメニューを開く
// *********************************************************
private function showPopupMenu():void {

	var popupMenu:Menu;

	// メニューをフォームコンテナに対して、XMLで定義された(popupMenu) 構造で追加する
	popupMenu = Menu.createMenu( mainForm, xmlPopupMenu, false);
	// 表示する内容を XML の属性に対応させる
	popupMenu.labelField = "@label";
	// イベントを登録
	popupMenu.addEventListener("itemClick", popupMenuHandler);

	// 表示位置の調整
	var locData:Point = new Point();
	locData.x = btn.x;
	locData.y = btn.y;
	locData = btn.localToGlobal(locData);

	popupMenu.setStyle( "backgroundColor", "0x000000" );
	popupMenu.width = 150;
	popupMenu.show(locData.x + btn.width, locData.y);
}

// *********************************************************
// ポップアップメニューの処理
// *********************************************************
private function popupMenuHandler(event:MenuEvent):void  {

	Alert.show( event.item.@label + " と " + event.item.@eventName);

}


※ ボタンに画像を使用しています( 背景透過 png )
Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	initialize="initData();"
	xmlns="control.*"
>

<!-- *************************************************** -->
<!-- 外部ソース -->
<!-- *************************************************** -->
<mx:Style source="extern/Style.css" />
<mx:Script source="extern/Script.as" />

<!-- *************************************************** -->
<!-- 入力フォーム -->
<!-- *************************************************** -->
<mx:Form
	id="mainForm"
	width="90%"
	height="90%"
	backgroundColor="0x8A0029"
	backgroundAlpha="0.3"
	creationComplete="initForm(event)"
>
	<mx:FormHeading height="40" label="社員データ登録"/>
	
	<mx:FormItem
		label="社員コード"
		labelStyleName="labelAlign"
		paddingBottom="30"
	>
		<LboxText
			id="fld1"
			maxChars="4"
			width="50"
		/>

	</mx:FormItem>
	<mx:FormItem
		label="氏名"
		labelStyleName="labelAlign"
		 paddingBottom="30"
	>
		<LboxText
			id="fld2"
			width="300"
		/>

	</mx:FormItem>
	<mx:FormItem
		label="フリガナ"
		labelStyleName="labelAlign"
		 paddingBottom="30"
	>
		<LboxText
			id="fld3"
			width="300"
		/>

	</mx:FormItem>

	<mx:FormItem
		label=""
		labelStyleName="labelAlign"
		 paddingBottom="30"
	>
		<mx:HBox>
			<mx:Button
				id="btn"
				icon="@Embed('icon.png')" 
				label=""
				styleName="orangeButton"
				click="showPopupMenu()"
			/>
		</mx:HBox>
	</mx:FormItem>


</mx:Form>

<mx:Panel
	width="90%"
	height="50"
	title="ここは Panel です"
	creationComplete="initPanel(event)"
>
</mx:Panel>

<mx:XML id="xmlPopupMenu">
	<root>
		<menuitem label="本人" eventName="popupMenu_01"/>
		<menuitem label="管理者" eventName="popupMenu_02"/>
	</root>
</mx:XML>

</mx:Application>