feat: Enhance UI feedback and improve data filtering logic

This commit is contained in:
William Valentin
2025-08-08 11:32:43 -07:00
parent 0252691e89
commit 61c8c72cf7
4 changed files with 137 additions and 42 deletions
+71 -4
View File
@@ -392,10 +392,15 @@ class UIManager:
# Column sort state tracking
self._tree_sort_directions: dict[str, bool] = {}
self._last_sorted_column: str | None = None
self._last_sorted_ascending: bool | None = None
def make_sort_callback(col_name: str):
def _callback():
self.sort_tree_column(tree, col_name)
# Remember last sort state
self._last_sorted_column = col_name
self._last_sorted_ascending = self._tree_sort_directions.get(col_name)
return _callback
@@ -407,10 +412,12 @@ class UIManager:
tree.pack(side="left", fill="both", expand=True)
# Add scrollbar with optimized scroll handling
scrollbar = ttk.Scrollbar(table_frame, orient="vertical", command=tree.yview)
tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side="right", fill="y")
# Add scrollbars with optimized scroll handling
vscroll = ttk.Scrollbar(table_frame, orient="vertical", command=tree.yview)
hscroll = ttk.Scrollbar(table_frame, orient="horizontal", command=tree.xview)
tree.configure(yscrollcommand=vscroll.set, xscrollcommand=hscroll.set)
vscroll.pack(side="right", fill="y")
hscroll.pack(side="bottom", fill="x")
# Optimize tree scrolling performance
self._optimize_tree_scrolling(tree)
@@ -452,6 +459,50 @@ class UIManager:
# Update heading arrow (basic glyph)
direction_glyph = "" if ascending else ""
tree.heading(column, text=f"{column} {direction_glyph}")
# Re-apply alternating row tags after sort
self.normalize_tree_stripes(tree)
def _sort_tree_column_direction(
self, tree: ttk.Treeview, column: str, ascending: bool
) -> None:
"""Sort a treeview column in a specific direction without toggling state."""
data = []
for item in tree.get_children(""):
values = tree.item(item, "values")
try:
col_index = tree["columns"].index(column)
except ValueError:
continue
data.append((values[col_index], item, values))
def try_cast(v: Any):
for caster in (int, float):
try:
return caster(v)
except Exception:
continue
return str(v)
data.sort(key=lambda tup: try_cast(tup[0]), reverse=not ascending)
for index, (_value, item, _vals) in enumerate(data):
tree.move(item, "", index)
direction_glyph = "" if ascending else ""
tree.heading(column, text=f"{column} {direction_glyph}")
# Re-apply alternating row tags after sort
self.normalize_tree_stripes(tree)
def reapply_last_sort(self, tree: ttk.Treeview) -> None:
"""Reapply the last known sort to the tree after data refresh."""
if not self._last_sorted_column or self._last_sorted_ascending is None:
return
import contextlib
with contextlib.suppress(Exception):
self._sort_tree_column_direction(
tree, self._last_sorted_column, bool(self._last_sorted_ascending)
)
def diff_update_tree(self, tree: ttk.Treeview, df: pd.DataFrame) -> None:
"""Apply minimal changes to treeview vs full rebuild.
@@ -518,6 +569,22 @@ class UIManager:
tag = "evenrow" if idx % 2 == 0 else "oddrow"
tree.insert("", "end", values=list(row), tags=(tag,))
# Ensure alternating stripes are normalized after updates
self.normalize_tree_stripes(tree)
def normalize_tree_stripes(self, tree: ttk.Treeview) -> None:
"""Normalize alternating row tags based on current visual order.
Keeps even/odd striping consistent after inserts, deletes, and sorts.
"""
try:
for idx, item in enumerate(tree.get_children("")):
tag = "evenrow" if idx % 2 == 0 else "oddrow"
tree.item(item, tags=(tag,))
except Exception:
# Best-effort visual enhancement; ignore errors
pass
def create_graph_frame(self, parent_frame: ttk.Frame) -> ttk.LabelFrame:
"""Create and configure the graph frame."""
graph_frame: ttk.LabelFrame = ttk.LabelFrame(