Open (or close) the interactive graph panel.
(base: tk.Tk, _html_path: str, live: bool = False)
| 260 | |
| 261 | |
| 262 | def gimmick_initialize(base: tk.Tk, _html_path: str, live: bool = False) -> None: |
| 263 | """Open (or close) the interactive graph panel.""" |
| 264 | global _container, _figure, _ax, _canvas_widget, _info_var, _filter_var, _node_filter_var, _live_mode, _base, _panel_G, _panel_pos |
| 265 | |
| 266 | if _container is not None and _container.winfo_exists(): |
| 267 | _close() |
| 268 | return |
| 269 | |
| 270 | try: |
| 271 | import networkx as nx |
| 272 | import matplotlib |
| 273 | matplotlib.use("TkAgg") |
| 274 | import matplotlib.pyplot as plt |
| 275 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk |
| 276 | except ImportError as exc: |
| 277 | log.warning("Interactive graph unavailable — missing dependency: %s", exc) |
| 278 | import webbrowser |
| 279 | webbrowser.open(_html_path) |
| 280 | return |
| 281 | |
| 282 | _base = base |
| 283 | _live_mode = live |
| 284 | |
| 285 | G, pos, node_colors, edge_colors = _build_graph_data(live=live) |
| 286 | if G is None and not live: |
| 287 | log.info("Interactive graph: no sessions in memory, nothing to show") |
| 288 | return |
| 289 | _panel_G = G |
| 290 | _panel_pos = pos |
| 291 | |
| 292 | # ── Figure ──────────────────────────────────────────────────────────────── |
| 293 | fig, ax = plt.subplots(figsize=(9, 7)) |
| 294 | fig.patch.set_facecolor("#1e1e2e") |
| 295 | ax.set_facecolor("#1e1e2e") |
| 296 | |
| 297 | if G is not None: |
| 298 | _draw_on_axes(ax, G, pos, node_colors, edge_colors) |
| 299 | else: |
| 300 | ax.text(0.5, 0.5, "Waiting for traffic…", ha="center", va="center", |
| 301 | color="white", fontsize=14, transform=ax.transAxes) |
| 302 | ax.axis("off") |
| 303 | fig.subplots_adjust(left=0.02, right=0.98, top=0.98, bottom=0.02) |
| 304 | |
| 305 | # ── Embed ───────────────────────────────────────────────────────────────── |
| 306 | base.resizable(True, True) |
| 307 | base.columnconfigure(11, weight=1) |
| 308 | base.geometry(f"{base.winfo_width() + 700}x{max(base.winfo_height(), 600)}") |
| 309 | |
| 310 | _container = tk.Frame(base, bg="#1e1e2e") |
| 311 | _container.grid(row=10, column=11, rowspan=41, sticky="nsew", |
| 312 | padx=(8, 8), pady=(8, 8)) |
| 313 | _container.rowconfigure(1, weight=1) |
| 314 | _container.columnconfigure(0, weight=1) |
| 315 | |
| 316 | toolbar_row = tk.Frame(_container, bg="#2e2e3e") |
| 317 | toolbar_row.grid(row=0, column=0, sticky="ew") |
| 318 | |
| 319 | cw = FigureCanvasTkAgg(fig, master=_container) |
no test coverage detected