Skip to content

Commit

Permalink
Merge pull request #59 from DSD-DBS/generalize-layers
Browse files Browse the repository at this point in the history
Generalize layers
  • Loading branch information
Wuestengecko committed Feb 7, 2022
2 parents 353dba4 + eb2ad27 commit 836a19e
Show file tree
Hide file tree
Showing 17 changed files with 1,964 additions and 166 deletions.
82 changes: 82 additions & 0 deletions capellambse/aird/capstyle.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,24 @@ class in the form::
"stroke-dasharray": "5",
},
},
"Operational Activity Interaction Blank": {
"Box.OperationalActivity": {
"fill": COLORS["_CAP_Activity_Orange"],
"rx": "10px",
"ry": "10px",
"stroke": COLORS["_CAP_Activity_Border_Orange"],
"text_fill": COLORS["_CAP_xAB_Activity_Label_Orange"],
},
"Box.OperationalProcess": {
"stroke": COLORS["black"],
"text_fill": COLORS["black"],
},
"Edge.FunctionalExchange": {
"marker-end": "ArrowMark",
"stroke-width": 2,
"stroke": COLORS["_CAP_Activity_Border_Orange"],
},
},
"Physical Architecture Blank": {
**dict.fromkeys(
["Box.CP_IN", "Box.CP_OUT", "Box.CP_INOUT"],
Expand All @@ -658,6 +676,14 @@ class in the form::
"stroke": COLORS["black"],
},
),
"Box.FIP": {
"fill": COLORS["dark_orange"],
"stroke-width": 0,
},
"Box.FOP": {
"fill": COLORS["_CAP_xAB_Function_Border_Green"],
"stroke-width": 0,
},
"Box.PP": {
"fill": COLORS["_CAP_PhysicalPort_Yellow"],
"stroke": COLORS["_CAP_Class_Border_Brown"],
Expand All @@ -670,12 +696,68 @@ class in the form::
"stroke": COLORS["_CAP_Node_Yellow_Border"],
"text_fill": COLORS["_CAP_Node_Yellow_Label"],
},
"Box.PhysicalFunction": {
"fill": COLORS["_CAP_xAB_Function_Green"],
"stroke": COLORS["_CAP_xAB_Function_Border_Green"],
},
"Edge.ComponentExchange": {
"stroke": COLORS["_CAP_Component_Border_Blue"],
"stroke-width": 2,
"text_fill": COLORS["_CAP_Component_Border_Blue"],
},
"Edge.FunctionalExchange": {
"stroke": COLORS["_CAP_xAB_Function_Border_Green"],
"stroke-width": 2,
"text_fill": COLORS["_CAP_xAB_Function_Border_Green"],
},
"Edge.PhysicalLink": {
"stroke": COLORS["red"],
"stroke-width": 2,
"text_fill": COLORS["red"],
},
},
"Physical Data Flow Blank": {
"Box.FIP": {
"fill": COLORS["dark_orange"],
"stroke-width": 0,
},
"Box.FOP": {
"fill": COLORS["_CAP_xAB_Function_Border_Green"],
"stroke-width": 0,
},
"Box.PhysicalFunction": {
"fill": COLORS["_CAP_xAB_Function_Green"],
"stroke": COLORS["_CAP_xAB_Function_Border_Green"],
},
"Edge.FunctionalExchange": {
"stroke": COLORS["_CAP_xAB_Function_Border_Green"],
"stroke-width": 2,
"text_fill": COLORS["_CAP_xAB_Function_Border_Green"],
},
},
"System Architecture Blank": {
**dict.fromkeys(
["Box.CP_IN", "Box.CP_OUT", "Box.CP_INOUT"],
{
"fill": COLORS["white"],
"stroke": COLORS["black"],
},
),
"Box.SystemComponent": {
"fill": [COLORS["_CAP_Actor_Blue_min"], COLORS["_CAP_Actor_Blue"]],
"stroke": COLORS["_CAP_Actor_Border_Blue"],
"text_fill": COLORS["_CAP_Actor_Blue_label"],
},
"Box.SystemFunction": {
"fill": COLORS["_CAP_xAB_Function_Green"],
"stroke": COLORS["_CAP_xAB_Function_Border_Green"],
},
"Edge.ComponentExchange": {
"stroke": COLORS["_CAP_Component_Border_Blue"],
"stroke-width": 2,
"text_fill": COLORS["_CAP_Component_Border_Blue"],
},
},
"System Data Flow Blank": {
"Box.FIP": {
"fill": COLORS["dark_orange"],
Expand Down
38 changes: 8 additions & 30 deletions capellambse/aird/diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,36 +190,14 @@ def snap_to_parent(self) -> None:

if self.port:
padding = (self.parent.PORT_OVERHANG, self.parent.PORT_OVERHANG)
# Distances of all corner combinations
# (our/parent's top-left/bottom-right)
d_tl_tl = self.pos - self.parent.pos
d_br_tl = self.pos + self.size - self.parent.pos
d_tl_br = self.pos - self.parent.pos - self.parent.size
d_br_br = self.pos + self.size - self.parent.pos - self.parent.size

# Find closest parent border (left vs. right and top vs. bottom)
d_tl = aird.Vector2D(
min(d_tl_tl.x, d_br_tl.x), min(d_tl_tl.y, d_br_tl.y)
)
d_br = aird.Vector2D(
min(d_tl_br.x, d_br_br.x), min(d_tl_br.y, d_br_br.y)
)
border = aird.Vector2D(
-1 if abs(d_tl.x) <= abs(d_br.x) else 1,
-1 if abs(d_tl.y) <= abs(d_br.y) else 1,
)

# Find out if horizontal or vertical border is closer
horiz = abs(d_tl.x if border.x < 0 else d_br.x) <= abs(
d_tl.y if border.y < 0 else d_br.y
)
border = border @ (horiz, not horiz)

self.pos = self.pos.boxsnap(
self.parent.pos - padding,
self.parent.pos + self.parent.size + padding - self.size,
border,
midbox_tl = self.parent.pos + self.size / 2 - padding
midbox_br = (
self.parent.pos + self.parent.size - self.size / 2 + padding
)
midbox = aird.Box(midbox_tl, midbox_br - midbox_tl)
mid = self.pos + self.size / 2
newmid = midbox.vector_snap(mid)
self.pos += newmid - mid
else:
padding = (self.parent.CHILD_MARGIN, self.parent.CHILD_MARGIN)
minpos = self.parent.pos + padding
Expand Down Expand Up @@ -253,7 +231,7 @@ def add_context(self, uuid: str) -> None:
self.parent.add_context(uuid)

def vector_snap(
self, vector: aird.Vec2ish, direction: aird.Vec2ish
self, vector: aird.Vec2ish, direction: aird.Vec2ish = (0, 0)
) -> aird.Vector2D:
"""Snap the ``vector`` into this Box, preferably into ``direction``."""
if not isinstance(vector, aird.Vector2D):
Expand Down
34 changes: 23 additions & 11 deletions capellambse/aird/vector2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,23 +170,35 @@ def boxsnap(
corner2
A Vector2D describing the second corner of the target box.
dirvec
A Vector2D pointing in the direction to snap towards.
Ignored.
"""
minx = min(corner1[0], corner2[0])
miny = min(corner1[1], corner2[1])
maxx = max(corner1[0], corner2[0])
maxy = max(corner1[1], corner2[1])

if abs(dirvec[0]) >= abs(dirvec[1]):
# Snap horizontally
return Vector2D(
(minx, maxx)[dirvec[0] > 0],
min(maxy - 1, max(miny + 1, self[1])),
)
# Snap vertically
return Vector2D(
min(maxx - 1, max(minx + 1, self[0])), (miny, maxy)[dirvec[1] > 0]
)
x, y = self.x, self.y
if x < minx:
x = minx
elif x > maxx:
x = maxx
if y < miny:
y = miny
elif y > maxy:
y = maxy

point = Vector2D(x, y)
if x != self.x or y != self.y:
return point

distances = [
Vector2D(self.x - minx, 0),
Vector2D(self.x - maxx, 0),
Vector2D(0, self.y - miny),
Vector2D(0, self.y - maxy),
]
offset = min(distances, key=lambda i: i.sqlength)
return point + offset

def __map(
self,
Expand Down
52 changes: 24 additions & 28 deletions capellambse/model/crosslayer/cs.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,6 @@
XT_PHYS_PATH_INV = "org.polarsys.capella.core.data.cs:PhysicalPathInvolvement"


class Component(c.GenericElement):
"""A template class for components."""

is_abstract = xmltools.BooleanAttributeProperty(
"_element",
"abstract",
__doc__="Boolean flag for an abstract Component",
)
is_human = xmltools.BooleanAttributeProperty(
"_element", "human", __doc__="Boolean flag for a human Component"
)
is_actor = xmltools.BooleanAttributeProperty(
"_element", "actor", __doc__="Boolean flag for an actor Component"
)

owner = c.ParentAccessor(c.GenericElement)
state_machines = c.ProxyAccessor(
capellacommon.StateMachine, aslist=c.ElementList
)

parts: c.Accessor


@c.xtype_handler(None)
class Part(c.GenericElement):
"""A representation of a physical component"""
Expand Down Expand Up @@ -113,6 +90,30 @@ class PhysicalLink(PhysicalPort):
physical_paths: c.Accessor


class Component(c.GenericElement):
"""A template class for components."""

is_abstract = xmltools.BooleanAttributeProperty(
"_element",
"abstract",
__doc__="Boolean flag for an abstract Component",
)
is_human = xmltools.BooleanAttributeProperty(
"_element", "human", __doc__="Boolean flag for a human Component"
)
is_actor = xmltools.BooleanAttributeProperty(
"_element", "actor", __doc__="Boolean flag for an actor Component"
)

owner = c.ParentAccessor(c.GenericElement)
state_machines = c.ProxyAccessor(
capellacommon.StateMachine, aslist=c.ElementList
)
ports = c.ProxyAccessor(fa.ComponentPort, aslist=c.ElementList)
physical_ports = c.ProxyAccessor(PhysicalPort, aslist=c.ElementList)
parts = c.ReferenceSearchingAccessor(Part, "type", aslist=c.ElementList)


@c.xtype_handler(None)
class PhysicalPath(c.GenericElement):
"""A physical path."""
Expand Down Expand Up @@ -144,11 +145,6 @@ class ComponentRealization(c.GenericElement):
_xmltag = "ownedComponentRealizations"


c.set_accessor(
Component,
"parts",
c.ReferenceSearchingAccessor(Part, "type", aslist=c.ElementList),
)
c.set_accessor(
InterfacePkg,
"packages",
Expand Down
58 changes: 50 additions & 8 deletions capellambse/model/crosslayer/fa.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,30 @@ class FunctionRealization(c.GenericElement):
class AbstractExchange(c.GenericElement):
"""Common code for Exchanges."""

source_port = c.AttrProxyAccessor(c.GenericElement, "source")
target_port = c.AttrProxyAccessor(c.GenericElement, "target")
source = c.AttrProxyAccessor(c.GenericElement, "source")
target = c.AttrProxyAccessor(c.GenericElement, "target")

@property
def source_port(self) -> c.GenericElement:
import warnings

warnings.warn(
"source_port is deprecated, use source instead",
FutureWarning,
stacklevel=2,
)
return self.source

@property
def target_port(self) -> c.GenericElement:
import warnings

warnings.warn(
"target_port is deprecated, use target instead",
FutureWarning,
stacklevel=2,
)
return self.target


@c.xtype_handler(None)
Expand Down Expand Up @@ -101,6 +123,18 @@ class FunctionOutputPort(FunctionPort):
)


class Function(AbstractFunction):
"""Common Code for Function's."""

is_leaf = property(lambda self: not self.functions)

inputs = c.ProxyAccessor(FunctionInputPort, aslist=c.ElementList)
outputs = c.ProxyAccessor(FunctionOutputPort, aslist=c.ElementList)

functions: c.Accessor
packages: c.Accessor


@c.xtype_handler(None)
class FunctionalExchange(AbstractExchange):
"""A functional exchange."""
Expand Down Expand Up @@ -136,7 +170,7 @@ class ComponentExchange(AbstractExchange):

_xmltag = "ownedComponentExchanges"

func_exchanges = c.ProxyAccessor(
allocated_functional_exchanges = c.ProxyAccessor(
FunctionalExchange,
XT_COMP_EX_FNC_EX_ALLOC,
aslist=c.ElementList,
Expand All @@ -148,12 +182,23 @@ class ComponentExchange(AbstractExchange):
aslist=c.ElementList,
)

@property
def func_exchanges(self) -> c.ElementList[FunctionalExchange]:
import warnings

warnings.warn(
"func_exchanges is deprecated, use allocated_functional_exchanges instead",
FutureWarning,
stacklevel=2,
)
return self.allocated_functional_exchanges

@property
def exchange_items(
self,
) -> c.ElementList[information.ExchangeItem]:
items = self.allocated_exchange_items
func_exchanges = self.func_exchanges
func_exchanges = self.allocated_functional_exchanges
assert isinstance(func_exchanges, cabc.Iterable)
for exchange in func_exchanges:
items += exchange.exchange_items
Expand All @@ -169,10 +214,7 @@ def exchange_items(
_port,
"exchanges",
c.ReferenceSearchingAccessor(
_exchange,
"source_port",
"target_port",
aslist=c.ElementList,
_exchange, "source", "target", aslist=c.ElementList
),
)
del _port, _exchange
Expand Down
Loading

0 comments on commit 836a19e

Please sign in to comment.