Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/UIWidgets/ListView.cs
2026-02-21 16:45:37 +08:00

1026 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using EasyLayout;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace UIWidgets
{
[AddComponentMenu("UI/ListView", 250)]
public class ListView : ListViewBase
{
[SerializeField]
[Obsolete("Use DataSource instead.")]
private List<string> strings = new List<string>();
private ObservableList<string> dataSource;
[SerializeField]
private TextAsset file;
[SerializeField]
public List<string> CommentsStartWith = new List<string> { "#", "//" };
[SerializeField]
public ListViewSources Source;
[SerializeField]
public bool Unique = true;
[SerializeField]
public bool AllowEmptyItems;
[SerializeField]
private Color backgroundColor = Color.white;
[SerializeField]
private Color textColor = Color.black;
[SerializeField]
public Color HighlightedBackgroundColor = new Color(203f, 230f, 244f, 255f);
[SerializeField]
public Color HighlightedTextColor = Color.black;
[SerializeField]
private Color selectedBackgroundColor = new Color(53f, 83f, 227f, 255f);
[SerializeField]
private Color selectedTextColor = Color.black;
[SerializeField]
public ImageAdvanced DefaultItem;
private List<ListViewStringComponent> components = new List<ListViewStringComponent>();
private List<UnityAction<PointerEventData>> callbacksEnter = new List<UnityAction<PointerEventData>>();
private List<UnityAction<PointerEventData>> callbacksExit = new List<UnityAction<PointerEventData>>();
[FormerlySerializedAs("Sort")]
[SerializeField]
private bool sort = true;
private Func<IEnumerable<string>, IEnumerable<string>> sortFunc = (IEnumerable<string> items) => items.OrderBy((string x) => x);
public ListViewEvent OnSelectString = new ListViewEvent();
public ListViewEvent OnDeselectString = new ListViewEvent();
[SerializeField]
private ScrollRect scrollRect;
private float itemHeight;
private float itemWidth;
private float scrollHeight;
private float scrollWidth;
private int maxVisibleItems;
private int visibleItems;
private int topHiddenItems;
private int bottomHiddenItems;
[SerializeField]
private ListViewDirection direction = ListViewDirection.Vertical;
[NonSerialized]
private bool isStartedListView;
private LayoutGroup layout;
protected ILayoutBridge LayoutBridge;
private List<string> SelectedItemsCache;
private List<ListViewStringComponent> componentsCache = new List<ListViewStringComponent>();
private bool needResize;
public ObservableList<string> DataSource
{
get
{
if (dataSource == null)
{
dataSource = new ObservableList<string>(strings);
dataSource.OnChange += UpdateItems;
strings = null;
}
return dataSource;
}
set
{
SetNewItems(value);
SetScrollValue(0f);
}
}
[Obsolete("Use DataSource instead.")]
public List<string> Strings
{
get
{
return new List<string>(DataSource);
}
set
{
SetNewItems(new ObservableList<string>(value));
SetScrollValue(0f);
}
}
[Obsolete("Use DataSource instead.")]
public new List<string> Items
{
get
{
return new List<string>(DataSource);
}
set
{
SetNewItems(new ObservableList<string>(value));
SetScrollValue(0f);
}
}
public TextAsset File
{
get
{
return file;
}
set
{
file = value;
if (file != null)
{
GetItemsFromFile(file);
SetScrollValue(0f);
}
}
}
public Color BackgroundColor
{
get
{
return backgroundColor;
}
set
{
backgroundColor = value;
UpdateColors();
}
}
public Color TextColor
{
get
{
return textColor;
}
set
{
textColor = value;
UpdateColors();
}
}
public Color SelectedBackgroundColor
{
get
{
return selectedBackgroundColor;
}
set
{
selectedBackgroundColor = value;
UpdateColors();
}
}
public Color SelectedTextColor
{
get
{
return selectedTextColor;
}
set
{
selectedTextColor = value;
UpdateColors();
}
}
public bool Sort
{
get
{
return sort;
}
set
{
sort = value;
if (Sort && isStartedListView && sortFunc != null)
{
UpdateItems();
}
}
}
public Func<IEnumerable<string>, IEnumerable<string>> SortFunc
{
get
{
return sortFunc;
}
set
{
sortFunc = value;
if (Sort && isStartedListView && sortFunc != null)
{
UpdateItems();
}
}
}
public ScrollRect ScrollRect
{
get
{
return scrollRect;
}
set
{
if (scrollRect != null)
{
ResizeListener component = scrollRect.GetComponent<ResizeListener>();
if (component != null)
{
component.OnResize.RemoveListener(SetNeedResize);
}
scrollRect.onValueChanged.RemoveListener(OnScrollUpdate);
}
scrollRect = value;
if (scrollRect != null)
{
ResizeListener resizeListener = scrollRect.GetComponent<ResizeListener>() ?? scrollRect.gameObject.AddComponent<ResizeListener>();
resizeListener.OnResize.AddListener(SetNeedResize);
scrollRect.onValueChanged.AddListener(OnScrollUpdate);
}
}
}
public ListViewDirection Direction
{
get
{
return direction;
}
set
{
direction = value;
if ((bool)scrollRect)
{
scrollRect.horizontal = IsHorizontal();
scrollRect.vertical = !IsHorizontal();
}
if (CanOptimize() && layout is global::EasyLayout.EasyLayout)
{
LayoutBridge.IsHorizontal = IsHorizontal();
CalculateMaxVisibleItems();
}
UpdateView();
}
}
public global::EasyLayout.EasyLayout Layout
{
get
{
return layout as global::EasyLayout.EasyLayout;
}
}
private void Awake()
{
Start();
}
public override void Start()
{
if (isStartedListView)
{
return;
}
isStartedListView = true;
base.Start();
base.Items = new List<ListViewItem>();
SelectedItemsCache = base.SelectedIndicies.Convert(GetDataItem);
DestroyGameObjects = false;
if (DefaultItem == null)
{
throw new NullReferenceException("DefaultItem is null. Set component of type ImageAdvanced to DefaultItem.");
}
DefaultItem.gameObject.SetActive(true);
if (DefaultItem.GetComponentInChildren<Text>() == null)
{
throw new MissingComponentException("DefaultItem don't have child with 'Text' component. Add child with 'Text' component to DefaultItem.");
}
if (CanOptimize())
{
ScrollRect = scrollRect;
RectTransform rectTransform = scrollRect.transform as RectTransform;
scrollHeight = rectTransform.rect.height;
scrollWidth = rectTransform.rect.width;
layout = Container.GetComponent<LayoutGroup>();
if (layout is global::EasyLayout.EasyLayout)
{
LayoutBridge = new EasyLayoutBridge(layout as global::EasyLayout.EasyLayout, DefaultItem.transform as RectTransform);
LayoutBridge.IsHorizontal = IsHorizontal();
}
else if (layout is HorizontalOrVerticalLayoutGroup)
{
LayoutBridge = new StandardLayoutBridge(layout as HorizontalOrVerticalLayoutGroup, DefaultItem.transform as RectTransform);
}
CalculateItemSize();
CalculateMaxVisibleItems();
}
DefaultItem.gameObject.SetActive(false);
UpdateItems();
OnSelect.AddListener(OnSelectCallback);
OnDeselect.AddListener(OnDeselectCallback);
}
protected virtual void CalculateItemSize()
{
if (LayoutBridge != null)
{
Vector2 itemSize = LayoutBridge.GetItemSize();
itemHeight = itemSize.y;
itemWidth = itemSize.x;
}
}
protected string GetDataItem(int index)
{
return DataSource[index];
}
protected bool IsHorizontal()
{
return direction == ListViewDirection.Horizontal;
}
private void CalculateMaxVisibleItems()
{
if (IsHorizontal())
{
maxVisibleItems = Mathf.CeilToInt(scrollWidth / itemWidth) + 1;
}
else
{
maxVisibleItems = Mathf.CeilToInt(scrollHeight / itemHeight) + 1;
}
}
private void Resize()
{
needResize = false;
RectTransform rectTransform = scrollRect.transform as RectTransform;
scrollHeight = rectTransform.rect.height;
scrollWidth = rectTransform.rect.width;
CalculateMaxVisibleItems();
UpdateView();
}
private bool CanOptimize()
{
return scrollRect != null && (layout != null || Container.GetComponent<global::EasyLayout.EasyLayout>() != null);
}
private void OnSelectCallback(int index, ListViewItem item)
{
if (SelectedItemsCache != null)
{
SelectedItemsCache.Add(DataSource[index]);
}
OnSelectString.Invoke(index, DataSource[index]);
if (item != null)
{
SelectColoring(item as ListViewStringComponent);
}
}
private void OnDeselectCallback(int index, ListViewItem item)
{
if (SelectedItemsCache != null)
{
SelectedItemsCache.Remove(DataSource[index]);
}
OnDeselectString.Invoke(index, DataSource[index]);
if (item != null)
{
DefaultColoring(item as ListViewStringComponent);
}
}
public override void UpdateItems()
{
if (Source == ListViewSources.List)
{
SetNewItems(DataSource);
return;
}
Source = ListViewSources.List;
GetItemsFromFile(File);
}
public override void Clear()
{
DataSource.Clear();
}
public void GetItemsFromFile()
{
GetItemsFromFile(File);
}
private string StringTrimEnd(string str)
{
return str.TrimEnd();
}
private bool IsStringNotEmpty(string str)
{
return str != string.Empty;
}
private bool NotComment(string str)
{
return !CommentsStartWith.Any((string comment) => str.StartsWith(comment));
}
public void GetItemsFromFile(TextAsset sourceFile)
{
if (!(file == null))
{
IEnumerable<string> enumerable = sourceFile.text.Split(new string[3] { "\r\n", "\r", "\n" }, StringSplitOptions.None).Select(StringTrimEnd);
if (Unique)
{
enumerable = enumerable.Distinct();
}
if (!AllowEmptyItems)
{
enumerable = enumerable.Where(IsStringNotEmpty);
}
if (CommentsStartWith.Count > 0)
{
enumerable = enumerable.Where(NotComment);
}
SetNewItems(enumerable.ToObservableList());
}
}
public virtual List<int> FindIndicies(string item)
{
return (from i in Enumerable.Range(0, DataSource.Count)
where DataSource[i] == item
select i).ToList();
}
public virtual int FindIndex(string item)
{
return DataSource.IndexOf(item);
}
public virtual int Add(string item)
{
List<int> second = ((!Sort || SortFunc == null) ? null : FindIndicies(item));
DataSource.Add(item);
if (Sort && SortFunc != null)
{
List<int> list = FindIndicies(item);
int[] array = list.Except(second).ToArray();
if (array.Length > 0)
{
return array[0];
}
if (list.Count > 0)
{
return list[0];
}
return -1;
}
return DataSource.Count - 1;
}
public virtual int Remove(string item)
{
int num = FindIndex(item);
if (num == -1)
{
return num;
}
DataSource.Remove(item);
return num;
}
private void RemoveCallback(ListViewStringComponent component, int index)
{
if (!(component == null))
{
if (index < callbacksEnter.Count)
{
component.onPointerEnter.RemoveListener(callbacksEnter[index]);
}
if (index < callbacksExit.Count)
{
component.onPointerExit.RemoveListener(callbacksExit[index]);
}
}
}
private void RemoveCallbacks()
{
components.ForEach(RemoveCallback);
callbacksEnter.Clear();
callbacksExit.Clear();
}
private void AddCallbacks()
{
components.ForEach(AddCallback);
}
private void AddCallback(ListViewStringComponent component, int index)
{
callbacksEnter.Add(delegate
{
OnPointerEnterCallback(component);
});
callbacksExit.Add(delegate
{
OnPointerExitCallback(component);
});
component.onPointerEnter.AddListener(callbacksEnter[index]);
component.onPointerExit.AddListener(callbacksExit[index]);
}
public override bool IsValid(int index)
{
return index >= 0 && index < DataSource.Count;
}
private void OnPointerEnterCallback(ListViewStringComponent component)
{
if (!IsValid(component.Index))
{
string message = string.Format("Index must be between 0 and Items.Count ({0})", DataSource.Count);
throw new IndexOutOfRangeException(message);
}
if (!IsSelected(component.Index))
{
HighlightColoring(component);
}
}
private void OnPointerExitCallback(ListViewStringComponent component)
{
if (!IsValid(component.Index))
{
string message = string.Format("Index must be between 0 and Items.Count ({0})", DataSource.Count);
throw new IndexOutOfRangeException(message);
}
if (!IsSelected(component.Index))
{
DefaultColoring(component);
}
}
protected void SetScrollValue(float value)
{
Vector2 anchoredPosition = scrollRect.content.anchoredPosition;
Vector2 vector = new Vector2(anchoredPosition.x, value);
if (vector != anchoredPosition)
{
scrollRect.content.anchoredPosition = vector;
ScrollUpdate();
}
}
protected float GetScrollValue()
{
Vector2 anchoredPosition = scrollRect.content.anchoredPosition;
return Mathf.Max(0f, (!IsHorizontal()) ? anchoredPosition.y : (0f - anchoredPosition.x));
}
protected float GetItemSize()
{
return (!IsHorizontal()) ? (itemHeight + LayoutBridge.GetSpacing()) : (itemWidth + LayoutBridge.GetSpacing());
}
protected float GetScrollSize()
{
return (!IsHorizontal()) ? scrollHeight : scrollWidth;
}
protected override void ScrollTo(int index)
{
if (CanOptimize())
{
int firstVisibleIndex = GetFirstVisibleIndex(true);
int lastVisibleIndex = GetLastVisibleIndex(true);
if (firstVisibleIndex > index)
{
float scrollValue = (float)index * GetItemSize();
SetScrollValue(scrollValue);
}
else if (lastVisibleIndex < index)
{
float scrollValue2 = (float)(index + 1) * GetItemSize() - LayoutBridge.GetSpacing() + LayoutBridge.GetMargin() - GetScrollSize();
SetScrollValue(scrollValue2);
}
}
}
private int GetLastVisibleIndex(bool strict = false)
{
float num = GetScrollValue() + GetScrollSize();
int num2 = ((!strict) ? Mathf.CeilToInt(num / GetItemSize()) : Mathf.FloorToInt(num / GetItemSize()));
return num2 - 1;
}
private int GetFirstVisibleIndex(bool strict = false)
{
int num = ((!strict) ? Mathf.FloorToInt(GetScrollValue() / GetItemSize()) : Mathf.CeilToInt(GetScrollValue() / GetItemSize()));
if (strict)
{
return num;
}
return Mathf.Min(num, Mathf.Max(0, DataSource.Count - visibleItems));
}
private ListViewStringComponent ComponentTopToBottom()
{
int index = components.Count - 1;
ListViewStringComponent listViewStringComponent = components[index];
components.RemoveAt(index);
components.Insert(0, listViewStringComponent);
listViewStringComponent.transform.SetAsFirstSibling();
return listViewStringComponent;
}
private ListViewStringComponent ComponentBottomToTop()
{
ListViewStringComponent listViewStringComponent = components[0];
components.RemoveAt(0);
components.Add(listViewStringComponent);
listViewStringComponent.transform.SetAsLastSibling();
return listViewStringComponent;
}
private void OnScrollUpdate(Vector2 position)
{
ScrollUpdate();
}
private void OnScroll(float value)
{
ScrollUpdate();
}
private void ScrollUpdate()
{
int num = topHiddenItems;
topHiddenItems = GetFirstVisibleIndex();
bottomHiddenItems = Mathf.Max(0, DataSource.Count - visibleItems - topHiddenItems);
if (num != topHiddenItems)
{
if (num == topHiddenItems + 1)
{
ListViewStringComponent listViewStringComponent = ComponentTopToBottom();
listViewStringComponent.Index = topHiddenItems;
listViewStringComponent.Text.text = DataSource[topHiddenItems];
Coloring(listViewStringComponent);
}
else if (num == topHiddenItems - 1)
{
ListViewStringComponent listViewStringComponent2 = ComponentBottomToTop();
int index = (listViewStringComponent2.Index = topHiddenItems + visibleItems - 1);
listViewStringComponent2.Text.text = DataSource[index];
Coloring(listViewStringComponent2);
}
else
{
int[] new_indicies = Enumerable.Range(topHiddenItems, visibleItems).ToArray();
components.ForEach(delegate(ListViewStringComponent x, int i)
{
x.Index = new_indicies[i];
x.Text.text = DataSource[new_indicies[i]];
Coloring(x);
});
}
}
if (LayoutBridge != null)
{
LayoutBridge.SetFiller(CalculateTopFillerSize(), CalculateBottomFillerSize());
LayoutBridge.UpdateLayout();
}
}
private bool IsNullComponent(ListViewStringComponent component)
{
return component == null;
}
private List<ListViewStringComponent> GetNewComponents()
{
componentsCache.RemoveAll(IsNullComponent);
List<ListViewStringComponent> new_components = new List<ListViewStringComponent>();
DataSource.ForEach(delegate(string x, int i)
{
if (i < visibleItems)
{
if (components.Count > 0)
{
new_components.Add(components[0]);
components.RemoveAt(0);
}
else if (componentsCache.Count > 0)
{
componentsCache[0].gameObject.SetActive(true);
new_components.Add(componentsCache[0]);
componentsCache.RemoveAt(0);
}
else
{
ImageAdvanced imageAdvanced = UnityEngine.Object.Instantiate(DefaultItem);
imageAdvanced.gameObject.SetActive(true);
ListViewStringComponent listViewStringComponent = imageAdvanced.GetComponent<ListViewStringComponent>();
if (listViewStringComponent == null)
{
listViewStringComponent = imageAdvanced.gameObject.AddComponent<ListViewStringComponent>();
listViewStringComponent.Background = imageAdvanced;
listViewStringComponent.Text = imageAdvanced.GetComponentInChildren<Text>();
}
Utilites.FixInstantiated(DefaultItem, imageAdvanced);
listViewStringComponent.gameObject.SetActive(true);
new_components.Add(listViewStringComponent);
}
}
});
components.ForEach(delegate(ListViewStringComponent x)
{
x.MovedToCache();
x.Index = -1;
x.gameObject.SetActive(false);
});
componentsCache.AddRange(components);
components.Clear();
return new_components;
}
private void UpdateView()
{
RemoveCallbacks();
if (CanOptimize() && DataSource.Count > 0)
{
visibleItems = ((maxVisibleItems >= DataSource.Count) ? DataSource.Count : maxVisibleItems);
}
else
{
visibleItems = DataSource.Count;
}
components = GetNewComponents();
base.Items = components.Convert((Converter<ListViewStringComponent, ListViewItem>)((ListViewStringComponent x) => x));
components.ForEach(SetComponentData);
AddCallbacks();
topHiddenItems = 0;
bottomHiddenItems = DataSource.Count() - visibleItems;
if (LayoutBridge != null)
{
LayoutBridge.SetFiller(CalculateTopFillerSize(), CalculateBottomFillerSize());
LayoutBridge.UpdateLayout();
}
if (scrollRect != null)
{
RectTransform rectTransform = scrollRect.transform as RectTransform;
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, rectTransform.rect.width);
}
}
private void SetComponentData(ListViewStringComponent component, int index)
{
component.Index = index;
component.Text.text = DataSource[index];
Coloring(component);
}
private bool IndexNotFound(int index)
{
return index == -1;
}
private void SetNewItems(ObservableList<string> newItems)
{
DataSource.OnChange -= UpdateItems;
if (Sort && SortFunc != null)
{
newItems.BeginUpdate();
string[] array = SortFunc(newItems).ToArray();
newItems.Clear();
newItems.AddRange(array);
newItems.EndUpdate();
}
SilentDeselect(base.SelectedIndicies);
List<int> list = SelectedItemsCache.Convert(newItems.IndexOf);
list.RemoveAll(IndexNotFound);
dataSource = newItems;
SilentSelect(list);
SelectedItemsCache = base.SelectedIndicies.Convert(GetDataItem);
UpdateView();
DataSource.OnChange += UpdateItems;
}
private float CalculateBottomFillerSize()
{
return (bottomHiddenItems != 0) ? ((float)bottomHiddenItems * GetItemSize() - LayoutBridge.GetSpacing()) : 0f;
}
private float CalculateTopFillerSize()
{
return (topHiddenItems != 0) ? ((float)topHiddenItems * GetItemSize() - LayoutBridge.GetSpacing()) : 0f;
}
private List<int> NewSelectedIndicies(ObservableList<string> newItems)
{
List<int> selected_indicies = new List<int>();
if (newItems.Count == 0)
{
return selected_indicies;
}
List<string> new_items_copy = new List<string>(newItems);
List<string> selected_items = base.SelectedIndicies.Convert(GetDataItem);
selected_items = selected_items.Where(delegate(string x)
{
bool flag = newItems.Contains(x);
if (flag)
{
new_items_copy.Remove(x);
}
return flag;
}).ToList();
newItems.ForEach(delegate(string item, int index)
{
if (selected_items.Contains(item))
{
selected_items.Remove(item);
selected_indicies.Add(index);
}
});
return selected_indicies;
}
protected override void Coloring(ListViewItem component)
{
if (!(component == null))
{
if (base.SelectedIndicies.Contains(component.Index))
{
SelectColoring(component);
}
else
{
DefaultColoring(component);
}
}
}
private void UpdateColors()
{
components.ForEach(Coloring);
}
private ListViewStringComponent GetComponent(int index)
{
return components.Find((ListViewStringComponent x) => x.Index == index);
}
public int Set(string item, bool allowDuplicate = true)
{
int num;
if (!allowDuplicate)
{
num = DataSource.IndexOf(item);
if (num == -1)
{
num = Add(item);
}
}
else
{
num = Add(item);
}
Select(num);
return num;
}
protected override void SelectItem(int index)
{
SelectColoring(GetComponent(index));
}
protected override void DeselectItem(int index)
{
DefaultColoring(GetComponent(index));
}
protected override void HighlightColoring(ListViewItem component)
{
if (!IsSelected(component.Index))
{
HighlightColoring(component as ListViewStringComponent);
}
}
protected virtual void HighlightColoring(ListViewStringComponent component)
{
if (!(component == null))
{
component.Background.color = HighlightedBackgroundColor;
component.Text.color = HighlightedTextColor;
}
}
protected virtual void SelectColoring(ListViewItem component)
{
if (!(component == null))
{
SelectColoring(component as ListViewStringComponent);
}
}
protected virtual void SelectColoring(ListViewStringComponent component)
{
if (!(component == null))
{
component.Background.color = selectedBackgroundColor;
component.Text.color = selectedTextColor;
}
}
protected virtual void DefaultColoring(ListViewItem component)
{
if (!(component == null))
{
DefaultColoring(component as ListViewStringComponent);
}
}
protected virtual void DefaultColoring(ListViewStringComponent component)
{
if (!(component == null))
{
component.Background.color = backgroundColor;
component.Text.color = textColor;
}
}
protected override void OnDestroy()
{
OnSelect.RemoveListener(OnSelectCallback);
OnDeselect.RemoveListener(OnDeselectCallback);
ScrollRect = null;
RemoveCallbacks();
base.OnDestroy();
}
private void Update()
{
if (needResize)
{
Resize();
}
}
private void SetNeedResize()
{
if (CanOptimize())
{
needResize = true;
}
}
}
}