452 lines
21 KiB
C#
452 lines
21 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using System.IO;
|
||
using System.Runtime.Serialization.Formatters.Binary;
|
||
|
||
|
||
namespace SuperTreeView
|
||
{
|
||
public class DemoScene2Script : MonoBehaviour
|
||
{
|
||
public TreeView mTreeView;
|
||
|
||
int mCurSelectedItemId = 0;
|
||
|
||
int mNewItemCount = 0;
|
||
void Start()
|
||
{
|
||
SpriteResMgr rm = SpriteResMgr.Instance;
|
||
mTreeView.OnTreeListAddOneItem = OnTreeListAddOneItem;
|
||
//mTreeView.OnTreeListDeleteOneItem = OnTreeListDeleteOneItem;
|
||
mTreeView.OnItemExpandBegin = OnItemExpandBegin;
|
||
mTreeView.OnItemCollapseBegin = OnItemCollapseBegin;
|
||
mTreeView.OnItemCustomEvent = OnItemCustomEvent;
|
||
mTreeView.OnTreeListRepositionFinish = OnTreeListRepositionFinish;
|
||
mTreeView.InitView();
|
||
BuildTreeAutomatically();
|
||
}
|
||
void BuildTreeAutomatically()
|
||
{
|
||
var datas = new List<string[]>
|
||
{
|
||
// --- 胸部体表标志 ---
|
||
new[] { "胸部体表标志", "胸骨柄", "XiongGuBing" },
|
||
new[] { "胸部体表标志", "胸骨上切迹", "XiongGuShangQieJi" },
|
||
new[] { "胸部体表标志", "胸骨角", "XiongGuJiao" },
|
||
new[] { "胸部体表标志", "剑突", "JianTu" },
|
||
new[] { "胸部体表标志", "1-7肋骨", "LeiGu1-7" },
|
||
new[] { "胸部体表标志", "11-12肋骨", "LeiGu11-12" },
|
||
new[] { "胸部体表标志", "肋间隙", "LeiJianXi" },
|
||
new[] { "胸部体表标志", "肩胛骨", "JianJiaGu" },
|
||
new[] { "胸部体表标志", "肩胛下角", "JianJiaXiaJiao" },
|
||
|
||
// --- 垂直线标志 ---
|
||
new[] { "垂直线标志", "前正中线", "QianZhengZhongXian" },
|
||
new[] { "垂直线标志", "(左、右)锁骨中线", "SuoGuZhongXian" },
|
||
new[] { "垂直线标志", "(左、右)胸骨线", "XiongGuXian" },
|
||
new[] { "垂直线标志", "(左、右)胸骨旁线", "XiongGuPangXian" },
|
||
new[] { "垂直线标志", "(左、右)腋前线", "YeQianXian" },
|
||
new[] { "垂直线标志", "(左、右)腋后线", "YeHouXian" },
|
||
new[] { "垂直线标志", "(左、右)腋中线", "YeZhongXian" },
|
||
new[] { "垂直线标志", "(左、右)肩胛线", "JianJiaXian" },
|
||
new[] { "垂直线标志", "后正中线", "HouZhengZhongXian" },
|
||
|
||
// --- 解剖区域 ---
|
||
new[] { "解剖区域", "(左、右)肩胛上区", "JianJiaShangQu" },
|
||
new[] { "解剖区域", "(左、右)肩胛下区", "JianJiaXiaQu" },
|
||
new[] { "解剖区域", "(左、右)肩胛间区", "JianJiaQuJian" },
|
||
|
||
// --- 动画 ---
|
||
new[] { "肺功能动画", "FeiGongNengDongHua" },
|
||
new[] { "心功能动画", "XinGongNengDongHua" },
|
||
|
||
// --- 肺部听诊 ---
|
||
new[] { "肺部听诊", "正常呼吸音", "气管呼吸音", "QiGuanHuXiYin" },
|
||
new[] { "肺部听诊", "正常呼吸音", "支气管呼吸音", "ZhiQiGuanHuXiYin" },
|
||
new[] { "肺部听诊", "正常呼吸音", "支气管肺泡呼吸音", "ZhiQiGuanFeiPaoHuXiYin" },
|
||
new[] { "肺部听诊", "正常呼吸音", "肺泡呼吸音", "FeiPaoHuXiYin" },
|
||
|
||
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "肺泡呼吸音减弱或消失", "FeiPaoHuXiYinJianRuoHuoXiaoShi" },
|
||
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "肺泡呼吸音增强", "FeiPaoHuXiYinZengQiang" },
|
||
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "呼吸音延长", "HuXiYinYanChang" },
|
||
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "断续性呼吸音", "DuanXuXingHuXiYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "异常肺泡呼吸音", "粗糙性呼吸音", "CuCaoXingHuXiYin" },
|
||
|
||
new[] { "肺部听诊", "异常呼吸音", "异常支气管呼吸音", "YiChangZhiQiGuanHuXiYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "异常支气管肺泡呼吸音", "YiChangZhiQiGuanFeiPaoHuXiYin" },
|
||
|
||
new[] { "肺部听诊", "异常呼吸音", "啰音", "粗湿啰音(大水泡音)", "CuShiLuoYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "啰音", "中湿啰音(中水泡音)", "ZhongShiLuoYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "啰音", "细湿啰音(小水泡音)", "XiShiLuoYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "啰音", "Velcro啰音", "VelcroLuoYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "啰音", "捻发音", "NianFaYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "啰音", "高调干啰音(哨笛音)", "GaoDiaoGanLuoYin" },
|
||
new[] { "肺部听诊", "异常呼吸音", "啰音", "低调干啰音(鼾音)", "DiDiaoGanLuoYin" },
|
||
|
||
new[] { "肺部听诊", "异常呼吸音", "胸膜摩擦音", "XiongMoMoCaYin" },
|
||
|
||
// --- 心脏听诊 ---
|
||
new[] { "心脏听诊", "心脏瓣膜听诊区", "二尖瓣区(心尖区)", "ErJianBanQu" },
|
||
new[] { "心脏听诊", "心脏瓣膜听诊区", "肺动脉瓣区", "FeiDongMaiBanQu" },
|
||
new[] { "心脏听诊", "心脏瓣膜听诊区", "主动脉瓣区", "ZhuDongMaiBanQu" },
|
||
new[] { "心脏听诊", "心脏瓣膜听诊区", "主动脉瓣第二听诊区", "ZhuDongMaiBanDiErTingZhenQu" },
|
||
new[] { "心脏听诊", "心脏瓣膜听诊区", "三尖瓣区", "SanJianBanQu" },
|
||
|
||
new[] { "心脏听诊", "心率", "XinLv" },
|
||
|
||
new[] { "心脏听诊", "心音", "第一心音", "DiYiXinYin" },
|
||
new[] { "心脏听诊", "心音", "第二心音", "DiErXinYin" },
|
||
new[] { "心脏听诊", "心音", "第三心音", "DiSanXinYin" },
|
||
new[] { "心脏听诊", "心音", "第四心音", "DiSiXinYin" },
|
||
new[] { "心脏听诊", "心音", "第一心音增强", "DiYiXinYinZengQiang" },
|
||
new[] { "心脏听诊", "心音", "第一心音减弱", "DiYiXinYinJianRuo" },
|
||
new[] { "心脏听诊", "心音", "第一心音强弱不等", "DiYiXinYinQiangRuoBuDeng" },
|
||
new[] { "心脏听诊", "心音", "第二心音增强", "DiErXinYinZengQiang" },
|
||
new[] { "心脏听诊", "心音", "第二心音减弱", "DiErXinYinJianRuo" },
|
||
new[] { "心脏听诊", "心音", "第一心音分裂", "DiYiXinYinFenLie" },
|
||
new[] { "心脏听诊", "心音", "第二心音通常分裂", "DiErXinYinTongChangFenLie" },
|
||
new[] { "心脏听诊", "心音", "第二心音固定分裂", "DiErXinYinGuDingFenLie" },
|
||
new[] { "心脏听诊", "心音", "第二心音反常分裂", "DiErXinYinFanChangFenLie" },
|
||
|
||
new[] { "心脏听诊", "额外心音", "舒张期额外心音", "舒张早期奔马律", "ShuZhangZaoQiBenMaLv" },
|
||
new[] { "心脏听诊", "额外心音", "舒张期额外心音", "舒张晚期奔马律", "ShuZhangWanQiBenMaLv" },
|
||
new[] { "心脏听诊", "额外心音", "舒张期额外心音", "开瓣音", "KaiBanYin" },
|
||
new[] { "心脏听诊", "额外心音", "收缩期额外心音", "收缩中、晚期喀喇音", "ShouSuoZhongWanQiKaLaYin" },
|
||
|
||
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "二尖瓣区", "ErJianBanQu2" },
|
||
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "主动脉瓣区", "ZhuDongMaiBanQu2" },
|
||
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "肺动脉瓣区", "FeiDongMaiBanQu2" },
|
||
new[] { "心脏听诊", "心脏杂音", "收缩期杂音", "三尖瓣区", "SanJianBanQu2" },
|
||
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "二尖瓣区", "ErJianBanQu3" },
|
||
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "主动脉瓣区", "ZhuDongMaiBanQu3" },
|
||
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "肺动脉瓣区", "FeiDongMaiBanQu3" },
|
||
new[] { "心脏听诊", "心脏杂音", "舒张期杂音", "三尖瓣区", "SanJianBanQu3" },
|
||
new[] { "心脏听诊", "心脏杂音", "连续性杂音", "LianXuXingZaYin" },
|
||
new[] { "心脏听诊", "心脏杂音", "心包摩擦音", "XinBaoMoCaYin" }
|
||
};
|
||
|
||
// 【修复点】创建一个虚拟的根节点对象,作为字典的 Key,避免使用 null
|
||
TreeViewItem virtualRoot = new TreeViewItem();
|
||
|
||
// 缓存结构:Key=父节点对象, Value=该父节点下的子节点字典 (名称->节点对象)
|
||
var nodeCache = new Dictionary<TreeViewItem, Dictionary<string, TreeViewItem>>();
|
||
|
||
// 初始化:将虚拟根节点的子节点字典放入缓存
|
||
nodeCache[virtualRoot] = new Dictionary<string, TreeViewItem>();
|
||
|
||
foreach (var row in datas)
|
||
{
|
||
if (row.Length == 0) continue;
|
||
|
||
// 初始父节点设为虚拟根节点
|
||
TreeViewItem currentParent = virtualRoot;
|
||
|
||
// 计算需要生成的节点数量 (总长度 - 1,因为最后一个是数据 Payload)
|
||
int nodeCount = row.Length - 1;
|
||
|
||
for (int i = 0; i < nodeCount; i++)
|
||
{
|
||
string nodeName = row[i];
|
||
|
||
// 判断当前节点是否携带数据:只有当它是这一行的最后一个生成节点时,才携带数据
|
||
bool isLastNodeInRow = (i == nodeCount - 1);
|
||
string payload = isLastNodeInRow ? row[row.Length - 1] : null;
|
||
|
||
// 确保当前父节点在缓存中有对应的子节点字典
|
||
if (!nodeCache.ContainsKey(currentParent))
|
||
{
|
||
nodeCache[currentParent] = new Dictionary<string, TreeViewItem>();
|
||
}
|
||
var childrenMap = nodeCache[currentParent];
|
||
|
||
TreeViewItem newNode;
|
||
|
||
// 1. 检查是否已存在同名子节点
|
||
if (childrenMap.TryGetValue(nodeName, out newNode))
|
||
{
|
||
// 节点已存在,直接复用
|
||
}
|
||
else
|
||
{
|
||
// 2. 创建新节点
|
||
if (currentParent == virtualRoot)
|
||
{
|
||
// 如果是虚拟根的直连子节点,直接添加到 mTreeView
|
||
newNode = mTreeView.AppendItem("ItemPrefab1");
|
||
}
|
||
else
|
||
{
|
||
// 否则添加到父节点的 ChildTree
|
||
newNode = currentParent.ChildTree.AppendItem("ItemPrefab1");
|
||
}
|
||
|
||
// 3. 设置信息
|
||
var script = newNode.GetComponent<ItemScript2>();
|
||
if (script != null)
|
||
{
|
||
if (!string.IsNullOrEmpty(payload))
|
||
{
|
||
// 有数据:SetItemInfo("", "名称", "数据")
|
||
script.SetItemInfo("", nodeName, payload);
|
||
}
|
||
else
|
||
{
|
||
// 无数据:SetItemInfo("", "名称")
|
||
script.SetItemInfo("", nodeName);
|
||
}
|
||
}
|
||
|
||
// 4. 加入缓存,方便后续行复用
|
||
childrenMap[nodeName] = newNode;
|
||
|
||
// 为新节点初始化一个空的子节点字典(预防未来可能有更深层级)
|
||
nodeCache[newNode] = new Dictionary<string, TreeViewItem>();
|
||
}
|
||
|
||
// 5. 更新父节点,进入下一层循环
|
||
currentParent = newNode;
|
||
}
|
||
}
|
||
|
||
Debug.Log("TreeView 构建完成!共处理 " + datas.Count + " 条数据。");
|
||
}
|
||
void OnItemExpandBegin(TreeViewItem item)
|
||
{
|
||
ItemScript2 st = item.GetComponent<ItemScript2>();
|
||
st.SetExpandStatus(true);
|
||
}
|
||
|
||
void OnItemCollapseBegin(TreeViewItem item)
|
||
{
|
||
ItemScript2 st = item.GetComponent<ItemScript2>();
|
||
st.SetExpandStatus(false);
|
||
}
|
||
|
||
void OnItemCustomEvent(TreeViewItem item, CustomEvent customEvent, System.Object param)
|
||
{
|
||
if (customEvent == CustomEvent.ItemClicked)
|
||
{
|
||
ItemScript2 st = item.GetComponent<ItemScript2>();
|
||
if (mCurSelectedItemId > 0)
|
||
{
|
||
if (item.ItemId == mCurSelectedItemId)
|
||
{
|
||
return;
|
||
}
|
||
TreeViewItem curSelectedItem = mTreeView.GetTreeItemById(mCurSelectedItemId);
|
||
if (curSelectedItem != null)
|
||
{
|
||
curSelectedItem.GetComponent<ItemScript2>().IsSelected = false;
|
||
}
|
||
mCurSelectedItemId = 0;
|
||
}
|
||
st.IsSelected = true;
|
||
mCurSelectedItemId = item.ItemId;
|
||
Debug.Log((string)param);
|
||
}
|
||
}
|
||
|
||
void OnTreeListAddOneItem(TreeList treeList)
|
||
{
|
||
int count = treeList.ItemCount;
|
||
TreeViewItem parentTreeItem = treeList.ParentTreeItem;
|
||
if (count > 0 && parentTreeItem != null)
|
||
{
|
||
ItemScript2 st = parentTreeItem.GetComponent<ItemScript2>();
|
||
st.SetExpandBtnVisible(true);
|
||
st.SetExpandStatus(parentTreeItem.IsExpand);
|
||
}
|
||
}
|
||
|
||
TreeViewItem CurSelectedItem
|
||
{
|
||
get
|
||
{
|
||
if (mCurSelectedItemId <= 0)
|
||
{
|
||
return null;
|
||
}
|
||
TreeViewItem item = mTreeView.GetTreeItemById(mCurSelectedItemId);
|
||
if (item == null)
|
||
{
|
||
mCurSelectedItemId = 0;
|
||
return null;
|
||
}
|
||
return item;
|
||
}
|
||
}
|
||
|
||
public void OnExpandAllBtnClicked()
|
||
{
|
||
mTreeView.ExpandAllItem();
|
||
}
|
||
public void OnCollapseAllBtnClicked()
|
||
{
|
||
mTreeView.CollapseAllItem();
|
||
}
|
||
|
||
public void OnExpandBtnClicked()
|
||
{
|
||
TreeViewItem item = CurSelectedItem;
|
||
if (item == null)
|
||
{
|
||
Debug.Log("Please Select a Item First");
|
||
return;
|
||
}
|
||
item.Expand();
|
||
}
|
||
|
||
public void OnCollapseBtnClicked()
|
||
{
|
||
TreeViewItem item = CurSelectedItem;
|
||
if (item == null)
|
||
{
|
||
Debug.Log("Please Select a Item First");
|
||
return;
|
||
}
|
||
item.Collapse();
|
||
}
|
||
|
||
public void OnInsertBeforeBtnClicked()
|
||
{
|
||
mNewItemCount++;
|
||
if (mTreeView.IsEmpty)
|
||
{
|
||
TreeViewItem childItem = mTreeView.InsertItem(0, "ItemPrefab1");
|
||
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
|
||
}
|
||
else
|
||
{
|
||
TreeViewItem item = CurSelectedItem;
|
||
if (item == null)
|
||
{
|
||
Debug.Log("Please Select a Item First");
|
||
return;
|
||
}
|
||
TreeViewItem childItem = item.ParentTreeList.InsertItem(item.ItemIndex, "ItemPrefab1");
|
||
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
|
||
}
|
||
|
||
}
|
||
|
||
public void OnInsertAfterBtnClicked()
|
||
{
|
||
mNewItemCount++;
|
||
if (mTreeView.IsEmpty)
|
||
{
|
||
TreeViewItem childItem = mTreeView.InsertItem(0, "ItemPrefab1");
|
||
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
|
||
}
|
||
else
|
||
{
|
||
TreeViewItem item = CurSelectedItem;
|
||
if (item == null)
|
||
{
|
||
Debug.Log("Please Select a Item First");
|
||
return;
|
||
}
|
||
TreeViewItem childItem = item.ParentTreeList.InsertItem(item.ItemIndex + 1, "ItemPrefab1");
|
||
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
|
||
}
|
||
}
|
||
|
||
public void OnAddChildBtnClicked()
|
||
{
|
||
mNewItemCount++;
|
||
if (mTreeView.IsEmpty)
|
||
{
|
||
TreeViewItem childItem = mTreeView.AppendItem("ItemPrefab1");
|
||
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
|
||
}
|
||
else
|
||
{
|
||
TreeViewItem item = CurSelectedItem;
|
||
if (item == null)
|
||
{
|
||
Debug.Log("Please Select a Item First");
|
||
return;
|
||
}
|
||
TreeViewItem childItem = item.ChildTree.AppendItem("ItemPrefab1");
|
||
childItem.GetComponent<ItemScript2>().SetItemInfo("movie", "Movie" + mNewItemCount);
|
||
}
|
||
}
|
||
|
||
public void OnDeleteBtnClicked()
|
||
{
|
||
TreeViewItem item = CurSelectedItem;
|
||
if (item == null)
|
||
{
|
||
Debug.Log("Please Select a Item First");
|
||
return;
|
||
}
|
||
item.ParentTreeList.DeleteItem(item);
|
||
}
|
||
|
||
public void OnBackBtnClicked()
|
||
{
|
||
UnityEngine.SceneManagement.SceneManager.LoadScene("MainMenu");
|
||
}
|
||
|
||
void SetRectTransformHeight(RectTransform rt,float height)
|
||
{
|
||
Vector2 size = rt.sizeDelta;
|
||
size.y = height;
|
||
rt.sizeDelta = size;
|
||
}
|
||
|
||
void OnTreeListRepositionFinish(TreeList treeList)
|
||
{
|
||
int count = treeList.ItemCount;
|
||
if(count == 0)
|
||
{
|
||
return;
|
||
}
|
||
//draw the line linked from item to item
|
||
TreeViewItem item0 = treeList.GetItemByIndex(0);
|
||
ItemScript2 itemScript0 = item0.GetComponent<ItemScript2>();
|
||
float topY = item0.transform.localPosition.y - item0.CachedRectTransform.rect.height / 2;
|
||
RectTransform rt0 = itemScript0.mLineVertical.GetComponent<RectTransform>();
|
||
RectTransform lineRf= rt0;
|
||
for (int i = 1; i< count ; ++i)
|
||
{
|
||
TreeViewItem item = treeList.GetItemByIndex(i);
|
||
ItemScript2 itemScript = item.GetComponent<ItemScript2>();
|
||
float centerY = item.transform.localPosition.y - item.CachedRectTransform.rect.height / 2;
|
||
float dist = topY - centerY;
|
||
topY = centerY;
|
||
RectTransform rt = itemScript.mLineVertical.GetComponent<RectTransform>();
|
||
//set the line length
|
||
SetRectTransformHeight(lineRf, dist);
|
||
lineRf = rt;
|
||
|
||
}
|
||
SetRectTransformHeight(lineRf, 0);
|
||
|
||
//draw the line linked from item to item' childTree
|
||
for (int i = 0; i < count; ++i)
|
||
{
|
||
TreeViewItem item = treeList.GetItemByIndex(i);
|
||
ItemScript2 itemScript = item.GetComponent<ItemScript2>();
|
||
RectTransform rt2 = itemScript.mLineVertical_2.GetComponent<RectTransform>();
|
||
|
||
if (item.ChildItemCount > 0 && item.IsCollapseEnd == false)
|
||
{
|
||
//get the childTree's first item
|
||
TreeViewItem childItem0 = item.ChildTree.GetItemByIndex(0);
|
||
ItemScript2 childItemScript0 = childItem0.GetComponent<ItemScript2>();
|
||
Vector3 pos0 = item.transform.InverseTransformPoint(childItemScript0.mExpandBtn.transform.position);
|
||
float dist2 = rt2.localPosition.y - pos0.y;
|
||
//set the line length
|
||
SetRectTransformHeight(rt2, dist2);
|
||
}
|
||
else
|
||
{
|
||
SetRectTransformHeight(rt2, 0);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
} |