Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected static Row emptyRow(String message, int columnCount) {
// ---- Sort helpers ----

protected static String sortLabel(String label, String column, String currentSort, boolean reversed) {
return currentSort.equals(column) ? label + (reversed ? "▲" : "▼") : label;
return currentSort.equals(column) ? label + (reversed ? TuiIcons.SORT_UP : TuiIcons.SORT_DOWN) : label;
}

protected static Style sortStyle(String column, String currentSort) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -757,13 +757,13 @@ void renderFooter(List<Span> spans) {
}
if (gotoTabPopup.isVisible()) {
hint(spans, "type", "filter");
hint(spans, "↑↓", "navigate");
hint(spans, TuiIcons.HINT_SCROLL, "navigate");
hint(spans, "Enter", "go to");
hintLast(spans, "Esc", "back");
return;
}
if (showActionsMenu) {
hint(spans, "↑↓", "navigate");
hint(spans, TuiIcons.HINT_SCROLL, "navigate");
hint(spans, "Enter", "select");
hintLast(spans, "Esc", "cancel");
}
Expand All @@ -789,52 +789,54 @@ private void renderActionsMenu(Frame frame, Rect area) {
// CAMEL-23818: use plain 2-wide emoji here. TamboUI mismeasures base-glyph + VS16
// sequences as 1-wide (fixed upstream in tamboui/tamboui#388), which left stray chars.
String keystrokeLabel = keystrokesEnabled.get()
? " 🔤 Hide Keystrokes"
: " 🔤 Show Keystrokes";
? TuiIcons.menuItem(TuiIcons.KEYSTROKES, "Hide Keystrokes")
: TuiIcons.menuItem(TuiIcons.KEYSTROKES, "Show Keystrokes");
String stopLabel = stopAllPopup.hasBothGroups()
? " 🛑 Stop All..."
: " 🛑 Stop All";
? TuiIcons.menuItem(TuiIcons.STOP, "Stop All...")
: TuiIcons.menuItem(TuiIcons.STOP, "Stop All");
String tapeLabel = tapeRecordingActive.get()
? " 🛑 Stop Tape Recording (Ctrl+R)"
: " 🔴 Start Tape Recording (Ctrl+R)";
? TuiIcons.menuItem(TuiIcons.STOP, "Stop Tape Recording (Ctrl+R)")
: TuiIcons.menuItem(TuiIcons.RECORD, "Start Tape Recording (Ctrl+R)");

List<ListItem> items = new ArrayList<>();
// Group 0: Go to
items.add(ListItem.from(" 🔍 Go to..."));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.GO_TO, "Go to...")));
items.add(ListItem.from(divider).style(Style.EMPTY.dim()));
// Group 1: User Actions
boolean hasSelection = ctx != null && ctx.selectedPid != null && !ctx.isInfraSelected();
items.add(hasSelection
? ListItem.from(" 📩 Send Message")
: ListItem.from(" 📩 Send Message").style(Style.EMPTY.dim()));
items.add(ListItem.from(" 🐪 Run an Example..."));
items.add(ListItem.from(" 📂 Run from Folder..."));
items.add(ListItem.from(" 🔧 Run Dev/Infra Service..."));
? ListItem.from(TuiIcons.menuItem(TuiIcons.MESSAGE, "Send Message"))
: ListItem.from(TuiIcons.menuItem(TuiIcons.MESSAGE, "Send Message")).style(Style.EMPTY.dim()));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.CAMEL, "Run an Example...")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.FOLDER_OPEN, "Run from Folder...")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.INFRA, "Run Dev/Infra Service...")));
items.add(hasSelection
? ListItem.from(" 📁 Browse Files...")
: ListItem.from(" 📁 Browse Files...").style(Style.EMPTY.dim()));
? ListItem.from(TuiIcons.menuItem(TuiIcons.FOLDER, "Browse Files..."))
: ListItem.from(TuiIcons.menuItem(TuiIcons.FOLDER, "Browse Files...")).style(Style.EMPTY.dim()));
items.add(ListItem.from(stopLabel));
items.add(ListItem.from(divider).style(Style.EMPTY.dim()));
// Group 2: Diagnostics
items.add(ListItem.from(" 🩺 Run Doctor"));
items.add(ListItem.from(" 🔄 Reset Stats"));
items.add(ListItem.from(" 🧹 Reset Screen"));
String themeLabel = "dark".equals(Theme.mode()) ? " 🌞 Light Theme" : " 🌙 Dark Theme";
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.DOCTOR, "Run Doctor")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.RESET, "Reset Stats")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.CLEAN, "Reset Screen")));
String themeLabel = "dark".equals(Theme.mode())
? TuiIcons.menuItem(TuiIcons.LIGHT_THEME, "Light Theme")
: TuiIcons.menuItem(TuiIcons.DARK_THEME, "Dark Theme");
items.add(ListItem.from(themeLabel));
items.add(ListItem.from(divider).style(Style.EMPTY.dim()));
// Group 3: Recording & Presentation
items.add(ListItem.from(" 📸 Take Screenshot"));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.SCREENSHOT, "Take Screenshot")));
items.add(ListItem.from(tapeLabel));
items.add(ListItem.from(" 📄 Tape Recording Guide"));
items.add(ListItem.from(" 💬 Caption..."));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.DOCUMENT, "Tape Recording Guide")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.CAPTION, "Caption...")));
items.add(ListItem.from(keystrokeLabel));
// Group 4: MCP
if (mcpEnabled) {
items.add(ListItem.from(divider).style(Style.EMPTY.dim()));
items.add(ListItem.from(" 🧠 Setup MCP"));
items.add(ListItem.from(" 💬 AI Log"));
items.add(ListItem.from(" 🤖 MCP Info"));
items.add(ListItem.from(" 📋 MCP Log"));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.MCP_BRAIN, "Setup MCP")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.CAPTION, "AI Log")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.MCP, "MCP Info")));
items.add(ListItem.from(TuiIcons.menuItem(TuiIcons.MCP_LOG, "MCP Log")));
}
// Group 5: Shell
items.add(ListItem.from(divider).style(Style.EMPTY.dim()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void render(Frame frame, Rect area) {
}

void renderFooter(List<Span> spans) {
hint(spans, "↑↓", "select");
hint(spans, TuiIcons.HINT_SCROLL, "select");
hint(spans, "PgUp/Dn", "scroll detail");
hintLast(spans, "Esc", "back");
}
Expand Down Expand Up @@ -174,11 +174,13 @@ private void renderDetail(Frame frame, Rect area) {
if (detail != null && !detail.isBlank()) {
if (entry.level() == AiPanel.LogLevel.TOOL || entry.level() == AiPanel.LogLevel.RESULT) {
lines.add(Line.from(Span.styled(
entry.level() == AiPanel.LogLevel.TOOL ? "▶ Arguments" : "◀ Result",
entry.level() == AiPanel.LogLevel.TOOL
? TuiIcons.ARROW_RIGHT + " Arguments"
: TuiIcons.ARROW_LEFT + " Result",
Style.EMPTY.fg(entry.level() == AiPanel.LogLevel.TOOL ? Color.YELLOW : Color.GREEN).bold())));
addJsonLines(lines, detail);
} else {
lines.add(Line.from(Span.styled("▶ Content",
lines.add(Line.from(Span.styled(TuiIcons.ARROW_RIGHT + " Content",
Style.EMPTY.fg(Color.CYAN).bold())));
for (String line : detail.split("\n", -1)) {
lines.add(Line.from(Span.styled(" " + line, Style.EMPTY.dim())));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ private void renderConversation(Frame frame, Rect area) {
if (thinking.get()) {
long elapsed = (System.currentTimeMillis() - thinkingStartTime) / 1000;
long dots = (System.currentTimeMillis() / 500) % 4;
md.append("*🤔 thinking");
md.append("*" + TuiIcons.THINKING + " thinking");
if (elapsed > 0) {
md.append(" (").append(elapsed).append("s)");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public void renderFooter(List<Span> spans) {
} else {
hint(spans, "/", "filter");
}
hint(spans, "↑↓", "navigate");
hint(spans, TuiIcons.HINT_SCROLL, "navigate");
hintLast(spans, "PgUp/Dn", "scroll");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ public void renderFooter(List<Span> spans) {
hint(spans, "Esc", "back");
if (view == VIEW_DETAIL) {
hint(spans, "p", "pretty" + (prettyPrint ? " [on]" : ""));
hintLast(spans, "↑↓", "scroll");
hintLast(spans, TuiIcons.HINT_SCROLL, "scroll");
} else if (view == VIEW_MESSAGES) {
hint(spans, "r", "refresh");
hintLast(spans, "Enter", "detail");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ public class CamelMonitor extends CamelCommand {
// Compact tab bar (10 labels + 9 "|" dividers) needs 88 chars — that is the true minimum
private static final int MIN_WIDTH = 88;
private static final int MIN_HEIGHT = 24;
// Full tab bar (10 labels + 9 " | " dividers) needs 126 chars; use compact below that
private static final int TABS_FULL_MIN_WIDTH = 126;
// Below this width the tab bar uses tight "|" dividers instead of spaced " | " so all 10 labels still fit
private static final int TABS_FULL_MIN_WIDTH = 157;

@CommandLine.Parameters(description = "Name or pid of running Camel integration", arity = "0..1")
String name = "*";
Expand Down Expand Up @@ -304,7 +304,7 @@ public void selectMorePopupEntry(int index) {
});

popupManager = new PopupManager(
ctx, this::getNonVanishingIntegrations, filesBrowser,
ctx, this::getNonVanishingIntegrations, tabRegistry::moreTabs, filesBrowser,
new PopupManager.PopupCallbacks() {
@Override
public void selectMoreTab(int index) {
Expand Down Expand Up @@ -1244,15 +1244,10 @@ private void renderTabs(Frame frame, Rect area) {

if (infraSelected) {
// Infra mode: only Overview and Log tabs
Line[] labels = compact
? new Line[] {
Line.from("1 Overview"),
Line.from("2 Log"),
}
: new Line[] {
Line.from(" 1 Overview "),
Line.from(" 2 Log "),
};
Line[] labels = {
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_OVERVIEW, "1", "Overview")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_LOG, "2", "Log")),
};

// Map real tab index to infra tab index for highlight
int infraTabIdx = tabsState.selected() == TAB_LOG ? 1 : 0;
Expand All @@ -1273,31 +1268,20 @@ private void renderTabs(Frame frame, Rect area) {
return;
}

Line[] labels = compact
? new Line[] {
Line.from("1 Overview"),
Line.from("2 Log"),
Line.from("3 Diagram"),
Line.from(tabRegistry.routesTab().isTopMode() ? "4 Top " : "4 Route"),
Line.from("5 Endpoint"),
Line.from("6 HTTP"),
Line.from("7 Health"),
Line.from("8 Inspect"),
Line.from("9 Errors"),
Line.from("0 More▾"),
}
: new Line[] {
Line.from(" 1 Overview "),
Line.from(" 2 Log "),
Line.from(" 3 Diagram "),
Line.from(tabRegistry.routesTab().isTopMode() ? " 4 Top " : " 4 Route "),
Line.from(" 5 Endpoint "),
Line.from(" 6 HTTP "),
Line.from(" 7 Health "),
Line.from(" 8 Inspect "),
Line.from(" 9 Errors "),
Line.from(" 0 More▾ "),
};
// Route and Top labels are the same display width so toggling Top mode does not shift the bar.
String routesLabel = tabRegistry.routesTab().isTopMode() ? " Top " : "Route";
Line[] labels = {
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_OVERVIEW, "1", "Overview")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_LOG, "2", "Log")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_DIAGRAM, "3", "Diagram")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_ROUTES, "4", routesLabel)),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_ENDPOINTS, "5", "Endpoint")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_HTTP, "6", "HTTP")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_HEALTH, "7", "Health")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_INSPECT, "8", "Inspect")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_ERRORS, "9", "Errors")),
Line.from(TuiIcons.primaryTabHeader(TuiIcons.TAB_MORE, "0", TuiIcons.moreTabLabel())),
};
popupManager.setCurrentTabLabels(labels);
lastTabLabels = labels;
lastTabDivider = dividerStr;
Expand Down Expand Up @@ -1735,12 +1719,12 @@ private void renderFooter(Frame frame, Rect area) {
Style labelStyle;
Style suffixStyle;
if (client != null) {
suffix = active ? " ●" : " ○";
suffix = active ? " " + TuiIcons.SELECTED : " " + TuiIcons.IDLE;
mcpLabel += " (" + client + ")";
labelStyle = Theme.success();
suffixStyle = active ? Theme.mcpActive() : Theme.mcpIdle();
} else {
suffix = " ✗";
suffix = " " + TuiIcons.CROSS;
labelStyle = Theme.muted();
suffixStyle = Theme.mcpDown();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ protected void renderContent(Frame frame, Rect area, IntegrationInfo info) {
@Override
public void renderFooter(List<Span> spans) {
hint(spans, "Esc", "back");
hint(spans, "↑↓", "navigate");
hint(spans, TuiIcons.HINT_SCROLL, "navigate");
hint(spans, "s", "sort");
}

Expand Down Expand Up @@ -208,7 +208,7 @@ private void renderStateDiagram(Frame frame, Rect area, CircuitBreakerInfo cb) {
lines.add(Line.from(
Span.raw(" "),
Span.styled("│ CLOSED │", closedBox),
Span.raw("─────────────►"),
Span.raw("─────────────" + TuiIcons.POINTER),
Span.styled("│ OPEN │", openBox),
Span.raw("◄─┐")));
lines.add(Line.from(
Expand All @@ -220,7 +220,7 @@ private void renderStateDiagram(Frame frame, Rect area, CircuitBreakerInfo cb) {
lines.add(Line.from(
Span.raw(" "),
Span.styled("└──────", closedBox),
Span.raw("▲"),
Span.raw(TuiIcons.SORT_UP),
Span.styled("───────┘", closedBox),
Span.raw(" "),
Span.styled("└───────", openBox),
Expand All @@ -240,7 +240,7 @@ private void renderStateDiagram(Frame frame, Rect area, CircuitBreakerInfo cb) {
lines.add(Line.from(
Span.raw(" │ "),
Span.styled("┌───────", halfOpenBox),
Span.raw("▼"),
Span.raw(TuiIcons.SORT_DOWN),
Span.styled("──────┐", halfOpenBox),
Span.raw(" │")));
lines.add(Line.from(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public void renderFooter(List<Span> spans) {
} else {
hint(spans, "/", "filter");
}
hintLast(spans, "↑↓", "navigate");
hintLast(spans, TuiIcons.HINT_SCROLL, "navigate");
}

private void loadClasspath() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ private Map<String, BaseOptionModel> getComponentOptions(String componentName) {
@Override
public void renderFooter(List<Span> spans) {
super.renderFooter(spans);
hint(spans, "↑↓", "navigate");
hint(spans, TuiIcons.HINT_SCROLL, "navigate");
hintLast(spans, "PgUp/Dn", "scroll");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ protected void renderContent(Frame frame, Rect area, IntegrationInfo info) {
: ("Started".equals(ci.state) || "Polling".equals(status)
? Style.EMPTY.fg(Color.GREEN)
: Style.EMPTY.fg(Color.LIGHT_RED));
String statusText = healthDown ? "⚠ " + status : status;
String statusText = healthDown ? TuiIcons.HEALTH_WARN + " " + status : status;
String type = consumerType(ci);
String schedule = consumerSchedule(ci);
String sinceLast = consumerSinceLast(ci);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ void preload(MonitorContext ctx, String pid) {

void renderFooterHints(List<Span> spans) {
hint(spans, "d/Esc", "close");
hint(spans, "↑↓←→", "scroll");
hint(spans, TuiIcons.HINT_NAV, "scroll");
hint(spans, "PgUp/PgDn", "page");
hint(spans, "Home/End", "top/end");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -663,17 +663,17 @@ public void renderFooter(List<Span> spans) {
if (!topologyMode && !diagram.getEipNodeBoxes().isEmpty()) {
hint(spans, "Esc", "back");
hint(spans, "t", "topology");
hint(spans, "↑↓←→", "navigate");
hint(spans, TuiIcons.HINT_NAV, "navigate");
hint(spans, "PgUp/PgDn", "page");
hint(spans, "c", "source");
} else if (!topologyMode) {
hint(spans, "Esc", "back");
hint(spans, "t", "topology");
hint(spans, "↑↓←→", "scroll");
hint(spans, TuiIcons.HINT_NAV, "scroll");
hint(spans, "PgUp/PgDn", "page");
} else if (!diagram.getNodeBoxes().isEmpty()) {
hint(spans, "Esc", "close");
hint(spans, "↑↓←→", "navigate");
hint(spans, TuiIcons.HINT_NAV, "navigate");
hint(spans, "Enter", "drill-down");
hint(spans, "PgUp/PgDn", "page");
hint(spans, "c", "source");
Expand Down
Loading