Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show relationships on top of other elements #1084

Merged
merged 4 commits into from Oct 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 9 additions & 4 deletions gaphor/core/modeling/diagram.py
Expand Up @@ -323,10 +323,15 @@ def iter_children(item):
yield child
yield from iter_children(child)

for root in self.ownedPresentation:
if not root.parent:
yield root
yield from iter_children(root)
def traverse_items() -> Iterable[Presentation]:
for root in self.ownedPresentation:
if not root.parent:
yield root
yield from iter_children(root)

yield from sorted(
traverse_items(), key=lambda e: int(isinstance(e, gaphas.Line))
)

def get_parent(self, item: Presentation) -> Presentation | None:
return item.parent
Expand Down
5 changes: 0 additions & 5 deletions gaphor/core/modeling/element.py
Expand Up @@ -5,7 +5,6 @@

import logging
import uuid
from contextlib import contextmanager
from typing import TYPE_CHECKING, Callable, Iterator, Protocol, TypeVar, overload

from gaphor.core.modeling.event import ElementUpdated
Expand Down Expand Up @@ -200,10 +199,6 @@ def watcher(
def handle(self, event: object) -> None:
...

@contextmanager
def block_events(self) -> Iterator[RepositoryProtocol]:
...


class EventWatcherProtocol(Protocol):
def watch(self, path: str, handler: Handler | None = None) -> EventWatcherProtocol:
Expand Down
9 changes: 1 addition & 8 deletions gaphor/core/modeling/presentation.py
Expand Up @@ -23,14 +23,7 @@

class Presentation(Matrices, Element, Generic[S]):
"""This presentation is used to link the behaviors of
`gaphor.core.modeling` and `gaphas.Item`.

Note that Presentations are not managed by the Element Factory.
Instead, Presentation objects are owned by Diagram. As a result they
do not emit ElementCreated and ElementDeleted events. Presentations
have their own create and delete events: ElementCreated and
ElementDeleted.
"""
`gaphor.core.modeling` and `gaphas.Item`."""

def __init__(self, diagram: Diagram, id: Id | None = None) -> None:
super().__init__(id=id, model=diagram.model)
Expand Down
51 changes: 38 additions & 13 deletions gaphor/core/modeling/tests/test_diagram.py
@@ -1,10 +1,7 @@
import gaphas
import pytest

from gaphor.core.eventmanager import EventManager
from gaphor.core.modeling import Diagram, ElementFactory, Presentation, StyleSheet
from gaphor.core.modeling.elementdispatcher import ElementDispatcher
from gaphor.UML.modelinglanguage import UMLModelingLanguage
from gaphor.core.modeling import Diagram, Presentation, StyleSheet


class Example(gaphas.Element, Presentation):
Expand All @@ -16,15 +13,18 @@ def unlink(self):
super().unlink()


class ExampleLine(gaphas.Line, Presentation):
def __init__(self, diagram, id):
super().__init__(connections=diagram.connections, diagram=diagram, id=id)

def unlink(self):
self.test_unlinked = True
super().unlink()


@pytest.fixture
def element_factory():
event_manager = EventManager()
element_dispatcher = ElementDispatcher(event_manager, UMLModelingLanguage())
element_factory = ElementFactory(event_manager, element_dispatcher)
yield element_factory
element_factory.shutdown()
element_dispatcher.shutdown()
event_manager.shutdown()
def diagram(element_factory):
return element_factory.create(Diagram)


def test_diagram_can_be_used_as_gtkview_model():
Expand Down Expand Up @@ -82,7 +82,6 @@ def request_update(self, items, removed_items) -> None:

def test_remove_presentation_triggers_view(element_factory):
diagram = element_factory.create(Diagram)
print(diagram.watcher())
view = ViewMock()
diagram.register_view(view)

Expand All @@ -93,3 +92,29 @@ def test_remove_presentation_triggers_view(element_factory):
assert example.diagram is None
assert example not in diagram.ownedPresentation
assert example in view.removed_items


def test_order_presentations_lines_are_last(diagram):
example_line = diagram.create(ExampleLine)
example = diagram.create(Example)

assert list(diagram.get_all_items()) == [example, example_line]


def test_order_presentations_line_is_grouped(diagram):
example_line = diagram.create(ExampleLine)
example_1 = diagram.create(Example)
example_2 = diagram.create(Example)

example_line.parent = example_1

assert list(diagram.get_all_items()) == [example_1, example_2, example_line]


def test_order_grouped_presentations(diagram):
example_1 = diagram.create(Example)
example_2 = diagram.create(Example)

example_1.parent = example_2

assert list(diagram.get_all_items()) == [example_2, example_1]
6 changes: 3 additions & 3 deletions gaphor/services/tests/test_undo_presentation.py
Expand Up @@ -51,7 +51,7 @@ def test_line_delete(diagram, undo_manager, event_manager):

def test_line_orthogonal_property(diagram, undo_manager, event_manager):
with Transaction(event_manager):
line = LinePresentation(diagram)
line = diagram.create(LinePresentation)
line.insert_handle(0, Handle())

with Transaction(event_manager):
Expand All @@ -70,7 +70,7 @@ def test_line_orthogonal_property(diagram, undo_manager, event_manager):

def test_line_horizontal_property(diagram, undo_manager, event_manager):
with Transaction(event_manager):
line = LinePresentation(diagram)
line = diagram.create(LinePresentation)
line.insert_handle(0, Handle())

with Transaction(event_manager):
Expand Down Expand Up @@ -99,7 +99,7 @@ def test_line_horizontal_property(diagram, undo_manager, event_manager):
def test_matrix_operation(action, diagram, undo_manager, event_manager):

with Transaction(event_manager):
line = LinePresentation(diagram)
line = diagram.create(LinePresentation)
line.matrix.translate(10, 0)

original = tuple(line.matrix)
Expand Down
27 changes: 11 additions & 16 deletions gaphor/services/undomanager.py
Expand Up @@ -265,14 +265,9 @@ def _action_executed(self, event=None):
self.event_manager.handle(ActionEnabled("win.edit-redo", self.can_redo()))
self.event_manager.handle(UndoManagerStateChanged(self))

def deep_lookup(self, id: str) -> Element:
def lookup(self, id: str) -> 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
raise ValueError(f"Element with id {id} not found in model")
return element

Expand Down Expand Up @@ -309,7 +304,7 @@ def undo_reversible_event(self, event: RevertibeEvent):
element_id = event.element.id

def b_undo_reversible_event():
element = self.deep_lookup(element_id)
element = self.lookup(element_id)
event.revert(element)

b_undo_reversible_event.__doc__ = (
Expand All @@ -325,7 +320,7 @@ def undo_create_element_event(self, event: ElementCreated):
element_id = event.element.id

def d_undo_create_event():
element = self.deep_lookup(element_id)
element = self.lookup(element_id)
element.unlink()

d_undo_create_event.__doc__ = f"Undo create element {event.element}."
Expand All @@ -348,7 +343,7 @@ def save_func(name, value):
event.element.save(save_func)

def b_undo_delete_event():
diagram: Diagram = self.deep_lookup(diagram_id) # type: ignore[assignment]
diagram: Diagram = self.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):
Expand All @@ -374,7 +369,7 @@ def undo_attribute_change_event(self, event: AttributeUpdated):
value = event.old_value

def c_undo_attribute_change_event():
element = self.deep_lookup(element_id)
element = self.lookup(element_id)
attribute._set(element, value)

c_undo_attribute_change_event.__doc__ = (
Expand All @@ -393,8 +388,8 @@ def undo_association_set_event(self, event: AssociationSet):
value_id = event.old_value and event.old_value.id

def c_undo_association_set_event():
element = self.deep_lookup(element_id)
value = value_id and self.deep_lookup(value_id)
element = self.lookup(element_id)
value = value_id and self.lookup(value_id)
association._set(element, value, from_opposite=True)

c_undo_association_set_event.__doc__ = (
Expand All @@ -413,8 +408,8 @@ def undo_association_add_event(self, event: AssociationAdded):
value_id = event.new_value.id

def c_undo_association_add_event():
element = self.deep_lookup(element_id)
value = self.deep_lookup(value_id)
element = self.lookup(element_id)
value = self.lookup(value_id)
association._del(element, value, from_opposite=True)

c_undo_association_add_event.__doc__ = (
Expand All @@ -433,8 +428,8 @@ def undo_association_delete_event(self, event: AssociationDeleted):
value_id = event.old_value.id

def c_undo_association_delete_event():
element = self.deep_lookup(element_id)
value = self.deep_lookup(value_id)
element = self.lookup(element_id)
value = self.lookup(value_id)
association._set(element, value, from_opposite=True)

c_undo_association_delete_event.__doc__ = (
Expand Down