more layer replacement
This commit is contained in:
		| @@ -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: | ||||||
|   | |||||||
| @@ -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() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jakob Ketterl
					Jakob Ketterl