You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/05/13 21:03:39 UTC
(camel) 01/07: CAMEL-23512: Fix TamboUI API misuse in camel-jbang-plugin-tui
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch CAMEL-23512-fix-tui-tamboui-api
in repository https://gitbox.apache.org/repos/asf/camel.git
commit b5c3d1c166623836094c9143b54b11ecfe0176d0
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed May 13 21:58:36 2026 +0200
CAMEL-23512: Fix TamboUI API misuse in camel-jbang-plugin-tui
- Replace deprecated KeyEvent.character() with ke.string() for proper Unicode support
- Use CharWidth for display width calculations instead of String.length()
- Fix TuiHelper.truncate() to use CharWidth.truncateWithEllipsis()
- Fix CamelCatalogTui.wrapText() and flowFields() to use CharWidth
- Fix CamelMonitor diagram width calculation to use CharWidth
- Enable mouse capture in CamelMonitor for diagram scrolling
- Move TableState for processors and route header to class fields
Co-Authored-By: Claude Opus 4.6 (1M context) <no...@anthropic.com>
---
.../jbang/core/commands/tui/CamelCatalogTui.java | 31 +++++++++++++---------
.../dsl/jbang/core/commands/tui/CamelMonitor.java | 12 ++++++---
.../dsl/jbang/core/commands/tui/TuiHelper.java | 5 +++-
3 files changed, 30 insertions(+), 18 deletions(-)
diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java
index cbd2e3022b0c..6b2ffc12e9b3 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java
@@ -28,6 +28,7 @@ import dev.tamboui.style.Color;
import dev.tamboui.style.Overflow;
import dev.tamboui.style.Style;
import dev.tamboui.terminal.Frame;
+import dev.tamboui.text.CharWidth;
import dev.tamboui.text.Line;
import dev.tamboui.text.Span;
import dev.tamboui.text.Text;
@@ -374,10 +375,10 @@ public class CamelCatalogTui extends CamelCommand {
// Typing filters the active panel
if (ke.code() == KeyCode.CHAR) {
if (focus == FOCUS_LIST) {
- componentFilter.append(ke.character());
+ componentFilter.append(ke.string());
applyComponentFilter();
} else {
- optionFilter.append(ke.character());
+ optionFilter.append(ke.string());
applyOptionFilter();
}
return true;
@@ -677,10 +678,10 @@ public class CamelCatalogTui extends CamelCommand {
for (String[] field : fields) {
String label = field[0] + ": ";
String value = field[1];
- int fieldLen = label.length() + value.length();
+ int fieldLen = CharWidth.of(label) + CharWidth.of(value);
// If adding this field would exceed width, flush current line
- if (!currentSpans.isEmpty() && currentLen + gap.length() + fieldLen > maxWidth) {
+ if (!currentSpans.isEmpty() && currentLen + CharWidth.of(gap) + fieldLen > maxWidth) {
lines.add(Line.from(currentSpans));
currentSpans = new ArrayList<>();
currentLen = 1;
@@ -688,7 +689,7 @@ public class CamelCatalogTui extends CamelCommand {
if (!currentSpans.isEmpty()) {
currentSpans.add(Span.raw(gap));
- currentLen += gap.length();
+ currentLen += CharWidth.of(gap);
} else {
currentSpans.add(Span.raw(" "));
}
@@ -723,15 +724,19 @@ public class CamelCatalogTui extends CamelCommand {
}
int pos = 0;
while (pos < text.length()) {
- int end = Math.min(pos + width, text.length());
- if (end < text.length() && end > pos) {
- int lastSpace = text.lastIndexOf(' ', end);
- if (lastSpace > pos) {
- end = lastSpace + 1;
- }
+ String remaining = text.substring(pos);
+ int remainingWidth = CharWidth.of(remaining);
+ if (remainingWidth <= width) {
+ lines.add(Line.from(Span.styled(" " + remaining.trim(), style)));
+ break;
+ }
+ String chunk = CharWidth.substringByWidth(remaining, width);
+ int lastSpace = chunk.lastIndexOf(' ');
+ if (lastSpace > 0) {
+ chunk = chunk.substring(0, lastSpace + 1);
}
- lines.add(Line.from(Span.styled(" " + text.substring(pos, end).trim(), style)));
- pos = end;
+ lines.add(Line.from(Span.styled(" " + chunk.trim(), style)));
+ pos += chunk.length();
}
}
diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
index 8b3f9e9a3fc4..ea17f985877c 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
@@ -49,9 +49,11 @@ import dev.tamboui.style.Color;
import dev.tamboui.style.Overflow;
import dev.tamboui.style.Style;
import dev.tamboui.terminal.Frame;
+import dev.tamboui.text.CharWidth;
import dev.tamboui.text.Line;
import dev.tamboui.text.Span;
import dev.tamboui.text.Text;
+import dev.tamboui.tui.TuiConfig;
import dev.tamboui.tui.TuiRunner;
import dev.tamboui.tui.event.Event;
import dev.tamboui.tui.event.KeyCode;
@@ -131,6 +133,8 @@ public class CamelMonitor extends CamelCommand {
private final TableState routeTableState = new TableState();
private final TableState healthTableState = new TableState();
private final TableState endpointTableState = new TableState();
+ private final TableState processorTableState = new TableState();
+ private final TableState routeHeaderTableState = new TableState();
private final TabsState tabsState = new TabsState(TAB_OVERVIEW);
// Sparkline: throughput history per PID (one point per second)
@@ -206,7 +210,7 @@ public class CamelMonitor extends CamelCommand {
// Initial data load
refreshData();
- try (var tui = TuiRunner.create()) {
+ try (var tui = TuiRunner.create(TuiConfig.builder().mouseCapture(true).build())) {
// Intercept Ctrl+C: quit the TUI cleanly instead of letting
// the JVM tear down the classloader while we're still running
Signal.handle(new Signal("INT"), sig -> tui.quit());
@@ -936,7 +940,7 @@ public class CamelMonitor extends CamelCommand {
.title(" Processors [" + route.routeId + "] ").build())
.build();
- frame.renderStatefulWidget(table, area, new TableState());
+ frame.renderStatefulWidget(table, area, processorTableState);
}
private void renderRouteHeader(Frame frame, Rect area, IntegrationInfo info) {
@@ -994,7 +998,7 @@ public class CamelMonitor extends CamelCommand {
.title(" Route [" + info.name + "] ").build())
.build();
- frame.renderStatefulWidget(table, area, new TableState());
+ frame.renderStatefulWidget(table, area, routeHeaderTableState);
}
private void renderDiagram(Frame frame, Rect area) {
@@ -1011,7 +1015,7 @@ public class CamelMonitor extends CamelCommand {
// Compute max width for horizontal scrolling
int maxWidth = 0;
for (String line : diagramLines) {
- maxWidth = Math.max(maxWidth, line.length());
+ maxWidth = Math.max(maxWidth, CharWidth.of(line));
}
Rect inner = block.inner(area);
diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java
index 87b7cc74d9e3..0183a53b139e 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
+import dev.tamboui.text.CharWidth;
import org.apache.camel.dsl.jbang.core.common.ProcessHelper;
import org.apache.camel.support.PatternHelper;
import org.apache.camel.util.FileUtil;
@@ -109,7 +110,9 @@ final class TuiHelper {
if (s == null) {
return "";
}
- return s.length() > max ? s.substring(0, max - 1) + "\u2026" : s;
+ return CharWidth.of(s) > max
+ ? CharWidth.truncateWithEllipsis(s, max, CharWidth.TruncatePosition.END)
+ : s;
}
/**