Order undo events

So create happens before properties, before unlink events.
This commit is contained in:
Arjan Molenaar 2021-02-05 19:58:56 +01:00
parent 62d3da1550
commit e49cae8649
No known key found for this signature in database
GPG Key ID: BF977B918996CB13
2 changed files with 73 additions and 29 deletions

View File

@ -65,10 +65,10 @@ class ActionStack:
@transactional
def execute(self):
self._actions.reverse()
self._actions.sort(key=lambda fn: fn.__name__)
for act in self._actions:
logger.debug("%s", act.__doc__)
logger.debug(act.__doc__)
try:
act()
except Exception:
@ -318,57 +318,57 @@ class UndoManager(Service, ActionProvider):
def undo_reversible_event(self, event: RevertibeEvent):
element_id = event.element.id
def _undo_reversible_event():
def b_undo_reversible_event():
element = self.deep_lookup(element_id)
event.revert(element)
_undo_reversible_event.__doc__ = (
b_undo_reversible_event.__doc__ = (
f"Reverse event {event.__class__.__name__} for element {event.element}."
)
self.add_undo_action(
_undo_reversible_event, requires_transaction=event.requires_transaction
b_undo_reversible_event, requires_transaction=event.requires_transaction
)
@event_handler(ElementCreated)
def undo_create_element_event(self, event: ElementCreated):
element_id = event.element.id
def _undo_create_event():
def c_undo_create_event():
element = self.deep_lookup(element_id)
element.unlink()
_undo_create_event.__doc__ = f"Undo create element {event.element}."
c_undo_create_event.__doc__ = f"Undo create element {event.element}."
del event
self.add_undo_action(_undo_create_event)
self.add_undo_action(c_undo_create_event)
@event_handler(ElementDeleted)
def undo_delete_element_event(self, event: ElementDeleted):
element_type = type(event.element)
element_id = event.element.id
def _undo_delete_event():
def a_undo_delete_event():
element = self.element_factory.create_as(element_type, element_id)
self.event_manager.handle(ElementCreated(self.element_factory, element))
_undo_delete_event.__doc__ = f"Recreate element {element_type} ({element_id})."
a_undo_delete_event.__doc__ = f"Recreate element {element_type} ({element_id})."
del event
self.add_undo_action(_undo_delete_event)
self.add_undo_action(a_undo_delete_event)
@event_handler(DiagramItemCreated)
def undo_create_diagram_item_event(self, event: DiagramItemCreated):
element_id = event.element.id
def _undo_create_event():
def c_undo_create_event():
element = self.deep_lookup(element_id)
element.unlink()
_undo_create_event.__doc__ = f"Undo create diagram item {event.element}."
c_undo_create_event.__doc__ = f"Undo create diagram item {event.element}."
del event
self.add_undo_action(_undo_create_event)
self.add_undo_action(c_undo_create_event)
@event_handler(DiagramItemDeleted)
def undo_delete_diagram_item_event(self, event: DiagramItemDeleted):
@ -382,17 +382,17 @@ class UndoManager(Service, ActionProvider):
event.element.save(save_func)
def _undo_delete_event():
def a_undo_delete_event():
diagram: Diagram = self.deep_lookup(diagram_id) # type: ignore[assignment]
element = diagram.create_as(element_type, element_id)
for name, ser in data.items():
for value in deserialize(ser, lambda ref: None):
element.load(name, value)
_undo_delete_event.__doc__ = f"Undo delete diagram item {event.element}."
a_undo_delete_event.__doc__ = f"Undo delete diagram item {event.element}."
del event
self.add_undo_action(_undo_delete_event)
self.add_undo_action(a_undo_delete_event)
@event_handler(AttributeUpdated)
def undo_attribute_change_event(self, event: AttributeUpdated):
@ -400,16 +400,16 @@ class UndoManager(Service, ActionProvider):
element_id = event.element.id
value = event.old_value
def _undo_attribute_change_event():
def b_undo_attribute_change_event():
element = self.deep_lookup(element_id)
attribute._set(element, value)
_undo_attribute_change_event.__doc__ = (
b_undo_attribute_change_event.__doc__ = (
f"Revert {event.element}.{attribute.name} to {value}."
)
del event
self.add_undo_action(_undo_attribute_change_event)
self.add_undo_action(b_undo_attribute_change_event)
@event_handler(AssociationSet)
def undo_association_set_event(self, event: AssociationSet):
@ -419,17 +419,17 @@ class UndoManager(Service, ActionProvider):
element_id = event.element.id
value_id = event.old_value and event.old_value.id
def _undo_association_set_event():
def b_undo_association_set_event():
element = self.deep_lookup(element_id)
value = value_id and self.deep_lookup(value_id)
association._set(element, value, from_opposite=True)
_undo_association_set_event.__doc__ = (
b_undo_association_set_event.__doc__ = (
f"Revert {event.element}.{association.name} to {event.old_value}."
)
del event
self.add_undo_action(_undo_association_set_event)
self.add_undo_action(b_undo_association_set_event)
@event_handler(AssociationAdded)
def undo_association_add_event(self, event: AssociationAdded):
@ -439,17 +439,17 @@ class UndoManager(Service, ActionProvider):
element_id = event.element.id
value_id = event.new_value.id
def _undo_association_add_event():
def b_undo_association_add_event():
element = self.deep_lookup(element_id)
value = self.deep_lookup(value_id)
association._del(element, value, from_opposite=True)
_undo_association_add_event.__doc__ = (
b_undo_association_add_event.__doc__ = (
f"{event.element}.{association.name} delete {event.new_value}."
)
del event
self.add_undo_action(_undo_association_add_event)
self.add_undo_action(b_undo_association_add_event)
@event_handler(AssociationDeleted)
def undo_association_delete_event(self, event: AssociationDeleted):
@ -459,14 +459,14 @@ class UndoManager(Service, ActionProvider):
element_id = event.element.id
value_id = event.old_value.id
def _undo_association_delete_event():
def b_undo_association_delete_event():
element = self.deep_lookup(element_id)
value = self.deep_lookup(value_id)
association._set(element, value, from_opposite=True)
_undo_association_delete_event.__doc__ = (
b_undo_association_delete_event.__doc__ = (
f"{event.element}.{association.name} add {event.old_value}."
)
del event
self.add_undo_action(_undo_association_delete_event)
self.add_undo_action(b_undo_association_delete_event)

View File

@ -123,6 +123,50 @@ def test_diagram_item_should_not_end_up_in_element_factory(
assert cls not in element_factory.lselect(), element_factory.lselect()
def test_delete_and_undo_diagram_item(event_manager, element_factory, undo_manager):
with Transaction(event_manager):
diagram = element_factory.create(Diagram)
with Transaction(event_manager):
subject = element_factory.create(UML.Class)
subject.name = "Name"
cls = diagram.create(ClassItem, subject=subject)
with Transaction(event_manager):
cls.unlink()
undo_manager.undo_transaction()
new_cls = diagram.ownedPresentation[0]
new_elem = element_factory.lookup(subject.id)
assert new_cls in new_elem.presentation
assert new_cls.subject
assert new_elem.name == "Name"
def test_delete_and_undo_model_element(event_manager, element_factory, undo_manager):
with Transaction(event_manager):
diagram = element_factory.create(Diagram)
with Transaction(event_manager):
subject = element_factory.create(UML.Class)
subject.name = "Name"
diagram.create(ClassItem, subject=subject)
with Transaction(event_manager):
subject.unlink()
undo_manager.undo_transaction()
new_cls = diagram.ownedPresentation[0]
new_elem = element_factory.lookup(subject.id)
assert new_cls in new_elem.presentation
assert new_cls.subject
assert new_elem.name == "Name"
def test_deleted_diagram_item_should_not_end_up_in_element_factory(
event_manager, element_factory, undo_manager
):