"""Standalone SaraTag Book-tag panel. Split out from Preview.py (Bugs/Minor: "SaraTag only shows in preview pane") so it can be shown/hidden and positioned independently — see AppConfig.ShowTags / TagsPosition / TagsLayout.""" from pathlib import Path from typing import Optional import flet as ft from Books import ReadBookForFile from Core import AppConfig, Palette # Fixedsys Excelsior is fixed-width, so a per-character estimate is accurate # enough to size chips without a real text-measurement API. EstimatedCharWidth = 7.5 ChipPadding = 32 def _EstimateChipWidth(Label: str, Config: AppConfig) -> Optional[float]: if not Config.TagMinWidth and not Config.TagMaxWidth: return None # let the chip hug its content, no constraint requested Natural = len(Label) * EstimatedCharWidth + ChipPadding Lower = Config.TagMinWidth or 0 Upper = Config.TagMaxWidth or Natural return max(Lower, min(Natural, Upper)) def _MakeChip(Key: str, Value, Config: AppConfig) -> ft.Chip: Label = f"{Key}: {Value}" return ft.Chip( label=Label, label_text_style=ft.TextStyle(color=Palette.Text, size=12), bgcolor=Palette.Surface0, shadow_color=Palette.Surface0, elevation=0, elevation_on_click=0, show_checkmark=False, width=_EstimateChipWidth(Label, Config), ) class TagPanel(ft.Container): def __init__(self, Config: AppConfig): self.Config = Config self.Body = ft.Column(spacing=0) self.Body.controls = self._BuildContent(None) BorderSide = ft.BorderSide(1, Palette.Surface1) super().__init__( content=self.Body, padding=8, bgcolor=Palette.Mantle, border=ft.Border(top=BorderSide, right=BorderSide, bottom=BorderSide, left=BorderSide), ) def ShowPath(self, EntryPath: Optional[Path]) -> None: self.Body.controls = self._BuildContent(EntryPath) self.update() def _BuildContent(self, EntryPath: Optional[Path]) -> list[ft.Control]: if EntryPath is None or EntryPath.is_dir(): return [ft.Text("No tags.", color=Palette.Overlay0, size=12)] Book = ReadBookForFile(EntryPath, self.Config) if not Book or not Book["Tags"]: return [ft.Text("No tags.", color=Palette.Overlay0, size=12)] Chips = [_MakeChip(Key, Value, self.Config) for Key, Value in Book["Tags"].items()] if self.Config.TagsLayout == "vertical": return [ft.Column(Chips, spacing=4, horizontal_alignment=ft.CrossAxisAlignment.START)] return [ft.Row(Chips, wrap=True, spacing=4, run_spacing=4)]