Beispiel #1
0
 def size(self, context: UpdateContext):
     style = merge_styles(context.style, self._inline_style)
     min_width = style.get("min-width", 0)
     min_height = style.get("min-height", 0)
     padding_top, padding_right, padding_bottom, padding_left = style[
         "padding"]
     self.sizes = [c.size(context) for c in self.children]
     width, height = self.icon.size(context)
     return (
         max(min_width, width + padding_right + padding_left),
         max(min_height, height + padding_top + padding_bottom),
     )
Beispiel #2
0
    def draw(self, context: DrawContext, bounding_box: Rectangle):
        """Draw the editable text."""
        super().draw(context, bounding_box)
        style = merge_styles(context.style, self._inline_style)

        text_box = self.text_box(style, bounding_box)
        text_align = style.get("text-align", TextAlign.CENTER)
        focus_box = self.focus_box
        x, y = focus_box_pos(text_box, (focus_box.width, focus_box.height),
                             text_align)
        focus_box.x = x
        focus_box.y = y

        text_draw_focus_box(context, *focus_box)
Beispiel #3
0
    def draw(self, context: DrawContext, bounding_box: Rectangle):
        style = merge_styles(context.style, self._inline_style)
        new_context = replace(context, style=style)
        padding_top, padding_right, padding_bottom, padding_left = style[
            "padding"]
        x = bounding_box.x + padding_left
        y = bounding_box.y + padding_top
        w = bounding_box.width - padding_right - padding_left
        h = bounding_box.height - padding_top - padding_bottom
        self.icon.draw(new_context, Rectangle(x, y, w, h))

        cx, cy, max_w, total_h = self.child_pos(style, bounding_box)
        for c, (cw, ch) in zip(self.children, self.sizes):
            c.draw(context, Rectangle(cx + (max_w - cw) / 2, cy, cw, ch))
            cy += ch
Beispiel #4
0
    def draw(self, context: DrawContext, bounding_box: Rectangle):
        """Draw the text, return the location and size."""
        style = merge_styles(context.style, self._inline_style)
        min_w = max(style.get("min-width", 0), bounding_box.width)
        min_h = max(style.get("min-height", 0), bounding_box.height)
        text_box = self.text_box(style, bounding_box)

        with cairo_state(context.cairo) as cr:
            text_color = style.get("text-color")
            if text_color:
                cr.set_source_rgba(*text_color)

            layout = self._layout
            cr.move_to(text_box.x, text_box.y)
            layout.set(font=style)
            layout.show_layout(cr, text_box.width, default_size=(min_w, min_h))
Beispiel #5
0
    def size(self, context: UpdateContext):
        style = merge_styles(context.style, self._inline_style)
        min_w = style.get("min-width", 0)
        min_h = style.get("min-height", 0)
        text_align = style.get("text-align", TextAlign.CENTER)
        padding_top, padding_right, padding_bottom, padding_left = style[
            "padding"]

        layout = self._layout
        layout.set(text=self.text(),
                   font=style,
                   width=self.width(),
                   text_align=text_align)
        width, height = layout.size()
        return (
            max(min_w, width + padding_right + padding_left),
            max(min_h, height + padding_top + padding_bottom),
        )
Beispiel #6
0
 def size(self, context: UpdateContext):
     style: Style = merge_styles(context.style, self._inline_style)
     min_width = style.get("min-width", 0)
     min_height = style.get("min-height", 0)
     padding_top, padding_right, padding_bottom, padding_left = style[
         "padding"]
     self.sizes = sizes = [c.size(context) for c in self.children]
     if sizes:
         widths, heights = list(zip(*sizes))
         return (
             max(
                 min_width,
                 max(widths) + padding_right + padding_left,
             ),
             max(
                 min_height,
                 sum(heights) + padding_top + padding_bottom,
             ),
         )
     else:
         return min_width, min_height
Beispiel #7
0
    def draw(self, context):
        def draw_line_end(end_handle, second_handle, draw):
            pos, p1 = end_handle.pos, second_handle.pos
            angle = atan2(p1.y - pos.y, p1.x - pos.x)
            cr = context.cairo
            cr.save()
            try:
                cr.translate(*pos)
                cr.rotate(angle)
                draw(context)
            finally:
                cr.restore()

        style = merge_styles(context.style, self.style)
        context = replace(context, style=style)

        cr = context.cairo
        cr.set_line_width(style["line-width"])
        cr.set_dash(style.get("dash-style", ()), 0)
        stroke = style["color"]
        if stroke:
            cr.set_source_rgba(*stroke)

        handles = self._handles
        draw_line_end(handles[0], handles[1], self.draw_head)

        for h in self._handles[1:-1]:
            cr.line_to(*h.pos)

        draw_line_end(handles[-1], handles[-2], self.draw_tail)

        cr.stroke()

        for shape, rect in (
            (self.shape_head, self._shape_head_rect),
            (self.shape_middle, self._shape_middle_rect),
            (self.shape_tail, self._shape_tail_rect),
        ):
            if shape:
                shape.draw(context, rect)
