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
|
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
|
||||||
|
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