188 lines
4.7 KiB
GDScript
188 lines
4.7 KiB
GDScript
extends ReactiveDictionaryBase
|
|
class_name ReactiveDictionary
|
|
|
|
var _count : int
|
|
var _data : Dictionary
|
|
var _observers : Dictionary
|
|
var _rwlock : ReadWriteLock
|
|
|
|
var is_disposed : bool
|
|
|
|
func _get_subscription(event_class, notify_count = false) -> Callable:
|
|
var wself : WeakRef = weakref(self)
|
|
|
|
return func(observer : ObserverBase, _scheduler : SchedulerBase = null) -> DisposableBase:
|
|
var prop : ReactiveDictionary = wself.get_ref()
|
|
|
|
if not prop or prop.is_disposed:
|
|
observer.on_completed()
|
|
return Disposable.new()
|
|
|
|
if notify_count:
|
|
observer.on_next(prop.Count)
|
|
|
|
if true:
|
|
var __ = ReadWriteLockGuard.new(prop._rwlock, false)
|
|
if not (event_class in prop._observers):
|
|
prop._observers[event_class] = []
|
|
prop._observers[event_class].push_back(observer)
|
|
|
|
var dispose_ = func():
|
|
var _prop = wself.get_ref()
|
|
if not _prop:
|
|
return
|
|
var __ = ReadWriteLockGuard.new(prop._rwlock, false)
|
|
prop._observers[event_class].erase(observer)
|
|
|
|
return Disposable.new(dispose_)
|
|
|
|
func _notify_all(event_class, event):
|
|
var observers_ : Array
|
|
if true:
|
|
var __ = ReadWriteLockGuard.new(self._rwlock, true)
|
|
if event_class in self._observers:
|
|
observers_ = self._observers[event_class].duplicate()
|
|
for observer in observers_:
|
|
observer.on_next(event)
|
|
|
|
func _disconnect_all(event_class):
|
|
var observers_ : Array
|
|
if true:
|
|
var __ = ReadWriteLockGuard.new(this._rwlock, true)
|
|
if event_class in this._observers:
|
|
observers_ = this._observers[event_class].duplicate()
|
|
for observer in observers_:
|
|
observer.on_completed()
|
|
|
|
func _init(dict : Dictionary = {}):
|
|
super._init()
|
|
|
|
self._count = 0
|
|
self._data = dict.duplicate()
|
|
self._observers = {}
|
|
self._rwlock = ReadWriteLock.new()
|
|
self.is_disposed = false
|
|
|
|
self._observe_add_key = Observable.new(self._get_subscription(DictionaryAddKeyEvent))
|
|
self._observe_remove_key = Observable.new(self._get_subscription(DictionaryRemoveKeyEvent))
|
|
self._observer_update_value = Observable.new(self._get_subscription(DictionaryUpdateValueEvent))
|
|
|
|
func ObserveCountChanged(notify_current_count : bool = false) -> Observable:
|
|
return Observable.new(self._get_subscription("CountChanged", notify_current_count))
|
|
|
|
func clear():
|
|
var keys = self.keys()
|
|
for key in keys:
|
|
self.erase(key)
|
|
|
|
func erase(key) -> bool:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return false
|
|
if self._data.has(key):
|
|
var value = self._data[key]
|
|
self._data.erase(key)
|
|
self._count -= 1
|
|
self._notify_all("CountChanged", self._count)
|
|
self._notify_all(DictionaryRemoveKeyEvent, DictionaryRemoveKeyEvent.new(key, value))
|
|
return true
|
|
return false
|
|
|
|
func set_pair(key, value):
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return null
|
|
if not self._data.has(key):
|
|
self._count += 1
|
|
self._data[key] = value
|
|
self._notify_all("CountChanged", self._count)
|
|
self._notify_all(DictionaryAddKeyEvent, DictionaryAddKeyEvent.new(key, value))
|
|
else:
|
|
self._data[key] = value
|
|
self._notify_all(DictionaryUpdateValueEvent, DictionaryUpdateValueEvent.new(key, value))
|
|
|
|
func to_dict() -> Dictionary:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return {}
|
|
return self._data.duplicate()
|
|
|
|
func find_key(value) -> Variant:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return null
|
|
return self._data.find_key(value)
|
|
|
|
func get_value(key, default = null) -> Variant:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return null
|
|
return self._data.get(key, default)
|
|
|
|
func has_key(key) -> bool:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return false
|
|
return self._data.has(key)
|
|
|
|
func has_all(keys : Array) -> bool:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return false
|
|
return self._data.has_all(keys)
|
|
|
|
func hash() -> int:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return 0
|
|
return self._data.hash()
|
|
|
|
func is_empty() -> bool:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return false
|
|
return self._data.is_empty()
|
|
|
|
func keys() -> Array:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return []
|
|
return self._data.keys()
|
|
|
|
func size() -> int:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return -1
|
|
return self._count
|
|
|
|
func values() -> Array:
|
|
if self.is_disposed:
|
|
DisposedError.raise()
|
|
return []
|
|
return self._data.values()
|
|
|
|
func dispose():
|
|
if this.is_disposed:
|
|
return
|
|
this.is_disposed = true
|
|
|
|
this._disconnect_all(DictionaryAddKeyEvent)
|
|
this._disconnect_all(DictionaryRemoveKeyEvent)
|
|
this._disconnect_all(DictionaryUpdateValueEvent)
|
|
this._disconnect_all("CountChanged")
|
|
|
|
this._data = {}
|
|
this._count = -1
|
|
this._observers = {}
|
|
|
|
func to_readonly() -> ReadOnlyReactiveDictionary:
|
|
return ReadOnlyReactiveDictionary.new(self)
|
|
|
|
func _to_string() -> String:
|
|
if self.is_disposed:
|
|
return "<<Disposed ReactiveDictionary>>"
|
|
return str(self._data)
|
|
|
|
func iter() -> Iterator:
|
|
return GDRx.iter(self._data)
|