more layer replacement

This commit is contained in:
Jakob Ketterl 2020-03-24 22:11:54 +01:00
parent 14634af83c
commit 236f3d2058
2 changed files with 74 additions and 16 deletions

View File

@ -92,7 +92,6 @@ class PropertyLayer(PropertyManager):
def __setitem__(self, name, value): def __setitem__(self, name, value):
if name in self.properties and self.properties[name] == value: if name in self.properties and self.properties[name] == value:
return return
logger.debug("property change: %s => %s", name, value)
self.properties[name] = value self.properties[name] = value
self._fireCallbacks(name, value) self._fireCallbacks(name, value)
@ -146,33 +145,61 @@ class PropertyStack(PropertyManager):
""" """
highest priority = 0 highest priority = 0
""" """
self._fireChanges(self._addLayer(priority, pm))
def _addLayer(self, priority: int, pm: PropertyManager):
changes = {}
for key in pm.keys(): for key in pm.keys():
if key not in self or self[key] != pm[key]: if key not in self or self[key] != pm[key]:
self._fireCallbacks(key, pm[key]) changes[key] = pm[key]
self.layers.append({"priority": priority, "props": pm})
def eventClosure(name, value): def eventClosure(name, value):
self.receiveEvent(pm, name, value) self.receiveEvent(pm, name, value)
pm.wire(eventClosure) sub = pm.wire(eventClosure)
self.layers.append({"priority": priority, "props": pm, "sub": sub})
return changes
def removeLayer(self, pm: PropertyManager):
for layer in self.layers:
if layer["props"] == pm:
self._fireChanges(self._removeLayer(layer))
def _removeLayer(self, layer):
layer["sub"].cancel()
self.layers.remove(layer)
changes = {}
pm = layer["props"]
for key in pm.keys():
if key in self:
if self[key] != pm[key]:
changes[key] = self[key]
else:
changes[key] = None
return changes
def replaceLayer(self, priority: int, pm: PropertyManager):
layers = [x for x in self.layers if x["priority"] == priority]
changes = {}
if layers:
changes = self._removeLayer(layers[0])
for k, v in self._addLayer(priority, pm).items():
changes[k] = v
self._fireChanges(changes)
def _fireChanges(self, changes):
for k, v in changes.items():
self._fireCallbacks(k, v)
def receiveEvent(self, layer, name, value): def receiveEvent(self, layer, name, value):
if layer != self._getTopLayer(name): if layer != self._getTopLayer(name):
return return
self._fireCallbacks(name, value) self._fireCallbacks(name, value)
def removeLayer(self, pm: PropertyManager):
for layer in self.layers:
if layer["props"] == pm:
self.layers.remove(layer)
for key in pm.keys():
if key in self:
if self[key] != pm[key]:
self._fireCallbacks(key, self[key])
else:
self._fireCallbacks(key, None)
def _getTopLayer(self, item): def _getTopLayer(self, item):
layers = [la["props"] for la in sorted(self.layers, key=lambda l: l["priority"])] layers = [la["props"] for la in sorted(self.layers, key=lambda l: l["priority"])]
for m in layers: for m in layers:

View File

@ -136,3 +136,34 @@ class PropertyStackTest(TestCase):
mock.reset_mock() mock.reset_mock()
stack.removeLayer(high_layer) stack.removeLayer(high_layer)
mock.method.assert_called_once_with(None) mock.method.assert_called_once_with(None)
def testReplaceLayer(self):
first_layer = PropertyLayer()
first_layer["testkey"] = "old value"
second_layer = PropertyLayer()
second_layer["testkey"] = "new value"
stack = PropertyStack()
stack.addLayer(0, first_layer)
mock = Mock()
stack.wireProperty("testkey", mock.method)
mock.method.assert_called_once_with("old value")
mock.reset_mock()
stack.replaceLayer(0, second_layer)
mock.method.assert_called_once_with("new value")
def testUnwiresEventsOnRemoval(self):
layer = PropertyLayer()
layer["testkey"] = "before"
stack = PropertyStack()
stack.addLayer(0, layer)
mock = Mock()
stack.wire(mock.method)
stack.removeLayer(layer)
mock.method.assert_called_once_with("testkey", None)
mock.reset_mock()
layer["testkey"] = "after"
mock.method.assert_not_called()