home · contact · privacy
Browser: Minor refactoring.
authorChristian Heller <c.heller@plomlompom.de>
Mon, 28 Oct 2024 12:34:45 +0000 (13:34 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Mon, 28 Oct 2024 12:34:45 +0000 (13:34 +0100)
browser.py

index 6de27286f4a74bbab693a910b3770fa4f50ec47e..bc2167fb8a849f398aa551a2d4fe0b40580ad57c 100755 (executable)
@@ -344,16 +344,15 @@ class GalleryConfig():
 class GallerySlot(Gtk.Button):
     """Slot in Gallery representing a GalleryItem."""
 
-    def __init__(self, item, on_click_file=None):
+    def __init__(self, item, slots_geometry, on_click_file=None):
         super().__init__()
+        self._geometry = slots_geometry
         self.add_css_class('slot')
         self.set_hexpand(True)
         self.item = item
         self.item.slot = self
         if on_click_file:
             self.connect('clicked', on_click_file)
-        self._slot_size = None
-        self._side_margin = None
 
     def mark(self, css_class, do_add=True):
         """Add or remove css_class from self."""
@@ -362,18 +361,18 @@ class GallerySlot(Gtk.Button):
         else:
             self.remove_css_class(css_class)
 
-    def ensure_slot_size(self, slot_size, margin):
+    def ensure_slot_size(self):
         """Call ._size_widget to size .props.child; if none, make empty one."""
-        self._slot_size = slot_size
-        self._side_margin = margin // 2
         if self.get_child() is None:
             self.set_child(Gtk.Label(label='+'))
         self._size_widget()
 
     def _size_widget(self):
         for s in ('bottom', 'top', 'start', 'end'):
-            setattr(self.get_child().props, f'margin_{s}', self._side_margin)
-        self.get_child().set_size_request(self._slot_size, self._slot_size)
+            setattr(self.get_child().props, f'margin_{s}',
+                    self._geometry.side_margin)
+        self.get_child().set_size_request(self._geometry.size_sans_margins,
+                                          self._geometry.size_sans_margins)
 
     def update_widget(self, is_in_vp):
         """(Un-)load slot, for Imgs if (not) is_in_vp, update CSS class."""
@@ -400,6 +399,21 @@ class GallerySlot(Gtk.Button):
             self.mark('bookmarked', self.item.bookmarked)
 
 
+class GallerySlotsGeometry:
+    """Collect variable sizes shared among all GallerySlots."""
+
+    def __init__(self):
+        self._margin = GALLERY_SLOT_MARGIN
+        assert 0 == self._margin % 2  # avoid ._margin != 2 * .side_margin
+        self.side_margin = self._margin // 2
+        self.size, self.size_sans_margins = -1, -1
+
+    def set_size(self, size):
+        """Not only set .size but also update .size_sans_margins."""
+        self.size = size
+        self.size_sans_margins = self.size - self._margin
+
+
 class GalleryItem(GObject.GObject):
     """Gallery representation of filesystem entry, base to DirItem, ImgItem."""
     slot: GallerySlot
@@ -476,10 +490,10 @@ class ImgItem(GalleryItem):
 class VerticalLabel(Gtk.DrawingArea):
     """Label of vertical text (rotated -90°)."""
 
-    def __init__(self, text, max_height_ref):
+    def __init__(self, text, slots_geometry):
         super().__init__()
         self._text = text
-        self._max_height_ref = max_height_ref
+        self._slots_geometry = slots_geometry
         test_layout = self.create_pango_layout()
         test_layout.set_markup(text)
         _, self._text_height = test_layout.get_pixel_size()
@@ -489,7 +503,7 @@ class VerticalLabel(Gtk.DrawingArea):
         """Create layout, rotate by 90°, size widget to measurements."""
         layout = self.create_pango_layout()
         layout.set_markup(self._text)
-        layout.set_width(self._max_height_ref[0] * Pango.SCALE)
+        layout.set_width(self._slots_geometry.size * Pango.SCALE)
         layout.set_ellipsize(Pango.EllipsizeMode.MIDDLE)
         text_width, _ = layout.get_pixel_size()
         cairo_ctx.translate(0, text_width + (height - text_width))
@@ -526,7 +540,7 @@ class Gallery:
         self._recurse_dirs = False
         self._by_1st = False
         self._per_row = GALLERY_PER_ROW_DEFAULT
-        self._slot_margin = GALLERY_SLOT_MARGIN
+        self._slots_geometry = GallerySlotsGeometry()
 
         self.dir_entries = []
         self.items_attrs = {}
@@ -538,7 +552,6 @@ class Gallery:
         scroller = Gtk.ScrolledWindow(propagate_natural_height=True)
         self._col_headers_frame = Gtk.Fixed()
         self._col_headers_grid = None
-        self._slot_size_ref = [0]
         self.frame = Gtk.Box(orientation=OR_V)
         self.frame.append(self._col_headers_frame)
         self.frame.append(scroller)
@@ -810,7 +823,7 @@ class Gallery:
                 if 1 == len(remaining):
                     for i, attr in enumerate(ancestors):
                         vlabel = VerticalLabel(f'<b>{attr[0]}</b>: {attr[1]}',
-                                               self._slot_size_ref)
+                                               self._slots_geometry)
                         self._grid.attach(vlabel, i, i_row_ref[0], 1, 1)
                     row = [None] * len(attr_values)
                     for item in items_of_parent:
