~fabrixxm/confy

9840f9e1c88cfb642aea5cacbfed24b8b592b0f9 — fabrixxm 8 months ago 42cddb8
Use Cairo again to draw line in EventActionRow

can't figure how to do it wihout Cairo. It works. I'm happy.
1 files changed, 70 insertions(+), 8 deletions(-)

M src/widgets.py
M src/widgets.py => src/widgets.py +70 -8
@@ 140,7 140,47 @@ class EventActionRow(Adw.ActionRow):
        return p.get_last_child() == self

    def do_snapshot(self, snapshot: Gtk.Snapshot):
        x = -2
        y = -2
        w = 10
        h = self.get_allocated_height()

        rect = Graphene.Rect().init(x, y, w, h)
        cr = snapshot.append_cairo(rect)
        self._draw(cr, rect)
        self.snapshot_child(self.get_first_child(), snapshot)

    def _roundedclippath(self, cr, x, y, w, h, rtop, rbottom):
        cr.arc(x+rtop, y+rtop, rtop, math.pi, 3*math.pi/2)
        cr.line_to(x+w, y)
        cr.line_to(x+w, y+h)
        cr.line_to(x+w, y+h)
        #cr.arc(x+w-rtop, y+rtop, rtop, 3*math.pi/2, 0) # top-right round corner
        #cr.arc(x+w-rbottom, y+h-rbottom, rbottom, 0, math.pi/2) # bottom-right
        cr.arc(x+rbottom, y+h-rbottom, rbottom, math.pi/2, math.pi)
        cr.close_path()
        cr.clip()

    def _draw(self, cr, rect):
        """
        Draw event progress indicator in widget background.
        It's a tick line on left border from top whose lenght is relative to the
        percentage of event time elapsed.

        We need to handle list round corners. Gtk doesn't clip element like HTML
        when rendering with "border-radius" value, so our line will overflow the
        corner.

        I use the clip path method. It get a top rounded corner if `self` is the first
        row in the list, and a bottom rounded corner if it's the last.
        Round radio is defined in code, as I can't find a way to get current widget CSS
        values.
        Then a line of required lenght, color and width is drawn from top.
        Color of the line is widget foreground color with alpha 0.2. Using foreground color
        make the line work on light and dark theme.
        """
        now = datetime.datetime.now(UTC).replace(tzinfo=None)
        #now = datetime.datetime(2023, 2, 5, 10, 50, tzinfo=UTC).replace(tzinfo=None)
        obj = self.obj

        dur = (obj.end.timestamp() - obj.start.timestamp())


@@ 152,17 192,38 @@ class EventActionRow(Adw.ActionRow):
            # set prc to 0 if the event is in the future or 1 if in the past
            prc = int(pos >= 0)

        x = -2
        y = -2
        w = 4
        h = self.get_allocated_height() * prc
        if prc == 0:
            return

        color = self.get_style_context().get_color()
        maxh = rect.get_height()
        x = rect.get_x()
        y = rect.get_y()
        h = maxh * prc
        w = rect.get_width()

        # clip at rounded corners
        rtop = 12 if self._is_first() and self.get_header() is None else 0
        rbottom = 12 if self._is_last() else 0

        # color
        # >= gtk 4.10 : self.get_color()
        color = self.get_style_context.get_color()
        color.alpha = 0.2
        rect = Graphene.Rect().init(x, y, w, h)
        snapshot.append_color(color, rect)

        self.snapshot_child(self.get_first_child(), snapshot)
        cr.save()

        # rounded clip path
        self._roundedclippath(cr, x, y-1, w, maxh+2, rtop, rbottom)

        # draw line
        cr.set_source_rgba(
            color.red, color.green, color.blue, color.alpha
        )
        cr.set_line_width(w)
        cr.move_to(x, y)
        cr.line_to(x, h)
        cr.stroke()
        cr.restore()

    def on_update(self, *args):
        obj = self.obj


@@ 635,3 696,4 @@ class PageHeaderBar(Gtk.Box):