アウトラインエディタの製作
ここからは、実際のアウトラインエディタの製作の様子を紹介したいと思います。
画面レイアウト
はじめに、画面の設計に取り掛かります。Flex Builderのデザインビューを使えば、さまざまなコンポーネントをドラッグ&ドロップで配置することができます。ただし、アウトラインエディタのような、レイアウトが複雑なアプリケーションでは、MXMLのタグを直接入力した方が早かったりします。これは、HTMLエディタでレイアウトの複雑なページをデザインする場合も同じでしょう。細かいところをマウス片手に必死に調整するよりは、タグを直接手で打ってしまった方が早いのです。
以下が、主なコントロールの配置図となっています。ソースファイルを見ると分かりますが、実際はこれほど単純ではなく、先ほど紹介したレイアウトを行うための<mx:HBox>
や<mx:VBox>
のタグが随所に利用されています。それでも、Flex Builderのコード補完機能のおかげか、コツさえ掴んでしまえば、それほど苦もなく、サクサクとコントロールを配置することができます。
今回利用する主なコンポーネント
今回使う主なコンポーネント(コントロール)を紹介します。
MenuBarコントロール
Windowsアプリケーションには必ずある、メインメニューを実現するためのコントロールです。マウスをラベルの上に乗せると、サブメニューが出現します。
Treeコントロール
Windowsのエクスプローラーなどでも利用されているツリーコントロールです。木構造を持つデータを表示、編集することができます。
TextInput/TextAreaコントロール
TextInputは、一行入力用のエディタコントロールです。それに対して、TextAreaは、複数行の文章を表示、入力するのに適したテキストボックスです。
データプロバイダの仕組み
TextAreaなどのコントロールは、text
プロパティに文字列を設定すれば、文字列がテキストボックスに表示されるようになっていますが、MenuBarやTreeコントロールでは、コントロールに表示するデータを、dataProvider
プロパティに設定することで表示できます。
そして、TreeやMenuBarのdataProvider
に設定するのはXMLデータです。例えば、次のように記述することで、Treeに任意のXMLデータを表示できます。
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <!-- Tree --> <mx:Tree id="todo_tree"
dataProvider="{todo_data}"
labelField="@label"
width="100%" height="100%"/> <!-- Data --> <mx:XMLList id="todo_data"> <node label="朝の日課"> <node label="ラジオ体操"/> <node label="ジョギング"/> </node> <node label="仕事メモ"> <node label="Aさんに電話"/> </node> </mx:XMLList> </mx:Application>
Treeコンポーネントで、labelField
プロパティを「@label」と指定していますが、これを「@text」や「@title」などに変更することで、好きな属性をラベルとして表示させることができます。また、MenuBarも同じで、メニューをXMLデータとして管理することができます。
ここでは、1つのファイルに、コントロールの配置と、データのXMLを混在させていますが、このXMLを別ファイルに切り分けたり、ネットワークから読み込んだXMLを表示させたりすることも簡単です。
イベントの記述
ツリーのアイテムを選択したり、テキストボックスに文字を書き込んだりすると、コントロールがイベントを発生させます。これらのイベントを処理するには、イベントハンドラを設定します。
以下は、id「a1」のTextAreaの内容が変更されたときに、テキストの文字数を数えてid「a2」のLabelに表示するプログラムです。
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:TextArea id="a1"
change="onChange()"/> <mx:Label id="a2"/> <mx:Script> <![CDATA[ private function onChange():void { a2.text = "文字数=" + a1.text.length; } ]]> </mx:Script> </mx:Application>
TextAreaのタグの中でchange="onChange()"
のように書いていますが、これでテキストが変更されると、onChange()
関数を実行するという意味になります。onChange()
関数は、<mx:Script>
タグで囲まれたスクリプトブロックに記述します。
メニューの処理
次に、MenuBarのイベントを定義してみたいと思います。MenuBarも、XMLでメニューのデータを指定します。そして、サブメニューがクリックされると、itemClickイベントが発生します。
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:MenuBar id="main_menu"
dataProvider="{main_menu_data}"
width="100%"
labelField="@label"
itemClick="main_menu_click(event)"/> <mx:XMLList id="main_menu_data"> <item label="ファイル"> <item label="新規"/> <item label="開く"/> <item label="保存"/> </item> </mx:XMLList> <mx:Script> <![CDATA[ import mx.events.MenuEvent; private function main_menu_click(e:MenuEvent):void { var x:XML = e.item as XML; trace(x.@label + "がクリックされました"); } ]]> </mx:Script> </mx:Application>
このように、メニューがクリックされると、itemClickイベントが実行されるようになっていますが、メニューの数が多くなってくると、メニューの数だけ、switch文で処理を分岐する必要があります。これでは大変なので、MenuBarのdataProvider
がXMLオブジェクトであることを活かして、メニューの定義で指定した関数を実行するように工夫します。
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:MenuBar id="main_menu"
dataProvider="{main_menu_data}"
width="100%"
labelField="@label"
itemClick="main_menu_click(event)"/> <mx:XMLList id="main_menu_data"> <item label="ファイル"> <item label="新規" click="menu_new_click"/> <item label="開く" click="menu_open_click"/> <item label="保存" click="menu_save_click"/> </item> </mx:XMLList> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.events.MenuEvent; private function main_menu_click(e:MenuEvent):void { var x:XML = e.item as XML; var funcname:String = x.@click; this[funcname](); // ---------------- (*1) 関数実行 } private function menu_new_click():void { Alert.show("new"); } private function menu_open_click():void { Alert.show("open"); } private function menu_save_click():void { Alert.show("save"); } ]]> </mx:Script> </mx:Application>
プログラム中の(*1)を見ると分かりますが、メニューの定義の際に指定したclick
属性を得て、その名前の関数を実行するようにしています。動的な言語ならではの柔軟性が活きる例です。