@@ -821,10 +834,10 @@ class Gallery:
                         row[idx_val_in_attr_values] = item
                     for i_col, item in enumerate(row):
                         if item:
-                            slot = GallerySlot(item,
-                                               item_clicker(i_slot_ref[0]))
+                            slot = GallerySlot(item, self._slots_geometry)
                         else:
-                            slot = GallerySlot(GalleryItem('', ''))  # dummy
+                            slot = GallerySlot(GalleryItem('', ''),  # dummy
+                                               self._slots_geometry)
                         self.slots += [slot]
                         i_slot_ref[0] += 1
                         self._grid.attach(slot, i_col + len(ancestors),
@@ -876,7 +889,8 @@ class Gallery:
                     if self._per_row == i_col:
                         i_col = 0
                         i_row += 1
-                    slot = GallerySlot(item, item_clicker(i))
+                    slot = GallerySlot(item, self._slots_geometry,
+                                       item_clicker(i))
                     self._grid.attach(slot, i_col, i_row, 1, 1)
                     self.slots += [slot]
                     i_col += 1
@@ -953,7 +967,7 @@ class Gallery:
                 i_vlabels += 1
         max_slot_width = (vp_width - side_offset) // self._per_row
         slot_size = min(vp_height, max_slot_width)
-        self._slot_size_ref[0] = slot_size
+        self._slots_geometry.set_size(slot_size)
         if self._by_1st:
             i_widgets = 0
             while True:
@@ -961,14 +975,14 @@ class Gallery:
                 if 0 == i_widgets:
                     widget.set_size_request(side_offset, -1)
                 elif isinstance(widget, Gtk.Label):
-                    widget.set_size_request(slot_size, -1)
+                    widget.set_size_request(self._slots_geometry.size, -1)
                 else:
                     break
                 i_widgets += 1
-        slot_size_sans_margin = slot_size - self._slot_margin
         for idx, slot in enumerate(self.slots):
-            slot.ensure_slot_size(slot_size_sans_margin, self._slot_margin)
-        vp_scroll.set_upper(slot_size * ceil(len(self.slots) / self._per_row))
+            slot.ensure_slot_size()
+        vp_scroll.set_upper(self._slots_geometry.size * ceil(len(self.slots)
+                                                             / self._per_row))
         if self._scroll_to_focus(vp_scroll, vp_top, vp_bottom):
             return
         for idx, slot in enumerate(self.slots):
@@ -979,9 +993,8 @@ class Gallery:
 
     def _position_to_viewport(
             self, idx, vp_top, vp_bottom, in_vp_greedy=False):
-        slot_size = self._slot_size_ref[0]
-        slot_top = (idx // self._per_row) * slot_size
-        slot_bottom = slot_top + slot_size
+        slot_top = (idx // self._per_row) * self._slots_geometry.size
+        slot_bottom = slot_top + self._slots_geometry.size
         if in_vp_greedy:
             in_vp = (slot_bottom >= vp_top and slot_top <= vp_bottom)
         else:
@@ -989,18 +1002,18 @@ class Gallery:
         return in_vp, slot_top, slot_bottom
 
     def _scroll_to_focus(self, vp_scroll, vp_top, vp_bottom):
-        slot_size = self._slot_size_ref[0]
         scroll_to_focus = self._shall_scroll_to_focus
         self._shall_redraw, self._shall_scroll_to_focus = False, False
         if scroll_to_focus:
             in_vp, slot_top, slot_bottom = self._position_to_viewport(
-                    self.selected_idx, slot_size, vp_top, vp_bottom)
+                    self.selected_idx, vp_top, vp_bottom)
             if not in_vp:
                 self._shall_redraw, self._shall_scroll_to_focus = True, True
                 if slot_top < vp_top:
                     vp_scroll.set_value(slot_top)
                 else:
-                    vp_scroll.set_value(slot_bottom - slot_size)
+                    vp_scroll.set_value(slot_bottom
+                                        - self._slots_geometry.size)
                 return True
         return False