using System; using System.Collections.Generic; using FairyGUI.Utils; namespace FairyGUI { /// /// /// public class GTree : GList { public delegate void TreeNodeRenderDelegate(GTreeNode node, GComponent obj); public delegate void TreeNodeWillExpandDelegate(GTreeNode node, bool expand); /// /// 当TreeNode需要更新时回调 /// public TreeNodeRenderDelegate treeNodeRender; /// /// 当TreeNode即将展开或者收缩时回调。可以在回调中动态增加子节点。 /// public TreeNodeWillExpandDelegate treeNodeWillExpand; int _indent; GTreeNode _rootNode; int _clickToExpand; bool _expandedStatusInEvt; private static List helperIntList = new List(); /// /// /// public GTree() { _indent = 30; _rootNode = new GTreeNode(true); _rootNode._SetTree(this); _rootNode.expanded = true; } /// /// TreeView的顶层节点,这是个虚拟节点,也就是他不会显示出来。 /// public GTreeNode rootNode { get { return _rootNode; } } /// /// TreeView每级的缩进,单位像素。 /// public int indent { get { return _indent; } set { _indent = value; } } /// /// /// public int clickToExpand { get { return _clickToExpand; } set { _clickToExpand = value; } } /// /// /// /// public GTreeNode GetSelectedNode() { int i = this.selectedIndex; if (i != -1) return (GTreeNode)this.GetChildAt(i)._treeNode; else return null; } /// /// /// /// public List GetSelectedNodes() { return GetSelectedNodes(null); } /// /// /// /// /// public List GetSelectedNodes(List result) { if (result == null) result = new List(); helperIntList.Clear(); List sels = GetSelection(helperIntList); int cnt = sels.Count; for (int i = 0; i < cnt; i++) { GTreeNode node = GetChildAt(sels[i])._treeNode; result.Add(node); } return result; } /// /// /// /// public void SelectNode(GTreeNode node) { SelectNode(node, false); } /// /// /// /// /// public void SelectNode(GTreeNode node, bool scrollItToView) { GTreeNode parentNode = node.parent; while (parentNode != null && parentNode != _rootNode) { parentNode.expanded = true; parentNode = parentNode.parent; } AddSelection(GetChildIndex(node.cell), scrollItToView); } /// /// /// /// public void UnselectNode(GTreeNode node) { RemoveSelection(GetChildIndex(node.cell)); } /// /// /// public void ExpandAll() { ExpandAll(_rootNode); } /// /// /// /// public void ExpandAll(GTreeNode folderNode) { folderNode.expanded = true; int cnt = folderNode.numChildren; for (int i = 0; i < cnt; i++) { GTreeNode node = folderNode.GetChildAt(i); if (node.isFolder) ExpandAll(node); } } /// /// /// /// public void CollapseAll() { CollapseAll(_rootNode); } /// /// /// /// public void CollapseAll(GTreeNode folderNode) { if (folderNode != _rootNode) folderNode.expanded = false; int cnt = folderNode.numChildren; for (int i = 0; i < cnt; i++) { GTreeNode node = folderNode.GetChildAt(i); if (node.isFolder) CollapseAll(node); } } /// /// /// /// void CreateCell(GTreeNode node) { GComponent child = itemPool.GetObject(string.IsNullOrEmpty(node._resURL) ? this.defaultItem : node._resURL) as GComponent; if (child == null) throw new Exception("FairyGUI: cannot create tree node object."); child.displayObject.home = this.displayObject.cachedTransform; child._treeNode = node; node._cell = child; GObject indentObj = node.cell.GetChild("indent"); if (indentObj != null) indentObj.width = (node.level - 1) * indent; Controller cc; cc = child.GetController("expanded"); if (cc != null) { cc.onChanged.Add(__expandedStateChanged); cc.selectedIndex = node.expanded ? 1 : 0; } cc = child.GetController("leaf"); if (cc != null) cc.selectedIndex = node.isFolder ? 0 : 1; if (node.isFolder) child.onTouchBegin.Add(__cellTouchBegin); if (treeNodeRender != null) treeNodeRender(node, node._cell); } /// /// /// /// internal void _AfterInserted(GTreeNode node) { if (node._cell == null) CreateCell(node); int index = GetInsertIndexForNode(node); AddChildAt(node.cell, index); if (treeNodeRender != null) treeNodeRender(node, node._cell); if (node.isFolder && node.expanded) CheckChildren(node, index); } /// /// /// /// /// int GetInsertIndexForNode(GTreeNode node) { GTreeNode prevNode = node.GetPrevSibling(); if (prevNode == null) prevNode = node.parent; int insertIndex = GetChildIndex(prevNode.cell) + 1; int myLevel = node.level; int cnt = this.numChildren; for (int i = insertIndex; i < cnt; i++) { GTreeNode testNode = GetChildAt(i)._treeNode; if (testNode.level <= myLevel) break; insertIndex++; } return insertIndex; } /// /// /// /// internal void _AfterRemoved(GTreeNode node) { RemoveNode(node); } /// /// /// /// internal void _AfterExpanded(GTreeNode node) { if (node == _rootNode) { CheckChildren(_rootNode, 0); return; } if (this.treeNodeWillExpand != null) this.treeNodeWillExpand(node, true); if (node._cell == null) return; if (this.treeNodeRender != null) this.treeNodeRender(node, node._cell); Controller cc = node._cell.GetController("expanded"); if (cc != null) cc.selectedIndex = 1; if (node._cell.parent != null) CheckChildren(node, GetChildIndex(node._cell)); } /// /// /// /// internal void _AfterCollapsed(GTreeNode node) { if (node == _rootNode) { CheckChildren(_rootNode, 0); return; } if (this.treeNodeWillExpand != null) this.treeNodeWillExpand(node, false); if (node._cell == null) return; if (this.treeNodeRender != null) this.treeNodeRender(node, node._cell); Controller cc = node._cell.GetController("expanded"); if (cc != null) cc.selectedIndex = 0; if (node._cell.parent != null) HideFolderNode(node); } /// /// /// /// internal void _AfterMoved(GTreeNode node) { int startIndex = GetChildIndex(node._cell); int endIndex; if (node.isFolder) endIndex = GetFolderEndIndex(startIndex, node.level); else endIndex = startIndex + 1; int insertIndex = GetInsertIndexForNode(node); int cnt = endIndex - startIndex; if (insertIndex < startIndex) { for (int i = 0; i < cnt; i++) { GObject obj = GetChildAt(startIndex + i); SetChildIndex(obj, insertIndex + i); } } else { for (int i = 0; i < cnt; i++) { GObject obj = GetChildAt(startIndex); SetChildIndex(obj, insertIndex); } } } private int GetFolderEndIndex(int startIndex, int level) { int cnt = this.numChildren; for (int i = startIndex + 1; i < cnt; i++) { GTreeNode node = GetChildAt(i)._treeNode; if (node.level <= level) return i; } return cnt; } /// /// /// /// /// /// int CheckChildren(GTreeNode folderNode, int index) { int cnt = folderNode.numChildren; for (int i = 0; i < cnt; i++) { index++; GTreeNode node = folderNode.GetChildAt(i); if (node.cell == null) CreateCell(node); if (node.cell.parent == null) AddChildAt(node.cell, index); if (node.isFolder && node.expanded) index = CheckChildren(node, index); } return index; } /// /// /// /// void HideFolderNode(GTreeNode folderNode) { int cnt = folderNode.numChildren; for (int i = 0; i < cnt; i++) { GTreeNode node = folderNode.GetChildAt(i); if (node.cell != null && node.cell.parent != null) RemoveChild(node.cell); if (node.isFolder && node.expanded) HideFolderNode(node); } } /// /// /// /// void RemoveNode(GTreeNode node) { if (node.cell != null) { if (node.cell.parent != null) RemoveChild(node.cell); itemPool.ReturnObject(node.cell); node._cell._treeNode = null; node._cell = null; } if (node.isFolder) { int cnt = node.numChildren; for (int i = 0; i < cnt; i++) { GTreeNode node2 = node.GetChildAt(i); RemoveNode(node2); } } } void __cellTouchBegin(EventContext context) { GTreeNode node = ((GObject)context.sender)._treeNode; _expandedStatusInEvt = node.expanded; } void __expandedStateChanged(EventContext context) { Controller cc = (Controller)context.sender; GTreeNode node = cc.parent._treeNode; node.expanded = cc.selectedIndex == 1; } override protected void DispatchItemEvent(GObject item, EventContext context) { if (_clickToExpand != 0) { GTreeNode node = item._treeNode; if (node != null && _expandedStatusInEvt == node.expanded) { if (_clickToExpand == 2) { if (context.inputEvent.isDoubleClick) node.expanded = !node.expanded; } else node.expanded = !node.expanded; } } base.DispatchItemEvent(item, context); } override public void Setup_BeforeAdd(ByteBuffer buffer, int beginPos) { base.Setup_BeforeAdd(buffer, beginPos); buffer.Seek(beginPos, 9); _indent = buffer.ReadInt(); _clickToExpand = buffer.ReadByte(); } override protected void ReadItems(ByteBuffer buffer) { int nextPos; string str; bool isFolder; GTreeNode lastNode = null; int level; int prevLevel = 0; int cnt = buffer.ReadShort(); for (int i = 0; i < cnt; i++) { nextPos = buffer.ReadUshort(); nextPos += buffer.position; str = buffer.ReadS(); if (str == null) { str = this.defaultItem; if (str == null) { buffer.position = nextPos; continue; } } isFolder = buffer.ReadBool(); level = buffer.ReadByte(); GTreeNode node = new GTreeNode(isFolder, str); node.expanded = true; if (i == 0) _rootNode.AddChild(node); else { if (level > prevLevel) lastNode.AddChild(node); else if (level < prevLevel) { for (int j = level; j <= prevLevel; j++) lastNode = lastNode.parent; lastNode.AddChild(node); } else lastNode.parent.AddChild(node); } lastNode = node; prevLevel = level; SetupItem(buffer, node.cell); buffer.position = nextPos; } } } }