feat: Enhance UI feedback and improve data filtering logic
This commit is contained in:
+71
-4
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user