# Copyright 2022 (c) Anna Schumaker. """Helper classes for Buttons.""" from gi.repository import GObject from gi.repository import Gtk class Button(Gtk.Button): """A Gtk.Button with extra properties and default large size.""" icon_name = GObject.Property(type=str) icon_size = GObject.Property(type=Gtk.IconSize, default=Gtk.IconSize.NORMAL) icon_opacity = GObject.Property(type=float, default=1.0, minimum=0.0, maximum=1.0) def __init__(self, **kwargs): """Initialize a Button.""" super().__init__(focusable=False, **kwargs) self._image = Gtk.Image(icon_name=self.icon_name, icon_size=self.icon_size, opacity=self.icon_opacity) self.bind_property("icon-name", self._image, "icon-name") self.bind_property("icon-size", self._image, "icon-size") self.bind_property("icon-opacity", self._image, "opacity") self.set_child(self._image) class PopoverButton(Gtk.MenuButton): """A MenuButton with a Gtk.Popover attached.""" popover_child = GObject.Property(type=Gtk.Widget) def __init__(self, **kwargs): """Initialize a popover.Button.""" super().__init__(popover=Gtk.Popover(), **kwargs) self.bind_property("popover-child", self.get_popover(), "child") self.get_popover().set_child(self.popover_child) def popdown(self): """Close the popover.""" self.get_popover().popdown() class SplitButton(Gtk.Box): """A Button and secondary widget packed together.""" icon_name = GObject.Property(type=str) icon_size = GObject.Property(type=Gtk.IconSize, default=Gtk.IconSize.NORMAL) def __init__(self, secondary: Gtk.Button, **kwargs): """Initialize a Split Button.""" super().__init__(**kwargs) self._primary = Button(hexpand=True, icon_name=self.icon_name, icon_size=self.icon_size) self._separator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL, margin_top=12, margin_bottom=12) self._secondary = secondary self.bind_property("icon-name", self._primary, "icon-name") self.bind_property("icon-size", self._primary, "icon-size") self._primary.connect("clicked", self.__clicked) self.append(self._primary) self.append(self._separator) self.append(secondary) self.add_css_class("emmental-splitbutton") def __clicked(self, button: Button) -> None: self.emit("clicked") @GObject.Property(type=Gtk.Button, flags=GObject.ParamFlags.READABLE) def secondary(self) -> Gtk.Button: """Get the secondary button attached to the SplitButton.""" return self._secondary @GObject.Signal def clicked(self) -> None: """Signal that the primary button has been clicked.""" class ImageToggle(Button): """Inspired by a ToggleButton, but changes image based on state.""" active_icon_name = GObject.Property(type=str) inactive_icon_name = GObject.Property(type=str) def __init__(self, active_icon_name: str, inactive_icon_name: str, active: bool = False, **kwargs) -> None: """Initialize an ImageToggle button.""" super().__init__(active_icon_name=active_icon_name, inactive_icon_name=inactive_icon_name, icon_name=inactive_icon_name, active=active, **kwargs) def do_clicked(self) -> None: """Handle a click event.""" self.active = not self.active @GObject.Property(type=bool, default=False) def active(self) -> bool: """Get the active state.""" return self.icon_name == self.active_icon_name @active.setter def active(self, newval: bool) -> None: if newval != self.active: icon = self.active_icon_name if newval else self.inactive_icon_name self.icon_name = icon self.emit("toggled") @GObject.Signal def toggled(self) -> None: """Active state has been toggled."""