109 lines
3.0 KiB
Python
109 lines
3.0 KiB
Python
"""Shared visual helpers for data grids."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from tkinter import ttk
|
|
from typing import Any
|
|
|
|
TABLE_ROW_EVEN = "#FFFFFF"
|
|
TABLE_ROW_ODD = "#F4F6F8"
|
|
TABLE_HEADER_BG = "#D1D5DB"
|
|
TABLE_HEADER_FG = "#111827"
|
|
TABLE_SELECTED_BG = "#DCEBFF"
|
|
TABLE_SELECTED_FG = "#111827"
|
|
|
|
|
|
def style_treeview(
|
|
tree: ttk.Treeview,
|
|
*,
|
|
style_name: str,
|
|
rowheight: int = 24,
|
|
font: Any = ("Segoe UI", 9),
|
|
heading_font: Any = ("Segoe UI", 9, "bold"),
|
|
) -> ttk.Style:
|
|
"""Apply a consistent high-contrast header and zebra-ready style."""
|
|
|
|
style = ttk.Style(tree)
|
|
style.configure(style_name, rowheight=rowheight, font=font)
|
|
style.configure(
|
|
f"{style_name}.Heading",
|
|
font=heading_font,
|
|
background=TABLE_HEADER_BG,
|
|
foreground=TABLE_HEADER_FG,
|
|
relief="flat",
|
|
)
|
|
style.map(
|
|
f"{style_name}.Heading",
|
|
background=[("active", TABLE_HEADER_BG), ("pressed", TABLE_HEADER_BG)],
|
|
foreground=[("active", TABLE_HEADER_FG), ("pressed", TABLE_HEADER_FG)],
|
|
)
|
|
style.map(
|
|
style_name,
|
|
background=[("selected", TABLE_SELECTED_BG)],
|
|
foreground=[("selected", TABLE_SELECTED_FG)],
|
|
)
|
|
tree.configure(style=style_name)
|
|
configure_treeview_zebra_tags(tree)
|
|
return style
|
|
|
|
|
|
def configure_treeview_zebra_tags(tree: ttk.Treeview) -> None:
|
|
"""Register alternating row color tags on a Treeview."""
|
|
|
|
tree.tag_configure("even", background=TABLE_ROW_EVEN)
|
|
tree.tag_configure("odd", background=TABLE_ROW_ODD)
|
|
|
|
|
|
def zebra_tag(index: int) -> str:
|
|
"""Return the alternating row tag for the given zero-based index."""
|
|
|
|
return "even" if index % 2 == 0 else "odd"
|
|
|
|
|
|
def merge_tags(*tags: str) -> tuple[str, ...]:
|
|
"""Return non-empty tags preserving order."""
|
|
|
|
return tuple(tag for tag in tags if tag)
|
|
|
|
|
|
def apply_tksheet_visual_style(sheet: Any) -> None:
|
|
"""Apply best-effort header contrast and zebra rows to a tksheet widget."""
|
|
|
|
try:
|
|
sheet.set_options(
|
|
header_bg=TABLE_HEADER_BG,
|
|
header_fg=TABLE_HEADER_FG,
|
|
header_selected_cells_bg=TABLE_HEADER_BG,
|
|
header_selected_cells_fg=TABLE_HEADER_FG,
|
|
table_bg=TABLE_ROW_EVEN,
|
|
table_fg="#111827",
|
|
selected_rows_bg=TABLE_SELECTED_BG,
|
|
selected_rows_fg=TABLE_SELECTED_FG,
|
|
selected_cells_bg=TABLE_SELECTED_BG,
|
|
selected_cells_fg=TABLE_SELECTED_FG,
|
|
)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def apply_tksheet_zebra(sheet: Any, row_count: int) -> None:
|
|
"""Apply alternating row colors to a tksheet widget when supported."""
|
|
|
|
try:
|
|
sheet.dehighlight_rows(redraw=False)
|
|
except Exception:
|
|
pass
|
|
for row_index in range(row_count):
|
|
try:
|
|
sheet.highlight_rows(
|
|
rows=[row_index],
|
|
bg=TABLE_ROW_EVEN if row_index % 2 == 0 else TABLE_ROW_ODD,
|
|
redraw=False,
|
|
)
|
|
except Exception:
|
|
break
|
|
try:
|
|
sheet.redraw()
|
|
except Exception:
|
|
pass
|