This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch feature/CAMEL-23672-tui-diagram
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 215a1fca41456d2b5cbba55eba7bcaa016f81f7a
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Jun 4 11:29:41 2026 +0200

    CAMEL-23672: camel-tui - Cache diagram data and split Enter/d in routes tab
    
    Cache diagram data per PID so reopening the diagram is instant without
    IPC reload. Cache is invalidated on integration change. In the routes
    table, Enter opens topology view and d opens route diagram drilled
    into the selected route.
    
    Signed-off-by: Claus Ibsen <[email protected]>
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../jbang/core/commands/tui/DiagramSupport.java    | 33 ++++++++++++++++++
 .../dsl/jbang/core/commands/tui/RoutesTab.java     | 40 ++++++++++++++++++----
 2 files changed, 67 insertions(+), 6 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
index 72c360c6f8be..904266b1568a 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramSupport.java
@@ -86,6 +86,7 @@ class DiagramSupport {
     private TopologyLayoutResult topologyLayout;
     private int topologyNodeWidth;
     private java.util.Map<String, RouteDiagramLayoutEngine.LayoutRoute> 
routeLayouts = Collections.emptyMap();
+    private String cachedPid;
 
     List<String> getLines() {
         return lines;
@@ -265,6 +266,11 @@ class DiagramSupport {
 
     void reset() {
         close();
+        invalidateCache();
+    }
+
+    void invalidateCache() {
+        cachedPid = null;
         lines = Collections.emptyList();
         nodeBoxes = Collections.emptyList();
         topologyNodes = Collections.emptyList();
@@ -279,6 +285,32 @@ class DiagramSupport {
         scrollX = 0;
     }
 
+    boolean hasCachedData(String pid) {
+        return pid != null && pid.equals(cachedPid) && hasDiagramData();
+    }
+
+    void showCached() {
+        showDiagram = true;
+        scrollY = 0;
+        scrollX = 0;
+    }
+
+    void applyPendingSelection() {
+        if (pendingSelectionRouteId != null && !nodeBoxes.isEmpty()) {
+            int newIdx = -1;
+            for (int i = 0; i < nodeBoxes.size(); i++) {
+                if 
(pendingSelectionRouteId.equals(nodeBoxes.get(i).routeId())) {
+                    newIdx = i;
+                    break;
+                }
+            }
+            if (newIdx >= 0) {
+                selectedNodeIndex = newIdx;
+            }
+        }
+        pendingSelectionRouteId = null;
+    }
+
     void renderFooterHints(List<Span> spans) {
         hint(spans, "Esc", "close");
         hint(spans, "↑↓←→", "scroll");
@@ -1162,6 +1194,7 @@ class DiagramSupport {
             if (!showDiagram) {
                 return;
             }
+            cachedPid = pid;
             topologyLayout = finalTopoResult;
             topologyNodeWidth = finalNodeW;
             topologyNodes = finalTopoNodes;
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
index 32720c47722f..86d66f680caf 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
@@ -303,12 +303,18 @@ class RoutesTab implements MonitorTab {
             return true;
         }
 
-        // Diagram toggle
+        // Enter in table mode opens topology
+        if (!diagram.isShowDiagram() && !sourceViewer.isVisible() && 
ke.isConfirm()) {
+            openTopology();
+            return true;
+        }
+
+        // d in table mode opens route diagram, in diagram mode closes it
         if (ke.isCharIgnoreCase('d')) {
             if (diagram.isShowDiagram()) {
                 closeDiagram();
             } else {
-                openDiagram();
+                openRouteDiagram();
             }
             return true;
         }
@@ -653,12 +659,13 @@ class RoutesTab implements MonitorTab {
         } else {
             hint(spans, "Esc", "back");
             hint(spans, "↑↓", "navigate");
+            hint(spans, "Enter", "topology");
+            hint(spans, "d", "diagram");
             hint(spans, "s", "sort");
             hint(spans, "n", "description" + (showDescription ? " [on]" : " 
[off]"));
             hint(spans, "t", routeTopMode ? "top [on]" : "top [off]");
             if (!routeTopMode) {
                 hint(spans, "c", "source");
-                hint(spans, "d", "diagram");
                 String routeState = selectedRouteState();
                 boolean supSus = selectedRouteSupportsSuspension();
                 if ("Started".equals(routeState)) {
@@ -693,11 +700,10 @@ class RoutesTab implements MonitorTab {
 
     // ---- Diagram open/close ----
 
-    private void openDiagram() {
+    private void openTopology() {
         topologyMode = true;
         drillDownRouteId = null;
         routeNavigationStack.clear();
-        diagram.reset();
         diagram.setTopologyMode(true);
 
         // Pre-select the currently highlighted route from the table
@@ -706,7 +712,29 @@ class RoutesTab implements MonitorTab {
             diagram.setPendingSelectionRouteId(selectedId);
         }
 
-        loadDiagram(true);
+        if (diagram.hasCachedData(ctx.selectedPid)) {
+            diagram.showCached();
+            diagram.applyPendingSelection();
+        } else {
+            loadDiagram(true);
+        }
+    }
+
+    private void openRouteDiagram() {
+        String selectedId = selectedRouteId();
+        if (selectedId == null) {
+            return;
+        }
+        topologyMode = false;
+        drillDownRouteId = selectedId;
+        routeNavigationStack.clear();
+        diagram.setTopologyMode(false);
+
+        if (diagram.hasCachedData(ctx.selectedPid)) {
+            diagram.showCached();
+        } else {
+            loadDiagram(true);
+        }
     }
 
     void closeDiagram() {

Reply via email to