1+ package com.thewizrd.simplewear.helpers
2+
3+ import android.os.Build
4+ import androidx.annotation.RequiresApi
5+ import java.util.LinkedList
6+ import java.util.function.Predicate
7+
8+ enum class ListChangedAction {
9+ ADD ,
10+ MOVE ,
11+ REMOVE ,
12+ REPLACE ,
13+ RESET
14+ }
15+
16+ class ListChangedArgs <T > {
17+ val action: ListChangedAction
18+ val newStartingIndex: Int
19+ val oldStartingIndex: Int
20+ val oldItems: List <T >?
21+ val newItems: List <T >?
22+
23+ constructor (action: ListChangedAction , newStartingIndex: Int , oldStartingIndex: Int ) {
24+ this .action = action
25+ this .newStartingIndex = newStartingIndex
26+ this .oldStartingIndex = oldStartingIndex
27+ this .oldItems = null
28+ this .newItems = null
29+ }
30+
31+ constructor (
32+ action: ListChangedAction ,
33+ newStartingIndex: Int ,
34+ oldStartingIndex: Int ,
35+ oldItems: List <T >? ,
36+ newItems: List <T >?
37+ ) {
38+ this .action = action
39+ this .newStartingIndex = newStartingIndex
40+ this .oldStartingIndex = oldStartingIndex
41+ this .oldItems = oldItems
42+ this .newItems = newItems
43+ }
44+ }
45+
46+
47+ interface OnListChangedListener <T > {
48+ /* *
49+ * Called whenever a change of unknown type has occurred, such as the entire list being
50+ * set to new values.
51+ *
52+ * @param sender The changing list.
53+ * @param args The data for the onChanged event.
54+ */
55+ fun onChanged (sender : ArrayList <T >, args : ListChangedArgs <T >)
56+ }
57+
58+ class CallbackList <T > {
59+ private val mCallbacks: MutableList <OnListChangedListener <T >> = mutableListOf ()
60+
61+ fun add (callback : OnListChangedListener <T >) {
62+ mCallbacks.add(callback)
63+ }
64+
65+ fun remove (callback : OnListChangedListener <T >) {
66+ mCallbacks.remove(callback)
67+ }
68+
69+ fun notifyChange (sender : ArrayList <T >, args : ListChangedArgs <T >) {
70+ for (i in mCallbacks.indices) {
71+ mCallbacks[i].onChanged(sender, args)
72+ }
73+ }
74+ }
75+
76+ open class ObservableArrayList <T > : ArrayList <T > {
77+ @delegate:Transient
78+ protected val mListeners: CallbackList <T > by lazy { CallbackList () }
79+
80+ constructor () : super ()
81+
82+ constructor (initialCapacity: Int ) : super (initialCapacity)
83+
84+ constructor (c: MutableCollection <out T >) : super (c)
85+
86+ fun addOnListChangedCallback (listChangedListener : OnListChangedListener <T >) {
87+ mListeners.add(listChangedListener)
88+ }
89+
90+ fun removeOnListChangedCallback (listChangedListener : OnListChangedListener <T >) {
91+ mListeners.remove(listChangedListener)
92+ }
93+
94+ fun move (oldIndex : Int , newIndex : Int ) {
95+ super .set(oldIndex, super .set(newIndex, super .get(oldIndex)))
96+
97+ mListeners.notifyChange(
98+ this ,
99+ ListChangedArgs (ListChangedAction .MOVE , newIndex, oldIndex)
100+ )
101+ }
102+
103+ override fun set (index : Int , element : T ): T {
104+ val oldVal = super .set(index, element)
105+ mListeners.notifyChange(
106+ this ,
107+ ListChangedArgs (
108+ ListChangedAction .REPLACE ,
109+ index,
110+ index,
111+ listOf (oldVal),
112+ listOf (element)
113+ )
114+ )
115+ return oldVal
116+ }
117+
118+ override fun add (t : T ): Boolean {
119+ super .add(t)
120+ mListeners.notifyChange(
121+ this ,
122+ ListChangedArgs (ListChangedAction .ADD , size - 1 , - 1 , null , listOf (t))
123+ )
124+ return true
125+ }
126+
127+ override fun add (index : Int , element : T ) {
128+ super .add(index, element)
129+ mListeners.notifyChange(
130+ this ,
131+ ListChangedArgs (ListChangedAction .ADD , index, - 1 , null , listOf (element))
132+ )
133+ }
134+
135+ override fun removeAt (index : Int ): T {
136+ val `val ` = super .removeAt(index)
137+ mListeners.notifyChange(
138+ this ,
139+ ListChangedArgs (ListChangedAction .REMOVE , - 1 , index, listOf (`val `), null )
140+ )
141+ return `val `
142+ }
143+
144+ override fun remove (o : T ): Boolean {
145+ val index = indexOf(o)
146+ if (index >= 0 ) {
147+ removeAt(index)
148+ return true
149+ } else {
150+ return false
151+ }
152+ }
153+
154+ override fun clear () {
155+ val oldSize = size
156+ super .clear()
157+ if (oldSize != 0 ) {
158+ mListeners.notifyChange(
159+ this ,
160+ ListChangedArgs (ListChangedAction .RESET , - 1 , - 1 )
161+ )
162+ }
163+ }
164+
165+ override fun addAll (c : Collection <T >): Boolean {
166+ val oldSize = size
167+ val added = super .addAll(c)
168+ if (added) {
169+ mListeners.notifyChange(
170+ this ,
171+ ListChangedArgs (ListChangedAction .ADD , oldSize - 1 , - 1 , null , LinkedList <T >(c))
172+ )
173+ }
174+ return added
175+ }
176+
177+ override fun addAll (index : Int , c : Collection <T >): Boolean {
178+ val added = super .addAll(index, c)
179+ if (added) {
180+ mListeners.notifyChange(
181+ this ,
182+ ListChangedArgs (ListChangedAction .ADD , index, - 1 , null , LinkedList <T >(c))
183+ )
184+ }
185+ return added
186+ }
187+
188+ override fun removeRange (fromIndex : Int , toIndex : Int ) {
189+ val oldItems = this .subList(fromIndex, toIndex)
190+ super .removeRange(fromIndex, toIndex)
191+ mListeners.notifyChange(
192+ this ,
193+ ListChangedArgs (ListChangedAction .REMOVE , fromIndex, - 1 , oldItems, null )
194+ )
195+ }
196+
197+ override fun removeAll (c : Collection <T >): Boolean {
198+ val value = super .removeAll(c)
199+ mListeners.notifyChange(
200+ this ,
201+ ListChangedArgs (
202+ ListChangedAction .REMOVE ,
203+ - 1 ,
204+ - 1 ,
205+ LinkedList (c),
206+ null
207+ )
208+ )
209+ return value
210+ }
211+
212+ @RequiresApi(api = Build .VERSION_CODES .N )
213+ override fun removeIf (filter : Predicate <in T >): Boolean {
214+ val value = super .removeIf(filter)
215+ mListeners.notifyChange(
216+ this ,
217+ ListChangedArgs (ListChangedAction .REMOVE , - 1 , - 1 )
218+ )
219+ return value
220+ }
221+ }
0 commit comments