| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- #if UNITY_2019_4_OR_NEWER
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor;
- using UnityEngine;
- using UnityEditor.UIElements;
- using UnityEngine.UIElements;
- namespace YooAsset.Editor
- {
- /// <summary>
- /// Unity2022版本以上推荐官方类:MultiColumnListView组件
- /// </summary>
- //[UxmlElement]
- public partial class TableViewer : VisualElement
- {
- private readonly Toolbar _toolbar;
- private readonly ListView _listView;
- private readonly List<TableColumn> _columns = new List<TableColumn>(10);
- private List<ITableData> _itemsSource;
- private List<ITableData> _sortingDatas;
- // 排序相关
- private string _sortingHeader;
- private bool _descendingSort = true;
- /// <summary>
- /// 数据源
- /// </summary>
- public List<ITableData> itemsSource
- {
- get
- {
- return _itemsSource;
- }
- set
- {
- if (CheckItemsSource(value))
- {
- _itemsSource = value;
- _sortingDatas = value;
- }
- }
- }
- /// <summary>
- /// 选中的数据列表
- /// </summary>
- public List<ITableData> selectedItems
- {
- get
- {
- #if UNITY_2020_3_OR_NEWER
- return _listView.selectedItems.Cast<ITableData>().ToList();
- #else
- List<ITableData> result = new List<ITableData>();
- result.Add(_listView.selectedItem as ITableData);
- return result;
- #endif
- }
- }
- /// <summary>
- /// 单元视图交互事件
- /// </summary>
- public Action<PointerDownEvent, ITableData> ClickTableDataEvent;
- /// <summary>
- /// 单元视图交互事件
- /// </summary>
- public Action<TableColumn> ClickTableHeadEvent;
- /// <summary>
- /// 单元视图变化事件
- /// </summary>
- public Action<ITableData> SelectionChangedEvent;
- public TableViewer()
- {
- this.style.flexShrink = 1f;
- this.style.flexGrow = 1f;
- // 定义标题栏
- _toolbar = new Toolbar();
- // 定义列表视图
- _listView = new ListView();
- _listView.style.flexShrink = 1f;
- _listView.style.flexGrow = 1f;
- _listView.makeItem = MakeListViewElement;
- _listView.bindItem = BindListViewElement;
- _listView.selectionType = SelectionType.Multiple;
- _listView.RegisterCallback<PointerDownEvent>(OnClickListItem);
- #if UNITY_2022_3_OR_NEWER
- _listView.selectionChanged += OnSelectionChanged;
- #elif UNITY_2020_1_OR_NEWER
- _listView.onSelectionChange += OnSelectionChanged;
- #else
- _listView.onSelectionChanged += OnSelectionChanged;
- #endif
- this.Add(_toolbar);
- this.Add(_listView);
- }
- /// <summary>
- /// 获取标题UI元素
- /// </summary>
- public VisualElement GetHeaderElement(string elementName)
- {
- return _toolbar.Q<ToolbarButton>(elementName);
- }
- /// <summary>
- /// 添加单元列
- /// </summary>
- public void AddColumn(TableColumn column)
- {
- var toolbarBtn = new ToolbarButton();
- toolbarBtn.userData = column;
- toolbarBtn.name = column.ElementName;
- toolbarBtn.text = column.HeaderTitle;
- toolbarBtn.style.flexGrow = 0;
- toolbarBtn.style.width = column.ColumnStyle.Width;
- toolbarBtn.style.minWidth = column.ColumnStyle.Width;
- toolbarBtn.style.maxWidth = column.ColumnStyle.Width;
- toolbarBtn.clickable.clickedWithEventInfo += OnClickTableHead;
- SetCellElementStyle(toolbarBtn);
- _toolbar.Add(toolbarBtn);
- _columns.Add(column);
- // 可伸缩控制柄
- if (column.ColumnStyle.Stretchable)
- {
- int handleWidth = 3;
- int minWidth = (int)column.ColumnStyle.MinWidth.value;
- int maxWidth = (int)column.ColumnStyle.MaxWidth.value;
- var resizeHandle = new ResizeHandle(handleWidth, toolbarBtn, minWidth, maxWidth);
- resizeHandle.ResizeChanged += (float value) =>
- {
- float width = Mathf.Clamp(value, column.ColumnStyle.MinWidth.value, column.ColumnStyle.MaxWidth.value);
- column.ColumnStyle.Width = width;
- foreach (var element in column.CellElements)
- {
- element.style.width = width;
- element.style.minWidth = width;
- element.style.maxWidth = width;
- }
- };
- _toolbar.Add(resizeHandle);
- }
- // 计算索引值
- column.ColumnIndex = _columns.Count - 1;
- if (column.ColumnStyle.Sortable == false)
- toolbarBtn.SetEnabled(false);
- }
- /// <summary>
- /// 添加单元列集合
- /// </summary>
- public void AddColumns(IList<TableColumn> columns)
- {
- foreach (var column in columns)
- {
- AddColumn(column);
- }
- }
- /// <summary>
- /// 重建表格视图
- /// </summary>
- public void RebuildView()
- {
- if (_itemsSource == null)
- return;
- var itemsSource = _sortingDatas.Where(row => row.Visible);
- _listView.Clear();
- _listView.ClearSelection();
- _listView.itemsSource = itemsSource.ToList();
- _listView.Rebuild();
- // 刷新标题栏
- RefreshToobar();
- }
- private void RefreshToobar()
- {
- // 设置为原始标题
- foreach (var column in _columns)
- {
- var toobarButton = _toolbar.Q<ToolbarButton>(column.ElementName);
- toobarButton.text = column.HeaderTitle;
- }
- // 设置元素数量
- foreach (var column in _columns)
- {
- if (column.ColumnStyle.Counter)
- {
- var toobarButton = GetHeaderElement(column.ElementName) as ToolbarButton;
- toobarButton.text = $"{toobarButton.text} ({itemsSource.Count()})";
- }
- }
- // 设置展示单位
- foreach (var column in _columns)
- {
- if (string.IsNullOrEmpty(column.ColumnStyle.Units) == false)
- {
- var toobarButton = GetHeaderElement(column.ElementName) as ToolbarButton;
- toobarButton.text = $"{toobarButton.text} ({column.ColumnStyle.Units})";
- }
- }
- // 设置升降符号
- if (string.IsNullOrEmpty(_sortingHeader) == false)
- {
- var _toobarButton = _toolbar.Q<ToolbarButton>(_sortingHeader);
- if (_descendingSort)
- _toobarButton.text = $"{_toobarButton.text} ↓";
- else
- _toobarButton.text = $"{_toobarButton.text} ↑";
- }
- }
- /// <summary>
- /// 清空所有数据
- /// </summary>
- public void ClearAll(bool clearColumns, bool clearSource)
- {
- if (clearColumns)
- {
- _columns.Clear();
- _toolbar.Clear();
- }
- if (clearSource)
- {
- if (_itemsSource != null)
- _itemsSource.Clear();
- if (_sortingDatas != null)
- _sortingDatas.Clear();
- _listView.Clear();
- _listView.ClearSelection();
- }
- }
- private void OnClickListItem(PointerDownEvent evt)
- {
- var selectData = _listView.selectedItem as ITableData;
- if (selectData == null)
- return;
- ClickTableDataEvent?.Invoke(evt, selectData);
- }
- private void OnClickTableHead(EventBase eventBase)
- {
- if (_itemsSource == null)
- return;
- ToolbarButton toolbarBtn = eventBase.target as ToolbarButton;
- var clickedColumn = toolbarBtn.userData as TableColumn;
- if (clickedColumn == null)
- return;
- ClickTableHeadEvent?.Invoke(clickedColumn);
- if (clickedColumn.ColumnStyle.Sortable == false)
- return;
- if (_sortingHeader != clickedColumn.ElementName)
- {
- _sortingHeader = clickedColumn.ElementName;
- _descendingSort = false;
- }
- else
- {
- _descendingSort = !_descendingSort;
- }
- // 升降排序
- if (_descendingSort)
- _sortingDatas = _itemsSource.OrderByDescending(tableData => tableData.Cells[clickedColumn.ColumnIndex]).ToList();
- else
- _sortingDatas = _itemsSource.OrderBy(tableData => tableData.Cells[clickedColumn.ColumnIndex]).ToList();
- // 刷新数据表
- RebuildView();
- }
- private void OnSelectionChanged(IEnumerable<object> items)
- {
- foreach (var item in items)
- {
- var tableData = item as ITableData;
- SelectionChangedEvent?.Invoke(tableData);
- break;
- }
- }
- private bool CheckItemsSource(List<ITableData> itemsSource)
- {
- if (itemsSource == null)
- return false;
- if (itemsSource.Count > 0)
- {
- int cellCount = itemsSource[0].Cells.Count;
- for (int i = 0; i < itemsSource.Count; i++)
- {
- var tableData = itemsSource[i];
- if (tableData == null)
- {
- Debug.LogWarning($"Items source has null instance !");
- return false;
- }
- if (tableData.Cells == null || tableData.Cells.Count == 0)
- {
- Debug.LogWarning($"Items source data has empty cells !");
- return false;
- }
- if (tableData.Cells.Count != cellCount)
- {
- Debug.LogWarning($"Items source data has inconsisten cells count ! Item index {i}");
- return false;
- }
- }
- }
- return true;
- }
- private VisualElement MakeListViewElement()
- {
- VisualElement listViewElement = new VisualElement();
- listViewElement.style.flexDirection = FlexDirection.Row;
- foreach (var column in _columns)
- {
- var cellElement = column.MakeCell.Invoke();
- cellElement.name = column.ElementName;
- cellElement.style.flexGrow = 0f;
- cellElement.style.width = column.ColumnStyle.Width;
- cellElement.style.minWidth = column.ColumnStyle.Width;
- cellElement.style.maxWidth = column.ColumnStyle.Width;
- SetCellElementStyle(cellElement);
- listViewElement.Add(cellElement);
- column.CellElements.Add(cellElement);
- }
- return listViewElement;
- }
- private void BindListViewElement(VisualElement listViewElement, int index)
- {
- var sourceDatas = _listView.itemsSource as List<ITableData>;
- var tableData = sourceDatas[index];
- foreach (var colum in _columns)
- {
- var cellElement = listViewElement.Q(colum.ElementName);
- var tableCell = tableData.Cells[colum.ColumnIndex];
- colum.BindCell.Invoke(cellElement, tableData, tableCell);
- }
- }
- private void SetCellElementStyle(VisualElement element)
- {
- StyleLength defaultStyle = new StyleLength(1f);
- element.style.paddingTop = defaultStyle;
- element.style.paddingBottom = defaultStyle;
- element.style.marginTop = defaultStyle;
- element.style.marginBottom = defaultStyle;
- element.style.paddingLeft = 1;
- element.style.paddingRight = 1;
- element.style.marginLeft = 0;
- element.style.marginRight = 0;
- }
- }
- }
- #endif
|