""" Dialog for creating / editing server groups. """ import customtkinter as ctk from typing import Optional from core.i18n import t GROUP_COLORS = [ "#ef4444", # red "#f97316", # orange "#f59e0b", # amber "#22c55e", # green "#3b82f6", # blue "#6366f1", # indigo "#a855f7", # purple "#ec4899", # pink ] class GroupDialog(ctk.CTkToplevel): """Small dialog: group name + color picker (8 circles).""" def __init__(self, master, store, group: Optional[dict] = None): super().__init__(master) self.store = store self._group = group # None = add, dict = edit self.result: Optional[dict] = None self.title(t("edit_group") if group else t("add_group")) self.geometry("340x200") self.resizable(False, False) self.transient(master) self.focus_force() self.protocol("WM_DELETE_WINDOW", self._on_close) self._master_ref = master self._map_bind_id = master.bind("", self._on_parent_map, add="+") # ── Name ── ctk.CTkLabel(self, text=t("group_name"), anchor="w").pack( fill="x", padx=20, pady=(15, 2)) self._name_var = ctk.StringVar(value=group["name"] if group else "") self._name_entry = ctk.CTkEntry(self, textvariable=self._name_var) self._name_entry.pack(fill="x", padx=20) self._name_entry.focus() # ── Color picker ── ctk.CTkLabel(self, text=t("group_color"), anchor="w").pack( fill="x", padx=20, pady=(10, 2)) color_frame = ctk.CTkFrame(self, fg_color="transparent") color_frame.pack(fill="x", padx=20) self._selected_color = group["color"] if group else GROUP_COLORS[0] self._color_buttons: list[ctk.CTkButton] = [] for color in GROUP_COLORS: btn = ctk.CTkButton( color_frame, text="", width=28, height=28, fg_color=color, hover_color=color, border_width=3, border_color=color, corner_radius=14, command=lambda c=color: self._pick_color(c), ) btn.pack(side="left", padx=2) self._color_buttons.append(btn) self._highlight_selected_color() # ── Buttons ── btn_frame = ctk.CTkFrame(self, fg_color="transparent") btn_frame.pack(fill="x", padx=20, pady=(15, 10)) ctk.CTkButton(btn_frame, text=t("cancel"), width=80, fg_color="gray", command=self._on_close).pack(side="left") ctk.CTkButton(btn_frame, text=t("save"), width=80, command=self._save).pack(side="right") # Enter to save self.bind("", lambda e: self._save()) def _pick_color(self, color: str): self._selected_color = color self._highlight_selected_color() def _highlight_selected_color(self): for btn in self._color_buttons: fg = btn.cget("fg_color") if fg == self._selected_color: btn.configure(border_color="white") else: btn.configure(border_color=fg) def _on_parent_map(self, event=None): try: if not self.winfo_exists(): return self.deiconify() self.lift() self.focus_force() except Exception: pass def _on_close(self): try: self._master_ref.unbind("", self._map_bind_id) except Exception: pass self.destroy() def _save(self): name = self._name_var.get().strip() if not name: self._name_entry.focus() return if self._group: # Edit mode self.store.update_group( self._group["id"], name=name, color=self._selected_color) self.result = {"id": self._group["id"], "name": name, "color": self._selected_color} else: # Add mode group = self.store.add_group(name, self._selected_color) self.result = group self._on_close()