Beispiel #1
0
    def __init__(self, connections, id=None, model=None):
        super().__init__(id=id, model=model)
        self._matrix = Matrix()
        self._matrix_i2c = Matrix()
        self._connections = connections

        h1, h2 = Handle(), Handle()
        self._handles = [h1, h2]
        self._ports = [LinePort(h1.pos, h2.pos)]

        self._combined = None

        self.shape = IconBox(
            Box(style={"min-width": 0, "min-height": 45}, draw=self.draw_fork_node),
            Text(
                text=lambda: stereotypes_str(self.subject),
            ),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
            Text(
                text=lambda: isinstance(self.subject, UML.JoinNode)
                and self.subject.joinSpec not in (None, DEFAULT_JOIN_SPEC)
                and f"{{ joinSpec = {self.subject.joinSpec} }}"
                or "",
            ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject[JoinNode].joinSpec")

        connections.add_constraint(self, constraint(vertical=(h1.pos, h2.pos)))
        connections.add_constraint(self, constraint(above=(h1.pos, h2.pos), delta=30))
Beispiel #2
0
    def __init__(self, diagram, id=None):
        super().__init__(diagram, id=id)

        h1, h2 = Handle(), Handle()
        self._handles = [h1, h2]
        self._ports = [LinePort(h1.pos, h2.pos)]
        self.watch_handle(h1)
        self.watch_handle(h2)

        self.shape = IconBox(
            Box(draw=self.draw_fork_node),
            Text(
                text=lambda: stereotypes_str(self.subject),
            ),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
            Text(
                text=lambda: isinstance(self.subject, UML.JoinNode)
                and self.subject.joinSpec not in (None, DEFAULT_JOIN_SPEC)
                and f"{{ joinSpec = {self.subject.joinSpec} }}"
                or "",
            ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject[JoinNode].joinSpec")

        diagram.connections.add_constraint(self, constraint(vertical=(h1.pos, h2.pos)))
        diagram.connections.add_constraint(
            self, constraint(above=(h1.pos, h2.pos), delta=30)
        )
Beispiel #3
0
    def __init__(self, id=None, model=None):
        super().__init__(id, model)

        h1, h2 = Handle(), Handle()
        self._handles.append(h1)
        self._handles.append(h2)
        self._ports.append(LinePort(h1.pos, h2.pos))

        self._combined = None

        self.shape = IconBox(
            Box(style={"min-width": 0, "min-height": 45}, draw=self.draw_fork_node),
            Text(
                text=lambda: stereotypes_str(self.subject),
                style={"min-width": 0, "min-height": 0},
            ),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
            Text(
                text=lambda: isinstance(self.subject, UML.JoinNode)
                and self.subject.joinSpec not in (None, DEFAULT_JOIN_SPEC)
                and f"{{ joinSpec = {self.subject.joinSpec} }}"
                or "",
                style={"min-width": 0, "min-height": 0},
            ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject[JoinNode].joinSpec")
Beispiel #4
0
 def update_shapes(self):
     self.shape = IconBox(
         Box(style={"background-color": (1, 1, 1, 1)}, draw=draw_border),
         Text(text=lambda: stereotypes_str(self.subject, ("proxy", ))),
         EditableText(
             text=lambda: self.subject and self.subject.name or ""),
         style=text_position(self.connected_side()),
     )
     self.request_update()
Beispiel #5
0
def test_draw_icon_box(cr):
    box_drawn = None

    def box_draw(box, context, bounding_box):
        nonlocal box_drawn
        box_drawn = bounding_box

    shape = IconBox(Box(draw=box_draw), Text(text="some text"))

    bounding_box = Rectangle(11, 12, 13, 14)
    shape.draw(cr, bounding_box)

    assert box_drawn == bounding_box
Beispiel #6
0
def test_icon_box_child_placement_right_middle(context):
    style = {"text-align": TextAlign.RIGHT, "vertical-align": VerticalAlign.MIDDLE}

    text = Text(text="some text")
    shape = IconBox(Box(), text,)
    shape.size(context)

    w, h = shape.sizes[0]
    bounding_box = Rectangle(0, 0, 10, 20)

    x, y, _, _ = shape.child_pos(style, bounding_box)

    assert x == bounding_box.width
    assert y == (bounding_box.height - h) / 2
Beispiel #7
0
def test_icon_box_child_placement_center_bottom(context):
    style = {"text-align": TextAlign.CENTER, "vertical-align": VerticalAlign.BOTTOM}

    text = Text(text="some text")
    shape = IconBox(Box(), text,)
    shape.size(context)

    w, h = shape.sizes[0]
    bounding_box = Rectangle(0, 0, 10, 20)

    x, y, _, _ = shape.child_pos(style, bounding_box)

    assert x == (bounding_box.width - w) / 2
    assert y == bounding_box.height
Beispiel #8
0
    def __init__(self, id=None, model=None):
        super().__init__(id, model)

        self.shape = IconBox(
            Box(
                style={
                    "min-width": ARM * 2,
                    "min-height": HEAD + NECK + BODY + ARM
                },
                draw=draw_actor,
            ),
            Text(
                text=lambda: stereotypes_str(self.subject),
                style={
                    "min-width": 0,
                    "min-height": 0
                },
            ),
            EditableText(
                text=lambda: self.subject.name or "",
                style={"font-weight": FontWeight.BOLD},
            ),
        )

        self.watch("subject<NamedElement>.name")
        self.watch("subject.appliedStereotype.classifier.name")
Beispiel #9
0
 def update_shapes(self, event=None):
     if self._folded == Folded.NONE:
         self.shape = Box(
             Box(
                 Text(
                     text=lambda: UML.model.stereotypes_str(
                         self.subject, ("interface", )),
                     style={
                         "min-width": 0,
                         "min-height": 0
                     },
                 ),
                 EditableText(
                     text=lambda: self.subject.name or "",
                     style={"font-weight": FontWeight.BOLD},
                 ),
                 Text(
                     text=lambda: from_package_str(self),
                     style={
                         "font": "sans 8",
                         "min-width": 0,
                         "min-height": 0
                     },
                 ),
                 style={"padding": (12, 4, 12, 4)},
             ),
             *(self.show_attributes and self.subject
               and [attributes_compartment(self.subject)] or []),
             *(self.show_operations and self.subject
               and [operations_compartment(self.subject)] or []),
             *(self.show_stereotypes_attrs
               and stereotype_compartments(self.subject) or []),
             style={
                 "min-width": 100,
                 "min-height": 50,
                 "vertical-align": VerticalAlign.TOP,
             },
             draw=draw_border,
         )
     else:
         self.shape = IconBox(
             Box(
                 style={
                     "min-width": self.min_width,
                     "min-height": self.min_height
                 },
                 draw=self.draw_interface_ball_and_socket,
             ),
             Text(
                 text=lambda: UML.model.stereotypes_str(self.subject),
                 style={
                     "min-width": 0,
                     "min-height": 0
                 },
             ),
             EditableText(
                 text=lambda: self.subject.name or "",
                 style={"font-weight": FontWeight.BOLD},
             ),
         )
Beispiel #10
0
    def __init__(self, diagram, id=None):
        super().__init__(
            diagram,
            id,
            shape=IconBox(
                Box(
                    Text(text=lambda: stereotypes_str(self.subject), ),
                    EditableText(text=lambda: self.subject.name or ""),
                    style={
                        "min-width": 50,
                        "min-height": 30,
                        "padding": (5, 10, 5, 10),
                    },
                    draw=draw_border,
                ),
                Text(text=lambda: self.subject.upperBound not in
                     (None, "", DEFAULT_UPPER_BOUND) and
                     f"{{ upperBound = {self.subject.upperBound} }}" or "", ),
                Text(text=lambda: self.show_ordering and self.subject.ordering
                     and f"{{ ordering = {self.subject.ordering} }}" or "", ),
            ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject[ObjectNode].upperBound")
        self.watch("subject[ObjectNode].ordering")
        self.watch("show_ordering")
Beispiel #11
0
 def ball_and_socket_shape(self, connectors=None):
     assert self.canvas
     if connectors is None:
         # distinguish between None and []
         connected_items = [
             c.item for c in self.canvas.get_connections(connected=self)
         ]
         connectors = any(
             map(lambda i: isinstance(i.subject, UML.Connector),
                 connected_items))
     return IconBox(
         Box(
             style={
                 "min-width": self.min_width,
                 "min-height": self.min_height
             },
             draw=self.draw_interface_ball_and_socket,
         ),
         Text(text=lambda: UML.model.stereotypes_str(self.subject), ),
         EditableText(
             text=lambda: self.subject.name or "",
             style={
                 "font-weight":
                 FontWeight.NORMAL if connectors else FontWeight.BOLD
             },
         ),
     )
Beispiel #12
0
 def update_shapes(self):
     self.shape = IconBox(
         Box(draw=draw_history_pseudostate if self.subject and self.subject.
             kind == "shallowHistory" else draw_initial_pseudostate),
         Text(text=lambda: stereotypes_str(self.subject), ),
         EditableText(text=lambda: self.subject.name or ""),
     )
Beispiel #13
0
    def __init__(self, id=None, model=None):
        super().__init__(id, model)
        no_movable_handles(self)

        self._combined = None

        self.shape = IconBox(
            Box(style={
                "min-width": 20,
                "min-height": 30
            },
                draw=draw_decision_node),
            # Text should be left-top
            Text(
                text=lambda: stereotypes_str(self.subject),
                style={
                    "min-width": 0,
                    "min-height": 0
                },
            ),
            EditableText(
                text=lambda: self.subject and self.subject.name or ""),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
Beispiel #14
0
    def update_shapes(self, event=None):
        if self.subject and self.subject.kind == "shallowHistory":
            box = Box(draw=draw_history_pseudostate)
            self.handles()[SE].pos = (30, 30)
        else:
            box = Box(draw=draw_initial_pseudostate)
            self.handles()[SE].pos = (20, 20)

        self.shape = IconBox(
            box,
            Text(text=lambda: stereotypes_str(self.subject), ),
            EditableText(text=lambda: self.subject.name or ""),
        )
Beispiel #15
0
    def __init__(self, id=None, model=None):
        super().__init__(id, model)
        no_movable_handles(self)

        self.shape = IconBox(
            Box(style={"min-width": 20, "min-height": 20}, draw=draw_flow_final_node),
            # Text should be right-bottom
            Text(text=lambda: stereotypes_str(self.subject),),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
Beispiel #16
0
    def __init__(self, diagram, id=None):
        super().__init__(diagram, id, width=30, height=30)
        for h in self.handles():
            h.movable = False

        self.shape = IconBox(
            Box(draw=draw_final_state),
            Text(text=lambda: stereotypes_str(self.subject), ),
            EditableText(
                text=lambda: self.subject and self.subject.name or ""),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
Beispiel #17
0
    def __init__(self, id=None, model=None):
        super().__init__(id, model)
        for h in self.handles():
            h.movable = False
        self.shape = IconBox(
            Box(draw=draw_history_pseudostate),
            Text(
                text=lambda: stereotypes_str(self.subject),
                style={"min-width": 0, "min-height": 0},
            ),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
Beispiel #18
0
    def __init__(self, diagram, id=None):
        super().__init__(diagram, id, width=30, height=30)
        no_movable_handles(self)

        self.shape = IconBox(
            Box(draw=draw_activity_final_node),
            # Text should be right-bottom
            Text(
                text=lambda: stereotypes_str(self.subject),
            ),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
Beispiel #19
0
    def __init__(self, id=None, model=None):
        super().__init__(id, model)

        self._show_ordering = False

        self.shape = IconBox(
            Box(
                Text(
                    text=lambda: stereotypes_str(self.subject),
                    style={
                        "min-width": 0,
                        "min-height": 0
                    },
                ),
                EditableText(text=lambda: self.subject.name or ""),
                style={
                    "min-width": 50,
                    "min-height": 30,
                    "padding": (5, 10, 5, 10)
                },
                draw=draw_border,
            ),
            Text(
                text=lambda: self.subject.upperBound not in
                (None, DEFAULT_UPPER_BOUND
                 ) and f"{{ upperBound = {self.subject.upperBound} }}",
                style={
                    "min-width": 0,
                    "min-height": 0
                },
            ),
            Text(
                text=lambda: self._show_ordering and self.subject.ordering and
                f"{{ ordering = {self.subject.ordering} }}",
                style={
                    "min-width": 0,
                    "min-height": 0
                },
            ),
        )

        self.watch("subject<NamedElement>.name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject<ObjectNode>.upperBound")
        self.watch("subject<ObjectNode>.ordering")
Beispiel #20
0
    def __init__(self, diagram, id=None):
        super().__init__(diagram, id, width=ARM * 2, height=HEAD + NECK + BODY + ARM)

        self.shape = IconBox(
            Box(
                draw=draw_actor,
            ),
            Text(
                text=lambda: stereotypes_str(self.subject),
            ),
            EditableText(
                text=lambda: self.subject.name or "",
                style={"font-weight": FontWeight.BOLD},
            ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
Beispiel #21
0
    def update_shapes(self, event=None):
        if self.subject and self.subject.kind == "shallowHistory":
            box = Box(style={
                "min-height": 30,
                "min-width": 30
            },
                      draw=draw_history_pseudostate)
        else:
            box = Box(style={
                "min-height": 20,
                "min-width": 20
            },
                      draw=draw_initial_pseudostate)

        self.shape = IconBox(
            box,
            Text(text=lambda: stereotypes_str(self.subject), ),
            EditableText(text=lambda: self.subject.name or ""),
        )
Beispiel #22
0
class ForkNodeItem(Presentation[UML.ForkNode], HandlePositionUpdate, Named):
    """Representation of fork and join node."""

    def __init__(self, diagram, id=None):
        super().__init__(diagram, id=id)

        h1, h2 = Handle(), Handle()
        self._handles = [h1, h2]
        self._ports = [LinePort(h1.pos, h2.pos)]
        self.watch_handle(h1)
        self.watch_handle(h2)

        self.shape = IconBox(
            Box(draw=self.draw_fork_node),
            Text(
                text=lambda: stereotypes_str(self.subject),
            ),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
            Text(
                text=lambda: isinstance(self.subject, UML.JoinNode)
                and self.subject.joinSpec not in (None, DEFAULT_JOIN_SPEC)
                and f"{{ joinSpec = {self.subject.joinSpec} }}"
                or "",
            ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject[JoinNode].joinSpec")

        diagram.connections.add_constraint(self, constraint(vertical=(h1.pos, h2.pos)))
        diagram.connections.add_constraint(
            self, constraint(above=(h1.pos, h2.pos), delta=30)
        )

    combined: relation_one[UML.ControlNode] = association(
        "combined", UML.ControlNode, upper=1
    )

    def handles(self):
        return self._handles

    def ports(self):
        return self._ports

    def pre_update(self, context):
        pass

    def post_update(self, context):
        pass

    def save(self, save_func):
        save_func("matrix", tuple(self.matrix))
        save_func("height", float(self._handles[1].pos.y))
        super().save(save_func)

    def load(self, name, value):
        if name == "matrix":
            self.matrix.set(*ast.literal_eval(value))
        elif name == "height":
            self._handles[1].pos.y = ast.literal_eval(value)
        else:
            super().load(name, value)

    def draw(self, context):
        h1, h2 = self.handles()
        height = h2.pos.y - h1.pos.y
        self.shape.draw(context, Rectangle(0, 0, 1, height))

    def draw_fork_node(self, _box, context, _bounding_box):
        """
        Draw vertical line - symbol of fork and join nodes. Join
        specification is also drawn above the item.
        """
        cr = context.cairo

        cr.set_line_width(6)
        stroke = context.style.get("color")
        if stroke:
            cr.set_source_rgba(*stroke)
        h1, h2 = self._handles
        cr.move_to(h1.pos.x, h1.pos.y)
        cr.line_to(h2.pos.x, h2.pos.y)
        cr.stroke()

    def point(self, x, y):
        h1, h2 = self._handles
        d, p = distance_line_point(h1.pos, h2.pos, (x, y))
        # Subtract line_width / 2
        return d - 3
Beispiel #23
0
class ForkNodeItem(Presentation[UML.ForkNode], Item, Named):
    """
    Representation of fork and join node.
    """
    def __init__(self, id=None, model=None):
        super().__init__(id, model)

        h1, h2 = Handle(), Handle()
        self._handles.append(h1)
        self._handles.append(h2)
        self._ports.append(LinePort(h1.pos, h2.pos))

        self._combined = None

        self.shape = IconBox(
            Box(style={
                "min-width": 0,
                "min-height": 45
            },
                draw=self.draw_fork_node),
            Text(text=lambda: stereotypes_str(self.subject), ),
            EditableText(
                text=lambda: self.subject and self.subject.name or ""),
            Text(text=lambda: isinstance(self.subject, UML.JoinNode) and self.
                 subject.joinSpec not in (None, DEFAULT_JOIN_SPEC) and
                 f"{{ joinSpec = {self.subject.joinSpec} }}" or "", ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject[JoinNode].joinSpec")

        self.constraint(vertical=(h1.pos, h2.pos))
        self.constraint(above=(h1.pos, h2.pos), delta=30)

    def save(self, save_func):
        save_func("matrix", tuple(self.matrix))
        save_func("height", float(self._handles[1].pos.y))
        if self._combined:
            save_func("combined", self._combined)
        super().save(save_func)

    def load(self, name, value):
        if name == "matrix":
            self.matrix = ast.literal_eval(value)
        elif name == "height":
            self._handles[1].pos.y = ast.literal_eval(value)
        elif name == "combined":
            self._combined = value
        else:
            # DiagramItem.load(self, name, value)
            super().load(name, value)

    @observed
    def _set_combined(self, value):
        # self.preserve_property('combined')
        self._combined = value

    combined = reversible_property(lambda s: s._combined, _set_combined)

    def draw(self, context):
        h1, h2 = self.handles()
        height = h2.pos.y - h1.pos.y
        self.shape.draw(context, Rectangle(0, 0, 1, height))

    def draw_fork_node(self, _box, context, _bounding_box):
        """
        Draw vertical line - symbol of fork and join nodes. Join
        specification is also drawn above the item.
        """
        cr = context.cairo

        cr.set_line_width(6)
        h1, h2 = self._handles
        cr.move_to(h1.pos.x, h1.pos.y)
        cr.line_to(h2.pos.x, h2.pos.y)

        stroke(context)

    def point(self, pos):
        h1, h2 = self._handles
        d, p = distance_line_point(h1.pos, h2.pos, pos)
        # Subtract line_width / 2
        return d - 3
Beispiel #24
0
class ForkNodeItem(UML.Presentation, Item):
    """
    Representation of fork and join node.
    """

    def __init__(self, id=None, model=None):
        super().__init__(id, model)

        h1, h2 = Handle(), Handle()
        self._handles.append(h1)
        self._handles.append(h2)
        self._ports.append(LinePort(h1.pos, h2.pos))

        self._combined = None

        self.shape = IconBox(
            Box(style={"min-width": 0, "min-height": 45}, draw=self.draw_fork_node),
            Text(
                text=lambda: stereotypes_str(self.subject),
                style={"min-width": 0, "min-height": 0},
            ),
            EditableText(text=lambda: self.subject and self.subject.name or ""),
            Text(
                text=lambda: isinstance(self.subject, UML.JoinNode)
                and self.subject.joinSpec not in (None, DEFAULT_JOIN_SPEC)
                and f"{{ joinSpec = {self.subject.joinSpec} }}"
                or "",
                style={"min-width": 0, "min-height": 0},
            ),
        )

        self.watch("subject[NamedElement].name")
        self.watch("subject.appliedStereotype.classifier.name")
        self.watch("subject[JoinNode].joinSpec")

    def save(self, save_func):
        save_func("matrix", tuple(self.matrix))
        save_func("height", float(self._handles[1].pos.y))
        if self._combined:
            save_func("combined", self._combined, reference=True)
        super().save(save_func)

    def load(self, name, value):
        if name == "matrix":
            self.matrix = ast.literal_eval(value)
        elif name == "height":
            self._handles[1].pos.y = ast.literal_eval(value)
        elif name == "combined":
            self._combined = value
        else:
            # DiagramItem.load(self, name, value)
            super().load(name, value)

    @observed
    def _set_combined(self, value):
        # self.preserve_property('combined')
        self._combined = value

    combined = reversible_property(lambda s: s._combined, _set_combined)

    def setup_canvas(self):
        assert self.canvas
        super().setup_canvas()

        h1, h2 = self._handles
        cadd = self.canvas.solver.add_constraint
        c1 = EqualsConstraint(a=h1.pos.x, b=h2.pos.x)
        c2 = LessThanConstraint(smaller=h1.pos.y, bigger=h2.pos.y, delta=30)
        self.__constraints = (cadd(c1), cadd(c2))
        list(map(self.canvas.solver.add_constraint, self.__constraints))

    def teardown_canvas(self):
        assert self.canvas
        super().teardown_canvas()
        list(map(self.canvas.solver.remove_constraint, self.__constraints))

    def pre_update(self, context):
        cr = context.cairo
        _, h2 = self.handles()
        _, height = self.shape.size(cr)
        h2.pos.y = max(h2.pos.y, height)

    def draw(self, context):
        h1, h2 = self.handles()
        height = h2.pos.y - h1.pos.y
        self.shape.draw(context, Rectangle(0, 0, 1, height))

    def draw_fork_node(self, _box, context, _bounding_box):
        """
        Draw vertical line - symbol of fork and join nodes. Join
        specification is also drawn above the item.
        """
        cr = context.cairo

        cr.set_line_width(6)
        h1, h2 = self._handles
        cr.move_to(h1.pos.x, h1.pos.y)
        cr.line_to(h2.pos.x, h2.pos.y)

        cr.stroke()

    def point(self, pos):
        h1, h2 = self._handles
        d, p = distance_line_point(h1.pos, h2.pos, pos)
        # Substract line_width / 2
        return d - 3
Beispiel #25
0
class ProxyPortItem(Presentation[sysml.ProxyPort], Named):
    def __init__(self, connections, id=None, model=None):
        super().__init__(id=id, model=model)
        self._matrix = Matrix()
        self._matrix_i2c = Matrix()
        self._connections = connections

        h1 = Handle(connectable=True)
        self._handles = [h1]

        d = self.dimensions()
        top_left = Position(d.x, d.y)
        top_right = Position(d.x1, d.y)
        bottom_right = Position(d.x1, d.y1)
        bottom_left = Position(d.x, d.y1)
        self._ports = [
            LinePort(top_left, top_right),
            LinePort(top_right, bottom_right),
            LinePort(bottom_right, bottom_left),
            LinePort(bottom_left, top_left),
        ]

        self._last_connected_side = None
        self.watch("subject[NamedElement].name")
        self.update_shapes()

    @property
    def matrix(self) -> Matrix:
        return self._matrix

    @property
    def matrix_i2c(self) -> Matrix:
        return self._matrix_i2c

    def handles(self):
        return self._handles

    def ports(self):
        return self._ports

    def update_shapes(self):
        self.shape = IconBox(
            Box(style={"background-color": (1, 1, 1, 1)}, draw=draw_border),
            Text(text=lambda: stereotypes_str(self.subject, ("proxy", ))),
            EditableText(
                text=lambda: self.subject and self.subject.name or ""),
            style=text_position(self.connected_side()),
        )
        self.request_update()

    def connected_side(self) -> Optional[str]:
        cinfo = self._connections.get_connection(self._handles[0])

        return cinfo.connected.port_side(cinfo.port) if cinfo else None

    def dimensions(self):
        return Rectangle(-8, -8, 16, 16)

    def point(self, x, y):
        return distance_rectangle_point(self.dimensions(), (x, y))

    def save(self, save_func):
        save_func("matrix", tuple(self.matrix))

        c = self._connections.get_connection(self.handles()[0])
        if c:
            save_func("connection", c.connected)

        super().save(save_func)

    def load(self, name, value):
        if name == "matrix":
            self.matrix.set(*ast.literal_eval(value))
        elif name == "connection":
            self._load_connection = value
        else:
            super().load(name, value)

    def postload(self):
        super().postload()
        if hasattr(self, "_load_connection"):
            postload_connect(self, self.handles()[0], self._load_connection)
            del self._load_connection

        self.update_shapes()

    def pre_update(self, context):
        side = self.connected_side()
        if self._last_connected_side != side:
            self._last_connected_side = side
            self.update_shapes()

        self.shape.size(context)

    def post_update(self, context):
        pass

    def draw(self, context):
        self.shape.draw(context, self.dimensions())
Beispiel #26
0
class ProxyPortItem(Presentation[sysml.ProxyPort], Item, Named):
    def __init__(self, id=None, model=None):
        super().__init__(id, model)

        h1 = Handle(connectable=True)
        self._handles.append(h1)

        d = self.dimensions()
        top_left = Position((d.x, d.y))
        top_right = Position((d.x1, d.y))
        bottom_right = Position((d.x1, d.y1))
        bottom_left = Position((d.x, d.y1))
        self._ports.append(LinePort(top_left, top_right))
        self._ports.append(LinePort(top_right, bottom_right))
        self._ports.append(LinePort(bottom_right, bottom_left))
        self._ports.append(LinePort(bottom_left, top_left))

        self._last_connected_side = None
        self.watch("subject[NamedElement].name")

    def update_shapes(self):
        self.shape = IconBox(
            Box(style={"background-color": (1, 1, 1, 1)}, draw=draw_border),
            Text(text=lambda: stereotypes_str(self.subject, ("proxy", ))),
            EditableText(
                text=lambda: self.subject and self.subject.name or ""),
            style=text_position(self.connected_side()),
        )
        self.request_update()

    def connected_side(self) -> Optional[str]:
        if not self.canvas:
            return None

        cinfo = self.canvas.get_connection(self._handles[0])

        return cinfo.connected.port_side(cinfo.port) if cinfo else None

    def dimensions(self):
        return Rectangle(-8, -8, 16, 16)

    def point(self, pos):
        return distance_rectangle_point(self.dimensions(), pos)

    def setup_canvas(self):
        super().setup_canvas()
        self.subscribe_all()
        # Invoke here, since we do not receive events, unless we're attached to a canvas
        self.update_shapes()

    def teardown_canvas(self):
        self.unsubscribe_all()
        super().teardown_canvas()

    def save(self, save_func):
        save_func("matrix", tuple(self.matrix))

        assert self.canvas
        c = self.canvas.get_connection(self.handles()[0])
        if c:
            save_func("connection", c.connected)

        super().save(save_func)

    def load(self, name, value):
        if name == "matrix":
            self.matrix = ast.literal_eval(value)
        elif name == "connection":
            self._load_connection = value
        else:
            super().load(name, value)

    def postload(self):
        super().postload()
        if hasattr(self, "_load_connection"):
            postload_connect(self, self.handles()[0], self._load_connection)
            del self._load_connection

        self.update_shapes()

    def pre_update(self, context):
        side = self.connected_side()
        if self._last_connected_side != side:
            self._last_connected_side = side
            self.update_shapes()

        self.shape.size(context)

    def draw(self, context):
        self.shape.draw(context, self.dimensions())