Документация по Flex, равно как и почти весь интернет, усеяны примерами, как наполнить Tree, используя XML документ. Все, конечно, замечательно - но это так ужасно - каждый раз парсить одни и те же элементы. А между тем, у нас всегда есть замечательный способ - работа с массивами и объектами.
"Под катом" - исходный код, используемый во flash клиенте игры Берсерк Онлайн.
Дано: Список комнат игрового мира.
Требуется: Отобразить его древовидную структуру, по клику разрешить менять комнату.
Это - объект "Комната". У каждой комнаты есть идентификатор, метка, и данные.
package berserk.rooms
{
import messaging.Message;
public final class Room
{
public var id: String;
public var children: Array;
public var label: String;
public var data: Object;
public function Room(id: String) {
this.id = id;
}
public function addChild(r: Room):void {
if (!children) children = new Array();
children.add(r);
}
public function fromMessage(m: Message): void {
// TODO: Считать room_info из m
}
}
}
Это - менеджер комнат (хранит в себе все экземпляры класса Room):
package berserk.rooms
{
import mx.collections.ArrayCollection;
import flash.events.EventDispatcher;
import berserk.net.BerserkClient;
public final class RoomManager extends EventDispatcher
{
[Bindable]
public var all_rooms: ArrayCollection = new ArrayCollection();
private var ids: Array = new Array();
private var _client: BerserkClient = null;
public function RoomManager(client: BerserkClient) {
super();
_client = client;
}
private function addRoomNode(id: String, parent: Object = null): Room {
var item: Room = new Room(id);
item.label = id;
if (!parent) {
all_rooms.addItem(item);
} else {
if (!parent.children) parent.children = new Array();
parent.children.push(item);
}
return item;
}
public function addRoom(id: String): void {
if (ids[id]) {
//TODO:обновить инфо
return;
}
var n: int = id.lastIndexOf("/");
var parent: String = id.substr(0, n);
// parent: id комнаты родителя -- TODO убедиться
// id: id самой комнаты
var parentNode: Room = null;
if (parent != '') {
parentNode = ids[parent];
if (parentNode == null) {
addRoom(parent);
parentNode = ids[parent];
}
}
var room: Room = addRoomNode(id, parentNode);
ids[id] = room;
}
}
}
При добавлении, в первую очередь проверяем, нет ли уже комнаты с заданным идентификатором. Затем проверяем, есть ли нод для родительской комнаты, и собственно далее уже выполняем добавление.
Комнаты представлены в виде /parent/child. Присылаются в произвольном порядке. Таким образом, для добавления комнаты /parent/child, надо убедиться в существовании комнаты /parent, а затем в существовании комнаты.
Забрать данные мы можем через Bindable свойство all_rooms.
Собственно, рендерер:
<simpletitlewindow height="300" width="400" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="visual.gui.*">
<mx:script>
<!--[CDATA[
import berserk.rooms.Room;
import mx.events.ListEvent;
import mx.managers.PopUpManager;
import berserk.rooms.RoomManager;
import mx.core.Application;
private function onClose():void {
PopUpManager.removePopUp(this);
}
private final function handleItemClick(event: ListEvent): void {
if (event.target == mytree && event.itemRenderer.data is Room) {
var room: Room = event.itemRenderer.data as Room;
var roomID:String = room.id;
Application.application.berserkclient.changeRoom(roomID);
}
}
]]-->
</mx:script>
<mx:tree id="mytree" backgroundimage="/assets/roomlist_b.png" height="100%" width="100%"
backgroundalpha="0" itemclick="handleItemClick(event)"
dataprovider="{Application.application.berserkclient.roomManager.all_rooms}">
</mx:tree>
<mx:hbox width="100%" y="270" x="0">
<mx:button click="onClose()" label="Закрыть">
</mx:button>
</mx:hbox>
Здесь, в обработчике handleItemClick, мы имеем полноценный объект, а не какую-то жалкую XML-ину. Мы могли бы вызывать методы этого объекта. Мы можем обращаться к любым его свойствам. Мы имеем строгую типизацию и точно знаем, что там - именно объект Room, а не некий мистический XML, который надо парсить раз за разом.