Merge pull request #360 from gaphor/css-attributes
Support CSS attributes
This commit is contained in:
commit
e834f05448
@ -12,7 +12,7 @@ from typing import TYPE_CHECKING, Iterator, Optional, Sequence, Union
|
||||
|
||||
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.event import DiagramItemCreated
|
||||
from gaphor.core.modeling.presentation import Presentation
|
||||
@ -79,6 +79,37 @@ def removesuffix(self: str, suffix: str, /) -> str:
|
||||
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:
|
||||
def __init__(self, diagram: Diagram, view: Optional[gaphas.View] = None):
|
||||
self.diagram = diagram
|
||||
@ -95,7 +126,8 @@ class StyledDiagram:
|
||||
return (StyledItem(item, view) for item in self.diagram.canvas.get_root_items())
|
||||
|
||||
def attribute(self, name: str) -> str:
|
||||
return ""
|
||||
fields = name.split(".")
|
||||
return " ".join(map(attrstr, rgetattr(self.diagram, fields))).strip()
|
||||
|
||||
def state(self):
|
||||
return ()
|
||||
@ -132,7 +164,11 @@ class StyledItem:
|
||||
return (StyledItem(child, view) for child in children)
|
||||
|
||||
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]:
|
||||
view = self.view
|
||||
|
1
gaphor/core/modeling/tests/conftest.py
Normal file
1
gaphor/core/modeling/tests/conftest.py
Normal file
@ -0,0 +1 @@
|
||||
from gaphor.diagram.tests.fixtures import diagram, element_factory, event_manager
|
73
gaphor/core/modeling/tests/test_style_attributes.py
Normal file
73
gaphor/core/modeling/tests/test_style_attributes.py
Normal 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") == ""
|
Loading…
x
Reference in New Issue
Block a user