@@ 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):
+