diff --git a/qtile_extras/widget/groupbox2.py b/qtile_extras/widget/groupbox2.py index 46c6120b..20c46bff 100644 --- a/qtile_extras/widget/groupbox2.py +++ b/qtile_extras/widget/groupbox2.py @@ -19,6 +19,7 @@ # SOFTWARE. from __future__ import annotations +import math from copy import deepcopy from enum import Flag, auto from typing import TYPE_CHECKING @@ -60,12 +61,24 @@ def filter_attrs(attr): class GroupBoxRule: + attrs = [ + "text_colour", + "block_colour", + "block_border_width", + "block_border_colour", + "block_corner_radius", + "line_width", + "line_colour", + "text", + ] + def __init__( self, text_colour=SENTINEL, block_colour=SENTINEL, block_border_width=SENTINEL, block_border_colour=SENTINEL, + block_corner_radius=SENTINEL, line_width=SENTINEL, line_colour=SENTINEL, text=SENTINEL, @@ -74,6 +87,7 @@ def __init__( self.block_colour = block_colour self.block_border_width = block_border_width self.block_border_colour = block_border_colour + self.block_corner_radius = block_corner_radius self.line_width = line_width self.line_colour = line_colour self.text = text @@ -140,9 +154,7 @@ def clone(self): return deepcopy(self) def __repr__(self): - output = describe_attributes( - self, ["text_colour", "block_colour", "block_border_width", "block_border_colour"] - ) + output = describe_attributes(self, GroupBoxRule.attrs) when = describe_attributes( self, ["screen", "focused", "occupied", "urgent", "group_name", "func"], filter_attrs ) @@ -224,15 +236,7 @@ def _set_formats(self): @property def rule_attrs(self): - return [ - "text_colour", - "block_colour", - "block_border_width", - "block_border_colour", - "line_colour", - "line_width", - "text", - ] + return GroupBoxRule.attrs def _reset_format(self): for attr in self.rule_attrs: @@ -266,16 +270,39 @@ def has_line(self): def draw_block(self): ctx = self.drawer.ctx - ctx.rectangle( - self.margin_x, - self.margin_y, - self.size - 2 * self.margin_x, - self.bar.height - 2 * self.margin_y, - ) + if not self.block_corner_radius: + ctx.rectangle( + self.margin_x, + self.margin_y, + self.size - 2 * self.margin_x, + self.bar.height - 2 * self.margin_y, + ) + else: + radius = self.block_corner_radius + degrees = math.pi / 180.0 + + ctx.new_sub_path() + + delta = radius + 1 + x = self.margin_x + y = self.margin_y + width = self.size - 2 * self.margin_x + height = self.bar.height - 2 * self.margin_y + ctx.arc(x + width - delta, y + delta, radius, -90 * degrees, 0 * degrees) + ctx.arc(x + width - delta, y + height - delta, radius, 0 * degrees, 90 * degrees) + ctx.arc(x + delta, y + height - delta, radius, 90 * degrees, 180 * degrees) + ctx.arc(x + delta, y + delta, radius, 180 * degrees, 270 * degrees) + ctx.close_path() + if self.block_colour: self.drawer.set_source_rgb(self.block_colour) ctx.fill_preserve() + if self.block_border_colour and self.block_border_width: + ctx.set_line_width(self.block_border_width) + self.drawer.set_source_rgb(self.block_border_colour) + ctx.stroke() + ctx.new_path() def draw_text(self): @@ -337,6 +364,8 @@ class GroupBox2(base._Widget, base.MarginMixin, base.PaddingMixin): For example: + .. code:: python + rules = [ GroupBoxRule(block_colour="009999").when(screen=ScreenRule.THIS), GroupBoxRule(block_colour="999999").when(occupied=True), @@ -360,6 +389,8 @@ class GroupBox2(base._Widget, base.MarginMixin, base.PaddingMixin): As an example, to create a rule that is matched when a specific app is open in the group: + .. code:: python + def has_vlc(rule, box): for win in box.group.windows: if "VLC" in win.name: @@ -374,6 +405,8 @@ def has_vlc(rule, box): In addition, a user-defined function can set display properties dynamically. For example, to have a different icon depending on the state of the group: + .. code:: python + def set_label(rule, box): if box.focused: rule.text = "◉" @@ -387,6 +420,7 @@ def set_label(rule, box): # Include this in your group box rules # NB: The function returns True so this rule will always be run GroupBoxRule().when(func=set_label) + """ _experimental = True