Beispiel #8
0
    def draw(self, context: DrawContext, bounding_box: Rectangle):
        style: Style = merge_styles(context.style, self._inline_style)
        new_context = replace(context, style=style)
        padding_top, padding_right, padding_bottom, padding_left = style[
            "padding"]
        valign = style.get("vertical-align", VerticalAlign.MIDDLE)
        height = sum(h for _w, h in self.sizes)

        if self._draw_border:
            self._draw_border(self, new_context, bounding_box)
        x = bounding_box.x + padding_left
        if valign is VerticalAlign.MIDDLE:
            y = (bounding_box.y + padding_top +
                 (max(height, bounding_box.height - padding_top) - height) / 2)
        elif valign is VerticalAlign.BOTTOM:
            y = bounding_box.y + bounding_box.height - height - padding_bottom
        else:
            y = bounding_box.y + padding_top
        w = bounding_box.width - padding_right - padding_left
        for c, (_w, h) in zip(self.children, self.sizes):
            c.draw(context, Rectangle(x, y, w, h))
            y += h
Beispiel #9
0
    def post_update(self, context, p1, p2):
        """Update label placement for association's name and multiplicity
        label.

        p1 is the line end and p2 is the last but one point of the line.
        """
        style = merge_styles(context.style, self._inline_style)
        ofs = 5

        dx = float(p2[0]) - float(p1[0])
        dy = float(p2[1]) - float(p1[1])

        def max_text_size(size1, size2):
            w1, h1 = size1
            w2, h2 = size2
            return (max(w1, w2), max(h1, h2))

        name_layout = self._name_layout
        name_layout.set_text(self._name)
        name_layout.set_font(style)
        name_w, name_h = max_text_size(name_layout.size(), (10, 10))

        mult_layout = self._mult_layout
        mult_layout.set_text(self._mult)
        mult_layout.set_font(style)
        mult_w, mult_h = max_text_size(mult_layout.size(), (10, 10))

        if dy == 0:
            rc = 1000.0  # quite a lot...
        else:
            rc = dx / dy
        abs_rc = abs(rc)
        h = dx > 0  # right side of the box
        v = dy > 0  # bottom side

        if abs_rc > 6:
            # horizontal line
            if h:
                name_dx = ofs
                name_dy = -ofs - name_h
                mult_dx = ofs
                mult_dy = ofs
            else:
                name_dx = -ofs - name_w
                name_dy = -ofs - name_h
                mult_dx = -ofs - mult_w
                mult_dy = ofs
        elif 0 <= abs_rc <= 0.2:
            # vertical line
            if v:
                name_dx = -ofs - name_w
                name_dy = ofs
                mult_dx = ofs
                mult_dy = ofs
            else:
                name_dx = -ofs - name_w
                name_dy = -ofs - name_h
                mult_dx = ofs
                mult_dy = -ofs - mult_h
        else:
            # Should both items be placed on the same side of the line?
            r = abs_rc < 1.0

            # Find out alignment of text (depends on the direction of the line)
            align_left = h ^ r
            align_bottom = v ^ r
            if align_left:
                name_dx = ofs
                mult_dx = ofs
            else:
                name_dx = -ofs - name_w
                mult_dx = -ofs - mult_w
            if align_bottom:
                name_dy = -ofs - name_h
                mult_dy = -ofs - name_h - mult_h
            else:
                name_dy = ofs
                mult_dy = ofs + mult_h

        self._name_bounds = Rectangle(p1[0] + name_dx,
                                      p1[1] + name_dy,
                                      width=name_w,
                                      height=name_h)

        self._mult_bounds = Rectangle(p1[0] + mult_dx,
                                      p1[1] + mult_dy,
                                      width=mult_w,
                                      height=mult_h)
Beispiel #10
0
def test_merge_opacity():
    style = merge_styles({"color": (0, 0, 1, 1), "opacity": 0.7})

    assert style["color"] == (0, 0, 1, 0.7)
Beispiel #11
0
def test_font_size_override_with_relative_size():
    style = merge_styles({"font-size": 10}, {"font-size": 24},
                         {"font-size": "x-small"})

    assert style["font-size"] == 24 * 3 / 4
Beispiel #12
0
def test_final_font_size_is_a_number():
    style = merge_styles({"font-size": 10}, {"font-size": "x-small"},
                         {"font-size": 24})

    assert style["font-size"] == 24
Beispiel #13
0
def test_font_size(font_size, factor):
    style = merge_styles({"font-size": 10}, {"font-size": font_size})

    assert style["font-size"] == 10 * factor
Beispiel #14
0
def test_merge_opacity_with_transparency():
    style = merge_styles({"color": (0, 0, 0, 0.8), "opacity": 0.5})

    assert style["color"] == (0, 0, 0, 0.4)