2022-08-16 15:57:52 -04:00
|
|
|
# Copyright 2022 (c) Anna Schumaker.
|
|
|
|
"""Helper classes for Buttons."""
|
|
|
|
from gi.repository import GObject
|
|
|
|
from gi.repository import Gtk
|
|
|
|
|
|
|
|
|
2022-09-26 09:32:07 -04:00
|
|
|
class Button(Gtk.Button):
|
|
|
|
"""A Gtk.Button with extra properties and default large size."""
|
|
|
|
|
|
|
|
icon_name = GObject.Property(type=str)
|
|
|
|
icon_opacity = GObject.Property(type=float, default=1.0,
|
|
|
|
minimum=0.0, maximum=1.0)
|
|
|
|
|
2023-06-10 21:25:54 -04:00
|
|
|
def __init__(self, large_icon: bool = False, **kwargs):
|
2022-09-26 09:32:07 -04:00
|
|
|
"""Initialize a Button."""
|
|
|
|
super().__init__(focusable=False, **kwargs)
|
2023-06-10 21:25:54 -04:00
|
|
|
icon_size = Gtk.IconSize.LARGE if large_icon else Gtk.IconSize.NORMAL
|
|
|
|
self._image = Gtk.Image(icon_name=self.icon_name, icon_size=icon_size,
|
2022-09-26 09:32:07 -04:00
|
|
|
opacity=self.icon_opacity)
|
|
|
|
self.bind_property("icon-name", self._image, "icon-name")
|
|
|
|
self.bind_property("icon-opacity", self._image, "opacity")
|
|
|
|
self.set_child(self._image)
|
|
|
|
|
2023-06-10 21:25:54 -04:00
|
|
|
@GObject.Property(type=bool, default=False)
|
|
|
|
def large_icon(self) -> bool:
|
|
|
|
"""Get if this Button has a large icon."""
|
|
|
|
return self._image.get_icon_size() == Gtk.IconSize.LARGE
|
|
|
|
|
|
|
|
@large_icon.setter
|
|
|
|
def large_icon(self, newval: bool) -> None:
|
|
|
|
size = Gtk.IconSize.LARGE if newval else Gtk.IconSize.NORMAL
|
|
|
|
self._image.set_icon_size(size)
|
|
|
|
|
2022-09-26 09:32:07 -04:00
|
|
|
|
2022-08-16 15:57:52 -04:00
|
|
|
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()
|
2022-09-27 10:27:04 -04:00
|
|
|
|
|
|
|
|
|
|
|
class SplitButton(Gtk.Box):
|
|
|
|
"""A Button and secondary widget packed together."""
|
|
|
|
|
|
|
|
icon_name = GObject.Property(type=str)
|
2023-06-10 21:25:54 -04:00
|
|
|
large_icon = GObject.Property(type=bool, default=False)
|
2022-09-27 10:27:04 -04:00
|
|
|
|
|
|
|
def __init__(self, secondary: Gtk.Button, **kwargs):
|
|
|
|
"""Initialize a Split Button."""
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
self._primary = Button(hexpand=True, icon_name=self.icon_name,
|
2023-06-10 21:25:54 -04:00
|
|
|
large_icon=self.large_icon)
|
2022-09-27 10:27:04 -04:00
|
|
|
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")
|
2023-06-10 21:25:54 -04:00
|
|
|
self.bind_property("large-icon", self._primary, "large-icon")
|
2023-06-08 16:12:33 -04:00
|
|
|
self._primary.connect("activate", self.__activate)
|
2022-09-27 10:27:04 -04:00
|
|
|
self._primary.connect("clicked", self.__clicked)
|
|
|
|
|
|
|
|
self.append(self._primary)
|
|
|
|
self.append(self._separator)
|
|
|
|
self.append(secondary)
|
|
|
|
|
|
|
|
self.add_css_class("emmental-splitbutton")
|
|
|
|
|
2023-06-08 16:12:33 -04:00
|
|
|
def __activate(self, button: Button) -> None:
|
|
|
|
self.emit("activate-primary")
|
|
|
|
|
2022-09-27 10:27:04 -04:00
|
|
|
def __clicked(self, button: Button) -> None:
|
|
|
|
self.emit("clicked")
|
|
|
|
|
2023-06-08 16:12:33 -04:00
|
|
|
def activate(self, *args) -> None:
|
2023-06-10 19:28:24 -04:00
|
|
|
"""Activate the primary button."""
|
2023-06-08 16:12:33 -04:00
|
|
|
self._primary.activate()
|
|
|
|
|
2022-09-27 10:27:04 -04:00
|
|
|
@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
|
|
|
|
|
2023-06-08 16:12:33 -04:00
|
|
|
@GObject.Signal
|
|
|
|
def activate_primary(self) -> None:
|
|
|
|
"""Signal that the primary button has been activated."""
|
|
|
|
|
2022-09-27 10:27:04 -04:00
|
|
|
@GObject.Signal
|
|
|
|
def clicked(self) -> None:
|
|
|
|
"""Signal that the primary button has been clicked."""
|
2022-09-26 10:28:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
class ImageToggle(Button):
|
|
|
|
"""Inspired by a ToggleButton, but changes image based on state."""
|
|
|
|
|
|
|
|
active_icon_name = GObject.Property(type=str)
|
2023-06-10 20:25:11 -04:00
|
|
|
active_tooltip_text = GObject.Property(type=str)
|
|
|
|
|
2022-09-26 10:28:34 -04:00
|
|
|
inactive_icon_name = GObject.Property(type=str)
|
2023-06-10 20:25:11 -04:00
|
|
|
inactive_tooltip_text = GObject.Property(type=str)
|
2022-09-26 10:28:34 -04:00
|
|
|
|
|
|
|
def __init__(self, active_icon_name: str, inactive_icon_name: str,
|
2023-06-10 20:25:11 -04:00
|
|
|
active_tooltip_text: str | None = None,
|
|
|
|
inactive_tooltip_text: str | None = None,
|
|
|
|
*, active: bool = False, **kwargs) -> None:
|
2022-09-26 10:28:34 -04:00
|
|
|
"""Initialize an ImageToggle button."""
|
|
|
|
super().__init__(active_icon_name=active_icon_name,
|
|
|
|
inactive_icon_name=inactive_icon_name,
|
2023-06-10 20:25:11 -04:00
|
|
|
icon_name=inactive_icon_name,
|
|
|
|
active_tooltip_text=active_tooltip_text,
|
|
|
|
inactive_tooltip_text=inactive_tooltip_text,
|
|
|
|
tooltip_text=inactive_tooltip_text,
|
|
|
|
active=active, **kwargs)
|
2022-09-26 10:28:34 -04:00
|
|
|
|
|
|
|
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:
|
2023-06-10 20:25:11 -04:00
|
|
|
if newval:
|
|
|
|
self.icon_name = self.active_icon_name
|
|
|
|
self.props.tooltip_text = self.active_tooltip_text
|
|
|
|
else:
|
|
|
|
self.icon_name = self.inactive_icon_name
|
|
|
|
self.props.tooltip_text = self.inactive_tooltip_text
|
2022-09-26 10:28:34 -04:00
|
|
|
self.emit("toggled")
|
|
|
|
|
|
|
|
@GObject.Signal
|
|
|
|
def toggled(self) -> None:
|
|
|
|
"""Active state has been toggled."""
|