-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathListView.cs
151 lines (125 loc) · 3.3 KB
/
ListView.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityListView
{
public class ListView : MonoBehaviour
{
private readonly Dictionary<object, GameObject> items = new Dictionary<object, GameObject>();
public Dictionary<object, GameObject> Items
{
get { return items; }
}
[SerializeField]
private GameObject itemTemplate;
private void Start()
{
itemTemplate.SetActive(false);
}
public List<GameObject> Init<TAny>(IEnumerable<TAny> source)
{
return Init<TAny, IListViewItem<TAny>>(source,
(item, component) => component.Init(item));
}
public List<GameObject> Init<TAny, TInitArgs>(IEnumerable<TAny> source, TInitArgs args)
{
return Init<TAny, IListViewItem<TAny, TInitArgs>>(source,
(item, component) => component.Init(item, args));
}
public List<GameObject> Init<TAny, TComponent>(IEnumerable<TAny> source, Action<TAny, TComponent> initFunction)
{
Clear();
var result = new List<GameObject>();
foreach (var item in source)
{
var itemObject = AddItem(item, initFunction);
result.Add(itemObject);
}
return result;
}
public GameObject AddItem<TAny>(TAny item)
{
return AddItem<TAny, IListViewItem<TAny>>(item, (i, component) => component.Init(i));
}
public GameObject AddItem<TAny, TInitArgs>(TAny item, TInitArgs args)
{
return AddItem<TAny, IListViewItem<TAny, TInitArgs>>(item,
(i, component) => component.Init(i, args));
}
public GameObject AddItem<TAny, TComponent>(TAny item, Action<TAny, TComponent> initFunction)
{
var itemObject = Instantiate(itemTemplate);
itemObject.transform.SetParent(transform, false);
itemObject.SetActive(true);
var component = itemObject.GetComponent<TComponent>();
if (component != null)
{
initFunction(item, component);
}
itemObject.AddComponent<ListViewElement>().OnDestroyed += () => items.Remove(item);
items.Add(item, itemObject);
return itemObject;
}
public void RemoveItem<TAny>(TAny item)
{
if (items.ContainsKey(item))
{
var itemObj = items[item];
Destroy(itemObj.gameObject);
}
else
{
throw new Exception("No list item found for the given list element");
}
}
public void Clear()
{
foreach (Transform child in transform)
{
if (child.gameObject != itemTemplate)
{
Destroy(child.gameObject);
}
}
Items.Clear();
}
public T GetModelForChild<T>(GameObject child)
{
if (child.transform.parent != transform)
{
throw new Exception("The specified game object is not a child of the list view");
}
if (items.All(kvp => kvp.Value != child))
{
throw new Exception("The specified game object is a child but doesn't represent a list view item");
}
var key = items.First(kvp => kvp.Value == child).Key;
if (!(key is T))
{
throw new Exception("The model for the given game object doesn't match the specified type");
}
return (T) key;
}
public interface IListViewItem<T>
{
void Init(T model);
}
public interface IListViewItem<T, TInitArgs>
{
void Init(T model, TInitArgs args);
}
private class ListViewElement : MonoBehaviour
{
public event Action OnDestroyed;
private void OnDestroy()
{
if (OnDestroyed != null)
{
OnDestroyed();
OnDestroyed = null;
}
}
}
}
}