diff --git a/emmental/layout.py b/emmental/layout.py new file mode 100644 index 0000000..8e10f8b --- /dev/null +++ b/emmental/layout.py @@ -0,0 +1,45 @@ +# Copyright 2023 (c) Anna Schumaker. +"""Our adaptable layout that can rearrange widgets as the window is resized.""" +from gi.repository import GObject +from gi.repository import Gtk +from gi.repository import Adw + + +class Layout(Adw.Bin): + """A widget that can rearrange based on window dimensions.""" + + show_sidebar = GObject.Property(type=bool, default=False) + + wide_view = GObject.Property(type=bool, default=False) + + def __init__(self, *, content: Gtk.Widget = None, + sidebar: Gtk.Widget = None): + """Initialize our Layout widget.""" + super().__init__() + self._split_view = Adw.OverlaySplitView(content=content, + sidebar=sidebar, + collapsed=not self.wide_view) + self.props.child = self._split_view + + self.bind_property("show-sidebar", self._split_view, "show-sidebar", + GObject.BindingFlags.BIDIRECTIONAL) + self.bind_property("wide-view", self._split_view, "collapsed", + GObject.BindingFlags.INVERT_BOOLEAN) + + @GObject.Property(type=Gtk.Widget) + def content(self) -> Gtk.Widget: + """Get the content widget for the Layout.""" + return self._split_view.props.content + + @content.setter + def content(self, widget: Gtk.Widget) -> None: + self._split_view.props.content = widget + + @GObject.Property(type=Gtk.Widget) + def sidebar(self) -> Gtk.Widget: + """Get the sidebar widget for the Layout.""" + return self._split_view.props.sidebar + + @sidebar.setter + def sidebar(self, widget: Gtk.Widget) -> None: + self._split_view.props.sidebar = widget diff --git a/tests/test_layout.py b/tests/test_layout.py new file mode 100644 index 0000000..f4789ef --- /dev/null +++ b/tests/test_layout.py @@ -0,0 +1,65 @@ +# Copyright 2023 (c) Anna Schumaker. +"""Tests our adaptable layout widget.""" +import unittest +import emmental.layout +from gi.repository import Gtk +from gi.repository import Adw + + +class TestLayout(unittest.TestCase): + """Test case for our adaptable layout.""" + + def setUp(self): + """Set up common variables.""" + self.layout = emmental.layout.Layout() + + def test_init(self): + """Check that the layout is set up properly.""" + self.assertIsInstance(self.layout, Adw.Bin) + self.assertIsInstance(self.layout._split_view, Adw.OverlaySplitView) + self.assertTrue(self.layout._split_view.props.collapsed) + + def test_wide_view(self): + """Test the layout when we have a wide window.""" + self.assertFalse(self.layout.wide_view) + self.assertEqual(self.layout.props.child, self.layout._split_view) + + self.layout.wide_view = True + self.assertFalse(self.layout._split_view.props.collapsed) + + def test_content(self): + """Test the content widget property.""" + self.assertIsNone(self.layout.content) + + widget = Gtk.Label() + self.layout.content = widget + self.assertEqual(self.layout._split_view.props.content, widget) + self.assertEqual(self.layout.content, widget) + + widget2 = Gtk.Label() + layout2 = emmental.layout.Layout(content=widget2) + self.assertEqual(layout2.content, widget2) + + def test_sidebar(self): + """Test the sidebar widget property.""" + self.assertIsNone(self.layout.sidebar) + + widget = Gtk.Label() + self.layout.sidebar = widget + self.assertEqual(self.layout._split_view.props.sidebar, widget) + self.assertEqual(self.layout.sidebar, widget) + + widget2 = Gtk.Label() + layout2 = emmental.layout.Layout(sidebar=widget2) + self.assertEqual(layout2.sidebar, widget2) + + def test_show_sidebar(self): + """Test the show-sidebar property.""" + self.assertFalse(self.layout.show_sidebar) + self.assertFalse(self.layout._split_view.props.show_sidebar) + + self.layout.show_sidebar = True + self.assertTrue(self.layout._split_view.props.show_sidebar) + + self.layout._split_view.props.show_sidebar = False + self.assertFalse(self.layout.show_sidebar)