From 3c39cc9cda32cf3a529238b7e71d1acded0eec57 Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 15 Jan 2026 21:52:36 -0400 Subject: [PATCH] Improve flow visualization UX - Add navigation help bar at top of flow view with instructions: Pan, Zoom, Select, Edit step shortcuts - Fix zoom to fit all nodes on initial load (was only centering last node) - Use QTimer to ensure fit happens after widget is fully rendered - Clear selection after fitting so nodes don't appear selected Co-Authored-By: Claude Opus 4.5 --- src/cmdforge/gui/widgets/flow_graph.py | 55 ++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/src/cmdforge/gui/widgets/flow_graph.py b/src/cmdforge/gui/widgets/flow_graph.py index 60b2aa0..71e0f55 100644 --- a/src/cmdforge/gui/widgets/flow_graph.py +++ b/src/cmdforge/gui/widgets/flow_graph.py @@ -2,8 +2,8 @@ from typing import Optional, List -from PySide6.QtWidgets import QWidget, QVBoxLayout -from PySide6.QtCore import Signal +from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout +from PySide6.QtCore import Signal, Qt, QTimer from NodeGraphQt import NodeGraph, BaseNode @@ -135,6 +135,39 @@ class FlowGraphWidget(QWidget): """Set up the UI.""" layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(0) + + # Navigation help bar + help_bar = QWidget() + help_bar.setStyleSheet(""" + QWidget { + background-color: #edf2f7; + border-bottom: 1px solid #e2e8f0; + } + QLabel { + color: #718096; + font-size: 11px; + padding: 4px 8px; + } + """) + help_layout = QHBoxLayout(help_bar) + help_layout.setContentsMargins(8, 2, 8, 2) + + help_text = QLabel( + "Pan: Middle-click drag | " + "Zoom: Scroll wheel | " + "Select: Click or drag box | " + "Edit step: Double-click node" + ) + help_layout.addWidget(help_text) + help_layout.addStretch() + + # Fit view button + fit_label = QLabel("Press F to fit all") + fit_label.setStyleSheet("color: #667eea; font-weight: 500;") + help_layout.addWidget(fit_label) + + layout.addWidget(help_bar) # Create node graph self._graph = NodeGraph() @@ -149,7 +182,7 @@ class FlowGraphWidget(QWidget): self._graph.node_double_clicked.connect(self._on_node_double_clicked) # Add graph widget - layout.addWidget(self._graph.widget) + layout.addWidget(self._graph.widget, 1) def set_tool(self, tool: Optional[Tool]): """Set the tool to visualize.""" @@ -223,7 +256,21 @@ class FlowGraphWidget(QWidget): # Auto-layout and fit view self._graph.auto_layout_nodes() - self._graph.fit_to_selection() + + # Select all nodes then fit to selection, then clear selection + all_nodes = self._graph.all_nodes() + for node in all_nodes: + node.set_selected(True) + + # Use a timer to fit after the widget is fully rendered + QTimer.singleShot(50, self._fit_and_clear_selection) + + def _fit_and_clear_selection(self): + """Fit view to all nodes and clear selection.""" + if self._graph: + self._graph.fit_to_selection() + # Clear selection + self._graph.clear_selection() def _on_node_double_clicked(self, node): """Handle node double-click."""