2025-06-07 17:43:34 +08:00

558 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using FairyGUI.Utils;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class GTree : GList
{
public delegate void TreeNodeRenderDelegate(GTreeNode node, GComponent obj);
public delegate void TreeNodeWillExpandDelegate(GTreeNode node, bool expand);
/// <summary>
/// 当TreeNode需要更新时回调
/// </summary>
public TreeNodeRenderDelegate treeNodeRender;
/// <summary>
/// 当TreeNode即将展开或者收缩时回调。可以在回调中动态增加子节点。
/// </summary>
public TreeNodeWillExpandDelegate treeNodeWillExpand;
int _indent;
GTreeNode _rootNode;
int _clickToExpand;
bool _expandedStatusInEvt;
private static List<int> helperIntList = new List<int>();
/// <summary>
///
/// </summary>
public GTree()
{
_indent = 30;
_rootNode = new GTreeNode(true);
_rootNode._SetTree(this);
_rootNode.expanded = true;
}
/// <summary>
/// TreeView的顶层节点这是个虚拟节点也就是他不会显示出来。
/// </summary>
public GTreeNode rootNode
{
get { return _rootNode; }
}
/// <summary>
/// TreeView每级的缩进单位像素。
/// </summary>
public int indent
{
get { return _indent; }
set { _indent = value; }
}
/// <summary>
///
/// </summary>
public int clickToExpand
{
get { return _clickToExpand; }
set { _clickToExpand = value; }
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public GTreeNode GetSelectedNode()
{
int i = this.selectedIndex;
if (i != -1)
return (GTreeNode)this.GetChildAt(i)._treeNode;
else
return null;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public List<GTreeNode> GetSelectedNodes()
{
return GetSelectedNodes(null);
}
/// <summary>
///
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public List<GTreeNode> GetSelectedNodes(List<GTreeNode> result)
{
if (result == null)
result = new List<GTreeNode>();
helperIntList.Clear();
List<int> 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;
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
public void SelectNode(GTreeNode node)
{
SelectNode(node, false);
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
/// <param name="scrollItToView"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
public void UnselectNode(GTreeNode node)
{
RemoveSelection(GetChildIndex(node.cell));
}
/// <summary>
///
/// </summary>
public void ExpandAll()
{
ExpandAll(_rootNode);
}
/// <summary>
///
/// </summary>
/// <param name="folderNode"></param>
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);
}
}
/// <summary>
///
/// </summary>
/// <param name="folderNode"></param>
public void CollapseAll()
{
CollapseAll(_rootNode);
}
/// <summary>
///
/// </summary>
/// <param name="folderNode"></param>
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);
}
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
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;
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
internal void _AfterRemoved(GTreeNode node)
{
RemoveNode(node);
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
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));
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
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);
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
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;
}
/// <summary>
///
/// </summary>
/// <param name="folderNode"></param>
/// <param name="index"></param>
/// <returns></returns>
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;
}
/// <summary>
///
/// </summary>
/// <param name="folderNode"></param>
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);
}
}
/// <summary>
///
/// </summary>
/// <param name="node"></param>
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;
}
}
}
}