示例#1
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
示例#2
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
示例#3
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
示例#4
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())
示例#5
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())