buttons: Create an ImageToggle button

This button is inspired by the Gtk.ToggleButton button, except it
changes the displayed icon when active.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2022-09-26 10:28:34 -04:00
parent f85cdb5b49
commit 011dbd114b
2 changed files with 80 additions and 0 deletions

View File

@ -78,3 +78,37 @@ class SplitButton(Gtk.Box):
@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."""

View File

@ -147,3 +147,49 @@ class TestSplitButton(unittest.TestCase):
self.button.connect("clicked", on_click)
self.button._primary.emit("clicked")
on_click.assert_called_with(self.button)
class TestImageToggle(unittest.TestCase):
"""Test an ImageToggle button."""
def setUp(self):
"""Set up common variables."""
self.button = emmental.buttons.ImageToggle("active", "inactive")
def test_init(self):
"""Test that the ImageToggle button is configured correctly."""
self.assertIsInstance(self.button, emmental.buttons.Button)
self.assertEqual(self.button.active_icon_name, "active")
self.assertEqual(self.button.inactive_icon_name, "inactive")
self.assertEqual(self.button.icon_name, "inactive")
self.assertFalse(self.button.active)
def test_active(self):
"""Test the active property."""
self.button.active = True
self.assertTrue(self.button.active)
self.assertEqual(self.button.icon_name, "active")
self.button.active = False
self.assertFalse(self.button.active)
self.assertEqual(self.button.icon_name, "inactive")
button2 = emmental.buttons.ImageToggle("active", "inactive",
active=True)
self.assertTrue(button2.active)
def test_toggle(self):
"""Test the toggle signal."""
toggled = unittest.mock.Mock()
self.button.connect("toggled", toggled)
self.button.active = False
toggled.assert_not_called()
self.button.active = True
toggled.assert_called()
toggled.reset_mock()
self.button.emit("clicked")
self.assertFalse(self.button.active)
toggled.assert_called()