From ccb8dd8d689ae38a13604301305b252d08bfde43 Mon Sep 17 00:00:00 2001
From: Maximilian Moser <maximilian.moser@tuwien.ac.at>
Date: Wed, 28 Feb 2024 17:18:31 +0100
Subject: [PATCH] Cache the size requirements for the listboxes

* this simple implementation works for us because the listbox content
  doesn't change once it's set
* otherwise, the scrollbar causes the listbox to recalculate its size
  requirements on every render, which gets very laggy with many widgets
  in the listbox
---
 formatscaper/resultman.py | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/formatscaper/resultman.py b/formatscaper/resultman.py
index f21affd..38629b9 100755
--- a/formatscaper/resultman.py
+++ b/formatscaper/resultman.py
@@ -64,6 +64,26 @@ class SimpleButton(uw.Button):
     format: Optional[Format] = None
 
 
+class CachingListBox(uw.ListBox):
+    """ListBox with caching for sizes."""
+
+    def __init__(self, body):
+        """Constructor."""
+        super().__init__(body)
+        self._cached_sizes = {}
+
+        self._body._modified
+
+    def rows_max(self, size, focus):
+        """Scrollable protocol for sized iterable and not wrapped around contents."""
+        if size in self._cached_sizes:
+            return self._cached_sizes[size]
+
+        result = super().rows_max(size, focus)
+        self._cached_sizes[size] = result
+        return result
+
+
 # parsing CLI arguments
 parser = argparse.ArgumentParser(
     description="TUI tool for managing file format information"
@@ -168,7 +188,7 @@ def handle_select_format(format: Format, button: uw.Button):
         _files = "file" if num_files == 1 else "files"
         _records = "record" if len(relevant_results) == 1 else "records"
         bottom = uw.ScrollBar(
-            uw.ListBox(
+            CachingListBox(
                 uw.SimpleFocusListWalker(
                     [
                         uw.Divider(),
@@ -236,7 +256,7 @@ def create_format_buttons(filter: FormatFilter):
 
 
 formats_list = uw.ScrollBar(
-    uw.ListBox(uw.SimpleFocusListWalker(create_format_buttons(current_filter)))
+    CachingListBox(uw.SimpleFocusListWalker(create_format_buttons(current_filter)))
 )
 formats_list._command_map["l"] = "activate"
 formats_label = uw.Filler(uw.AttrMap(uw.Text("FORMATS", align="center"), "border"))
-- 
GitLab