using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; namespace WeChatWASM.Analysis { public class CommonTreeView : TreeView where T : class { private List> m_items; private Boolean isAllCheck; private Action m_toggleSelectAll; private readonly List m_datas; public CommonTreeView( TreeViewState state, MultiColumnHeader multiColumnHeader, List datas, FilterMethod filter, SelectMethod select = null, Action toggleSelectAll = null) : base(state, multiColumnHeader) { m_datas = datas; m_filter = filter; m_select = select; m_toggleSelectAll = toggleSelectAll; multiColumnHeader.sortingChanged += OnSortingChanged; multiColumnHeader.visibleColumnsChanged += OnVisibleColumnChanged; showAlternatingRowBackgrounds = true; showBorder = true; rowHeight = EditorGUIUtility.singleLineHeight; } private void OnVisibleColumnChanged(MultiColumnHeader multicolumnheader) { Reload(); } private void OnSortingChanged(MultiColumnHeader multicolumnheader) { var rows = GetRows(); Sort(rows, multiColumnHeader.sortedColumnIndex); } protected override TreeViewItem BuildRoot() { return new CommonTreeViewItem(-1, -1, null); } protected override IList BuildRows(TreeViewItem root) { if (m_items == null) { m_items = new List>(); for (var i = 0; i < m_datas.Count; i++) { var data = m_datas[i]; m_items.Add(new CommonTreeViewItem(i, 0, data)); } } var items = m_items; if (!string.IsNullOrEmpty(m_text)) items = Filter(items); var list = new List(); foreach (var item in items) { list.Add(item); } if (multiColumnHeader.sortedColumnIndex >= 0) Sort(list, multiColumnHeader.sortedColumnIndex); return items.Cast().ToList(); } private readonly FilterMethod m_filter; [CanBeNull] private readonly SelectMethod m_select; private List> Filter(IEnumerable> rows) { var enumerable = rows; var i = 0; if (IsColumnVisible(i) && m_filter != null) { enumerable = from item in enumerable where m_filter(item.Data, m_text) select item; } return enumerable.ToList(); } private CommonTableColumn Col(int idx) { return (CommonTableColumn)multiColumnHeader.state.columns[idx]; } private void Sort(IList rows, int sortIdx) { var flag = multiColumnHeader.IsSortedAscending(sortIdx); var comp = Col(sortIdx).Compare; var list = (List)rows; if (comp != null) { Comparison comparison = (lhs, rhs) => { var x1 = (CommonTreeViewItem)lhs; var x2 = (CommonTreeViewItem)rhs; return comp(x1.Data, x2.Data); }; Comparison comparison2 = (lhs, rhs) => { var x1 = (CommonTreeViewItem)lhs; var x2 = (CommonTreeViewItem)rhs; return -comp(x1.Data, x2.Data); }; list.Sort(!flag ? comparison2 : comparison); } } protected override void RowGUI(RowGUIArgs args) { var item = (CommonTreeViewItem)args.item; for (var i = 0; i < args.GetNumVisibleColumns(); i++) { CellGUI(args.GetCellRect(i), item.Data, args.GetColumn(i)); } } private void CellGUI(Rect cellRect, T item, int columnIndex) { CenterRectUsingSingleLineHeight(ref cellRect); var column = (CommonTableColumn)multiColumnHeader.GetColumn(columnIndex); if (column.DrawCell != null) column.DrawCell(cellRect, item); } public void OnCheckAllGUI() { var selectedList = this.GetSelection(); if (selectedList.Count != m_datas.Count) { isAllCheck = false; } var newState = GUI.Toggle(new Rect(5, 20, 50, 20), isAllCheck, "全选"); if (newState != isAllCheck) { isAllCheck = newState; if (isAllCheck) { if (m_datas.Count != 0) { this.SelectAllRows(); } } else { this.SetSelection(new List()); } if (m_toggleSelectAll != null) { m_toggleSelectAll(isAllCheck); } } } public void OnFilterGUI(Rect r) { EditorGUI.BeginChangeCheck(); var width = r.width; var num = 16f; r.width = num; r.x += num; r.width = GUI.skin.label.CalcSize(Styles.filterSelection).x; //EditorGUI.LabelField(r, Styles.filterSelection); r.width = Mathf.Min(width - (r.x + r.width), 300f); r.x = width - r.width + 25; FilterGUI(r); if (EditorGUI.EndChangeCheck()) { Reload(); } } private string m_text; private void FilterGUI(Rect r) { r.width -= 15f; //GUI.SetNextControlName("InputText"); m_text = EditorGUI.DelayedTextField(r, GUIContent.none, m_text, Styles.searchField); //EditorGUI.FocusTextInControl("InputText"); r.x += r.width; r.width = 15f; bool flag = m_text != ""; if (GUI.Button(r, GUIContent.none, (!flag) ? Styles.searchFieldCancelButtonEmpty : Styles.searchFieldCancelButton) && flag) { m_text = ""; GUIUtility.keyboardControl = 0; } } private bool IsColumnVisible(int idx) { return multiColumnHeader.state.visibleColumns.Any(t => t == idx); } protected override void KeyEvent() { if (Event.current.type == EventType.KeyDown) { if (Event.current.character == '\t') { GUI.FocusControl(Styles.focusHelper); Event.current.Use(); } } } protected override void SelectionChanged(IList selectedIds) { var datas = new List(); foreach (var id in selectedIds) { if (id < 0 || id > m_datas.Count) { Debug.Log(id + "out of range"); continue; } var data = m_datas[id]; datas.Add(data); } if (m_select != null) m_select(datas); } } public class CommonTableColumn : MultiColumnHeaderState.Column { public DrawCellMethod DrawCell; //public IFilter Filter; public CompareMethod Compare { get; set; } } //public interface IFilter //{ // void OnGUI(Rect r); //} //public interface IFilter : IFilter //{ // bool Filter(T prop); //} //public class StringFilter //{ // [SerializeField] // protected string m_Text = ""; // public void OnGUI(Rect r) // { // } // public bool Filter(string prop) // { // return prop.IndexOf(m_Text, 0, StringComparison.OrdinalIgnoreCase) >= 0; // } //} }