Undo manager records ids for attribute undo commands

This commit is contained in:
Arjan Molenaar 2021-01-02 15:51:41 +01:00
parent d1b1a6d845
commit 9174682e5a
No known key found for this signature in database
GPG Key ID: BF977B918996CB13
4 changed files with 25 additions and 7 deletions

View File

@ -196,6 +196,9 @@ class RepositoryProtocol(Protocol):
def select(self, expression: None) -> Iterator[Element]:
...
def lookup(self, id: str) -> Optional[Element]:
...
def watcher(
self, element: Element, default_handler: Optional[Handler] = None
) -> EventWatcherProtocol:

View File

@ -5,7 +5,7 @@ from gaphor.services.undomanager import UndoManager
@pytest.fixture
def undo_manager(event_manager):
undo_manager = UndoManager(event_manager)
def undo_manager(event_manager, element_factory):
undo_manager = UndoManager(event_manager, element_factory)
yield undo_manager
undo_manager.shutdown()

View File

@ -11,13 +11,15 @@ NOTE: it would be nice to use actions in conjunction with functools.partial.
"""
import logging
from typing import Callable, List
from typing import Callable, List, Optional
from gaphas import state
from gaphor.abc import ActionProvider, Service
from gaphor.action import action
from gaphor.core import event_handler
from gaphor.core.modeling.diagram import Diagram
from gaphor.core.modeling.element import Element, RepositoryProtocol
from gaphor.core.modeling.event import (
AssociationAdded,
AssociationDeleted,
@ -89,8 +91,9 @@ class UndoManager(Service, ActionProvider):
performed action.
"""
def __init__(self, event_manager):
def __init__(self, event_manager, element_factory):
self.event_manager = event_manager
self.element_factory: RepositoryProtocol = element_factory
self._undo_stack: List[ActionStack] = []
self._redo_stack: List[ActionStack] = []
self._stack_depth = 20
@ -253,6 +256,16 @@ class UndoManager(Service, ActionProvider):
self.event_manager.handle(ActionEnabled("win.edit-redo", self.can_redo()))
self.event_manager.handle(UndoManagerStateChanged(self))
def deep_lookup(self, id: str) -> Optional[Element]:
element: Optional[Element] = self.element_factory.lookup(id)
if not element:
for diagram in self.element_factory.select(Diagram):
presentation: Element
for presentation in diagram.ownedPresentation:
if presentation.id == id:
return presentation
return element
#
# Undo Handlers
#
@ -322,10 +335,12 @@ class UndoManager(Service, ActionProvider):
@event_handler(AttributeUpdated)
def undo_attribute_change_event(self, event):
attribute = event.property
element = event.element
element_id = event.element.id
value = event.old_value
del event
def _undo_attribute_change_event():
element = self.deep_lookup(element_id)
attribute._set(element, value)
self.add_undo_action(_undo_attribute_change_event)

View File

@ -22,8 +22,8 @@ def sanitizer_service(event_manager):
@pytest.fixture(autouse=True)
def undo_manager(event_manager):
return UndoManager(event_manager)
def undo_manager(event_manager, element_factory):
return UndoManager(event_manager, element_factory)
def test_remove_class_with_association(create, diagram, element_factory, event_manager):