Компонент Tree во Flex. Скажем "нет" XML dataProvider'ам.

· На чтение уйдёт 3 минуты · (504 слова)

Документация по 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, который надо парсить раз за разом.

Полезное