Merge pull request #360 from gaphor/css-attributes

Support CSS attributes
This commit is contained in:
Arjan Molenaar 2020-07-14 10:43:45 +02:00 committed by GitHub
commit e834f05448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 113 additions and 3 deletions

View File

@ -12,7 +12,7 @@ from typing import TYPE_CHECKING, Iterator, Optional, Sequence, Union
import gaphas import gaphas
from gaphor.core.modeling.coremodel import PackageableElement from gaphor.core.modeling.coremodel import Element, PackageableElement
from gaphor.core.modeling.element import Id, RepositoryProtocol from gaphor.core.modeling.element import Id, RepositoryProtocol
from gaphor.core.modeling.event import DiagramItemCreated from gaphor.core.modeling.event import DiagramItemCreated
from gaphor.core.modeling.presentation import Presentation from gaphor.core.modeling.presentation import Presentation
@ -79,6 +79,37 @@ def removesuffix(self: str, suffix: str, /) -> str:
return self[:] return self[:]
def rgetattr(obj, attrs, default=None):
a, *tail = attrs
v = getattr(obj, a, None)
print("")
if isinstance(v, (list, tuple)):
if tail:
for m in v:
yield from rgetattr(m, tail)
else:
yield from v
else:
if tail:
yield from rgetattr(v, tail)
elif v is not None:
yield v
def attrstr(obj):
"""Returns lower-case string representation of an attribute."""
if isinstance(obj, str):
return obj.lower()
elif isinstance(obj, (bool, int)):
return "true" if obj else ""
elif isinstance(obj, Element):
return obj.__class__.__name__.lower()
log.warn(
f'Can not make a string out of {obj}, returning "". Please raise an issue.'
)
return ""
class StyledDiagram: class StyledDiagram:
def __init__(self, diagram: Diagram, view: Optional[gaphas.View] = None): def __init__(self, diagram: Diagram, view: Optional[gaphas.View] = None):
self.diagram = diagram self.diagram = diagram
@ -95,7 +126,8 @@ class StyledDiagram:
return (StyledItem(item, view) for item in self.diagram.canvas.get_root_items()) return (StyledItem(item, view) for item in self.diagram.canvas.get_root_items())
def attribute(self, name: str) -> str: def attribute(self, name: str) -> str:
return "" fields = name.split(".")
return " ".join(map(attrstr, rgetattr(self.diagram, fields))).strip()
def state(self): def state(self):
return () return ()
@ -132,7 +164,11 @@ class StyledItem:
return (StyledItem(child, view) for child in children) return (StyledItem(child, view) for child in children)
def attribute(self, name: str) -> str: def attribute(self, name: str) -> str:
return "" fields = name.split(".")
a = " ".join(map(attrstr, rgetattr(self.item, fields))).strip()
if (not a) and self.item.subject:
a = " ".join(map(attrstr, rgetattr(self.item.subject, fields))).strip()
return a
def state(self) -> Sequence[str]: def state(self) -> Sequence[str]:
view = self.view view = self.view

View File

@ -0,0 +1 @@
from gaphor.diagram.tests.fixtures import diagram, element_factory, event_manager

View File

@ -0,0 +1,73 @@
from gaphor import UML
from gaphor.core.modeling.diagram import StyledItem
from gaphor.UML.classes import ClassItem
def test_attribute_of_item(diagram):
classitem = diagram.create(ClassItem)
node = StyledItem(classitem)
assert node.attribute("show_attributes") == "true"
def test_nonexistant_attribute_of_item(diagram):
classitem = diagram.create(ClassItem)
node = StyledItem(classitem)
assert node.attribute("foobar") == ""
def test_should_get_type_of_element_attribute(diagram, element_factory):
class_ = element_factory.create(UML.Class)
classitem = diagram.create(ClassItem, subject=class_)
node = StyledItem(classitem)
assert node.attribute("subject") == "class"
def test_should_read_attribute_of_subject(diagram, element_factory):
class_ = element_factory.create(UML.Class)
classitem = diagram.create(ClassItem, subject=class_)
class_.name = "myname"
node = StyledItem(classitem)
assert node.attribute("name") == "myname"
# test attributes that can be any of a list
def test_nested_attribute_of_subject(diagram, element_factory):
class_ = element_factory.create(UML.Class)
attr = element_factory.create(UML.Property)
class_.ownedAttribute = attr
classitem = diagram.create(ClassItem, subject=class_)
attr.name = "myname"
attr.isService = 1
node = StyledItem(classitem)
assert node.attribute("attribute") == "property"
assert node.attribute("attribute.name") == "myname"
assert node.attribute("attribute.isBehavior") == ""
assert node.attribute("attribute.isService") == "true"
assert node.attribute("attribute.notAnAttribute") == ""
def test_multiple_nested_attribute_of_subject(diagram, element_factory):
class_ = element_factory.create(UML.Class)
attr1 = element_factory.create(UML.Property)
attr2 = element_factory.create(UML.Property)
class_.ownedAttribute = attr1
class_.ownedAttribute = attr2
classitem = diagram.create(ClassItem, subject=class_)
attr1.name = "first"
attr2.name = "second"
node = StyledItem(classitem)
assert node.attribute("attribute") == "property property"
assert node.attribute("attribute.name") in ("first second", "second first")
assert node.attribute("attribute.notAnAttribute") == ""