InkHUD: Nodelist cleanup (#9737)

* Nodelist cleanup

* Trunk fix

* getTextWidth cleanup

Updated the lambda to cache width in textW and reuse it instead of repeatedly calling getTextWidth(text) for unchanged text.

* Putting back hopAway ==0  condition as mentioned relayed signal is missleading

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
HarukiToreda
2026-03-06 06:16:34 -06:00
committed by GitHub
co-authored by GitHub Ben Meadors
parent 5b94f580dc
commit 5b1ea922f3
2 changed files with 54 additions and 29 deletions
@@ -120,9 +120,26 @@ void InkHUD::NodeListApplet::onRender(bool full)
// Draw the main node list
// ========================
// Imaginary vertical line dividing left-side and right-side info
// Long-name will crop here
const uint16_t dividerX = (width() - 1) - getTextWidth("X Hops");
// Leave a small gutter between long-name text and right-side card content
constexpr uint8_t rightContentGap = 2;
// Truncate with trailing "...", sized using the current font.
auto ellipsizeToWidth = [this](std::string text, uint16_t maxWidth) {
constexpr const char *ellipsis = "...";
const uint16_t ellipsisW = getTextWidth(ellipsis);
uint16_t textW = getTextWidth(text);
if (maxWidth == 0)
return std::string();
if (textW <= maxWidth)
return text;
if (ellipsisW > maxWidth)
return std::string();
while (!text.empty() && (textW + ellipsisW > maxWidth)) {
text.pop_back();
textW = getTextWidth(text);
}
return text + ellipsis;
};
// Y value (top) of the current card. Increases as we draw.
uint16_t cardTopY = headerDivY + padDivH;
@@ -141,7 +158,7 @@ void InkHUD::NodeListApplet::onRender(bool full)
SignalStrength &signal = card->signal;
std::string longName; // handled below
std::string shortName; // handled below
std::string distance; // handled below;
std::string distance; // handled below
const uint8_t &hopsAway = card->hopsAway;
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeNum);
@@ -185,41 +202,49 @@ void InkHUD::NodeListApplet::onRender(bool full)
setFont(fontMedium);
printAt(0, lineAY, shortName, LEFT, MIDDLE);
// Print the distance
// Right-side labels and long name are rendered in small font.
setFont(fontSmall);
printAt(width() - 1, lineBY, distance, RIGHT, MIDDLE);
uint16_t rightContentW = 0;
// If we have a direct connection to the node, draw the signal indicator
// Bottom row right: distance.
if (!distance.empty()) {
rightContentW = std::max(rightContentW, getTextWidth(distance));
printAt(width() - 1, lineBY, distance, RIGHT, MIDDLE);
}
// Top row right: direct-link signal only.
if (hopsAway == 0 && signal != SIGNAL_UNKNOWN) {
uint16_t signalW = getTextWidth("Xkm"); // Indicator should be similar width to distance label
uint16_t signalW = getTextWidth("Xkm"); // Indicator width tuned to a short right-side label
uint16_t signalH = fontMedium.lineHeight() * 0.75;
int16_t signalY = lineAY + (fontMedium.lineHeight() / 2) - (fontMedium.lineHeight() * 0.75);
int16_t signalX = width() - signalW;
rightContentW = std::max(rightContentW, signalW);
drawSignalIndicator(signalX, signalY, signalW, signalH, signal);
}
// Otherwise, print "hops away" info, if available
else if (hopsAway != CardInfo::HOPS_UNKNOWN && node) {
std::string hopString = to_string(node->hops_away);
hopString += " Hop";
if (node->hops_away != 1)
hopString += "s"; // Append s for "Hops", rather than "Hop"
} else if (hopsAway != CardInfo::HOPS_UNKNOWN) {
std::string hopString = to_string(hopsAway) + (hopsAway == 1 ? " Hop" : " Hops");
rightContentW = std::max(rightContentW, getTextWidth(hopString));
printAt(width() - 1, lineAY, hopString, RIGHT, MIDDLE);
}
// Print the long name, cropping to prevent overflow onto the right-side info
setCrop(0, 0, dividerX - 1, height());
printAt(0, lineBY, longName, LEFT, MIDDLE);
// Give long names as much room as possible while still avoiding right side signal and hop space
const uint16_t longNameMaxW =
(rightContentW + rightContentGap < width()) ? (width() - rightContentW - rightContentGap) : 0;
const std::string longNameShown = ellipsizeToWidth(longName, longNameMaxW);
// GFX effect: "hatch" the right edge of longName area
// If a longName has been cropped, it will appear to fade out,
// creating a soft barrier with the right-side info
const int16_t hatchLeft = dividerX - 1 - (fontSmall.lineHeight());
const int16_t hatchWidth = fontSmall.lineHeight();
hatchRegion(hatchLeft, cardTopY, hatchWidth, cardH, 2, WHITE);
// Safety crop
setCrop(0, cardTopY, longNameMaxW, cardH);
printAt(0, lineBY, longNameShown, LEFT, MIDDLE);
resetCrop();
// Draw separator between cards
const int16_t separatorY = cardTopY + cardH - 1;
if (separatorY < height() - 1 && (card + 1) != cards.end()) {
for (int16_t xSep = 0; xSep < width(); xSep += 2)
drawPixel(xSep, separatorY, BLACK);
}
// Prepare to draw the next card
resetCrop();
cardTopY += cardH;
// Once we've run out of screen, stop drawing cards
@@ -288,4 +313,4 @@ void InkHUD::NodeListApplet::drawSignalIndicator(int16_t x, int16_t y, uint16_t
}
}
#endif
#endif
@@ -65,10 +65,10 @@ class NodeListApplet : public Applet, public MeshModule
// Card Dimensions
// - for rendering and for maxCards calc
uint8_t cardMarginH = fontSmall.lineHeight() / 2; // Gap between cards
uint8_t cardMarginH = 1; // Gap between cards (minimal to fit more rows)
uint16_t cardH = fontMedium.lineHeight() + fontSmall.lineHeight() + cardMarginH; // Height of card
};
} // namespace NicheGraphics::InkHUD
#endif
#endif