Reflow Node Lists and TLora Pager Views (#8942)

* Add files via upload

* Move files into the right place
This commit is contained in:
Jason P
2025-12-11 14:25:48 -06:00
committed by Jonathan Bennett
parent 20887eb1f6
commit f68ef9f7d7
5 changed files with 172 additions and 68 deletions

View File

@@ -1046,11 +1046,16 @@ void Screen::setFrames(FrameFocus focus)
indicatorIcons.push_back(icon_mail); indicatorIcons.push_back(icon_mail);
#ifndef USE_EINK #ifndef USE_EINK
if (!hiddenFrames.nodelist) { if (!hiddenFrames.nodelist_nodes) {
fsi.positions.nodelist = numframes; fsi.positions.nodelist_nodes = numframes;
normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicNodeListScreen; normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicListScreen_Nodes;
indicatorIcons.push_back(icon_nodes); indicatorIcons.push_back(icon_nodes);
} }
if (!hiddenFrames.nodelist_location) {
fsi.positions.nodelist_location = numframes;
normalFrames[numframes++] = graphics::NodeListRenderer::drawDynamicListScreen_Location;
indicatorIcons.push_back(icon_list);
}
#endif #endif
// Show detailed node views only on E-Ink builds // Show detailed node views only on E-Ink builds
@@ -1072,11 +1077,13 @@ void Screen::setFrames(FrameFocus focus)
} }
#endif #endif
#if HAS_GPS #if HAS_GPS
#ifdef USE_EINK
if (!hiddenFrames.nodelist_bearings) { if (!hiddenFrames.nodelist_bearings) {
fsi.positions.nodelist_bearings = numframes; fsi.positions.nodelist_bearings = numframes;
normalFrames[numframes++] = graphics::NodeListRenderer::drawNodeListWithCompasses; normalFrames[numframes++] = graphics::NodeListRenderer::drawNodeListWithCompasses;
indicatorIcons.push_back(icon_list); indicatorIcons.push_back(icon_list);
} }
#endif
if (!hiddenFrames.gps) { if (!hiddenFrames.gps) {
fsi.positions.gps = numframes; fsi.positions.gps = numframes;
normalFrames[numframes++] = graphics::UIRenderer::drawCompassAndLocationScreen; normalFrames[numframes++] = graphics::UIRenderer::drawCompassAndLocationScreen;
@@ -1238,8 +1245,11 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
void Screen::toggleFrameVisibility(const std::string &frameName) void Screen::toggleFrameVisibility(const std::string &frameName)
{ {
#ifndef USE_EINK #ifndef USE_EINK
if (frameName == "nodelist") { if (frameName == "nodelist_nodes") {
hiddenFrames.nodelist = !hiddenFrames.nodelist; hiddenFrames.nodelist_nodes = !hiddenFrames.nodelist_nodes;
}
if (frameName == "nodelist_location") {
hiddenFrames.nodelist_location = !hiddenFrames.nodelist_location;
} }
#endif #endif
#ifdef USE_EINK #ifdef USE_EINK
@@ -1254,9 +1264,11 @@ void Screen::toggleFrameVisibility(const std::string &frameName)
} }
#endif #endif
#if HAS_GPS #if HAS_GPS
#ifdef USE_EINK
if (frameName == "nodelist_bearings") { if (frameName == "nodelist_bearings") {
hiddenFrames.nodelist_bearings = !hiddenFrames.nodelist_bearings; hiddenFrames.nodelist_bearings = !hiddenFrames.nodelist_bearings;
} }
#endif
if (frameName == "gps") { if (frameName == "gps") {
hiddenFrames.gps = !hiddenFrames.gps; hiddenFrames.gps = !hiddenFrames.gps;
} }
@@ -1278,8 +1290,10 @@ void Screen::toggleFrameVisibility(const std::string &frameName)
bool Screen::isFrameHidden(const std::string &frameName) const bool Screen::isFrameHidden(const std::string &frameName) const
{ {
#ifndef USE_EINK #ifndef USE_EINK
if (frameName == "nodelist") if (frameName == "nodelist_nodes")
return hiddenFrames.nodelist; return hiddenFrames.nodelist_nodes;
if (frameName == "nodelist_location")
return hiddenFrames.nodelist_location;
#endif #endif
#ifdef USE_EINK #ifdef USE_EINK
if (frameName == "nodelist_lastheard") if (frameName == "nodelist_lastheard")
@@ -1290,8 +1304,10 @@ bool Screen::isFrameHidden(const std::string &frameName) const
return hiddenFrames.nodelist_distance; return hiddenFrames.nodelist_distance;
#endif #endif
#if HAS_GPS #if HAS_GPS
#ifdef USE_EINK
if (frameName == "nodelist_bearings") if (frameName == "nodelist_bearings")
return hiddenFrames.nodelist_bearings; return hiddenFrames.nodelist_bearings;
#endif
if (frameName == "gps") if (frameName == "gps")
return hiddenFrames.gps; return hiddenFrames.gps;
#endif #endif
@@ -1716,7 +1732,8 @@ int Screen::handleInputEvent(const InputEvent *event)
this->ui->getUiState()->currentFrame >= framesetInfo.positions.firstFavorite && this->ui->getUiState()->currentFrame >= framesetInfo.positions.firstFavorite &&
this->ui->getUiState()->currentFrame <= framesetInfo.positions.lastFavorite) { this->ui->getUiState()->currentFrame <= framesetInfo.positions.lastFavorite) {
menuHandler::favoriteBaseMenu(); menuHandler::favoriteBaseMenu();
} else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist || } else if (this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_nodes ||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_location ||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_lastheard || this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_lastheard ||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_hopsignal || this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_hopsignal ||
this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_distance || this->ui->getUiState()->currentFrame == framesetInfo.positions.nodelist_distance ||

View File

@@ -654,7 +654,8 @@ class Screen : public concurrency::OSThread
uint8_t gps = 255; uint8_t gps = 255;
uint8_t home = 255; uint8_t home = 255;
uint8_t textMessage = 255; uint8_t textMessage = 255;
uint8_t nodelist = 255; uint8_t nodelist_nodes = 255;
uint8_t nodelist_location = 255;
uint8_t nodelist_lastheard = 255; uint8_t nodelist_lastheard = 255;
uint8_t nodelist_hopsignal = 255; uint8_t nodelist_hopsignal = 255;
uint8_t nodelist_distance = 255; uint8_t nodelist_distance = 255;
@@ -677,7 +678,8 @@ class Screen : public concurrency::OSThread
bool home = false; bool home = false;
bool clock = false; bool clock = false;
#ifndef USE_EINK #ifndef USE_EINK
bool nodelist = false; bool nodelist_nodes = false;
bool nodelist_location = false;
#endif #endif
#ifdef USE_EINK #ifdef USE_EINK
bool nodelist_lastheard = false; bool nodelist_lastheard = false;
@@ -685,7 +687,9 @@ class Screen : public concurrency::OSThread
bool nodelist_distance = false; bool nodelist_distance = false;
#endif #endif
#if HAS_GPS #if HAS_GPS
#ifdef USE_EINK
bool nodelist_bearings = false; bool nodelist_bearings = false;
#endif
bool gps = false; bool gps = false;
#endif #endif
bool lora = false; bool lora = false;

View File

@@ -1111,20 +1111,33 @@ void menuHandler::positionBaseMenu()
void menuHandler::nodeListMenu() void menuHandler::nodeListMenu()
{ {
enum optionsNumbers { Back, Favorite, TraceRoute, Verify, Reset, enumEnd }; enum optionsNumbers { Back, Favorite, TraceRoute, Verify, Reset, NodeNameLength, enumEnd };
#if defined(M5STACK_UNITC6L) static const char *optionsArray[enumEnd] = {"Back"};
static const char *optionsArray[] = {"Back", "Add Favorite", "Reset Node"}; static int optionsEnumArray[enumEnd] = {Back};
#else int options = 1;
static const char *optionsArray[] = {"Back", "Add Favorite", "Trace Route", "Key Verification", "Reset NodeDB"};
optionsArray[options] = "Add Favorite";
optionsEnumArray[options++] = Favorite;
optionsArray[options] = "Trace Route";
optionsEnumArray[options++] = TraceRoute;
#if !defined(M5STACK_UNITC6L)
optionsArray[options] = "Key Verification";
optionsEnumArray[options++] = Verify;
#endif #endif
#if defined(T_DECK) || defined(T_LORA_PAGER) || defined(HACKADAY_COMMUNICATOR)
optionsArray[options] = "Show Long/Short Name";
optionsEnumArray[options++] = NodeNameLength;
#endif
optionsArray[options] = "Reset NodeDB";
optionsEnumArray[options++] = Reset;
BannerOverlayOptions bannerOptions; BannerOverlayOptions bannerOptions;
bannerOptions.message = "Node Action"; bannerOptions.message = "Node Action";
bannerOptions.optionsArrayPtr = optionsArray; bannerOptions.optionsArrayPtr = optionsArray;
#if defined(M5STACK_UNITC6L) bannerOptions.optionsCount = options;
bannerOptions.optionsCount = 3; bannerOptions.optionsEnumPtr = optionsEnumArray;
#else
bannerOptions.optionsCount = 5;
#endif
bannerOptions.bannerCallback = [](int selected) -> void { bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == Favorite) { if (selected == Favorite) {
menuQueue = add_favorite; menuQueue = add_favorite;
@@ -1138,6 +1151,9 @@ void menuHandler::nodeListMenu()
} else if (selected == TraceRoute) { } else if (selected == TraceRoute) {
menuQueue = trace_route_menu; menuQueue = trace_route_menu;
screen->runNow(); screen->runNow();
} else if (selected == NodeNameLength) {
menuHandler::menuQueue = menuHandler::node_name_length_menu;
screen->runNow();
} }
}; };
screen->showOverlayBanner(bannerOptions); screen->showOverlayBanner(bannerOptions);
@@ -1731,16 +1747,11 @@ void menuHandler::screenOptionsMenu()
hasSupportBrightness = false; hasSupportBrightness = false;
#endif #endif
enum optionsNumbers { Back, NodeNameLength, Brightness, ScreenColor, FrameToggles, DisplayUnits }; enum optionsNumbers { Back, Brightness, ScreenColor, FrameToggles, DisplayUnits };
static const char *optionsArray[5] = {"Back"}; static const char *optionsArray[5] = {"Back"};
static int optionsEnumArray[5] = {Back}; static int optionsEnumArray[5] = {Back};
int options = 1; int options = 1;
#if defined(T_DECK) || defined(T_LORA_PAGER) || defined(HACKADAY_COMMUNICATOR)
optionsArray[options] = "Show Long/Short Name";
optionsEnumArray[options++] = NodeNameLength;
#endif
// Only show brightness for B&W displays // Only show brightness for B&W displays
if (hasSupportBrightness) { if (hasSupportBrightness) {
optionsArray[options] = "Brightness"; optionsArray[options] = "Brightness";
@@ -1772,9 +1783,6 @@ void menuHandler::screenOptionsMenu()
} else if (selected == ScreenColor) { } else if (selected == ScreenColor) {
menuHandler::menuQueue = menuHandler::tftcolormenupicker; menuHandler::menuQueue = menuHandler::tftcolormenupicker;
screen->runNow(); screen->runNow();
} else if (selected == NodeNameLength) {
menuHandler::menuQueue = menuHandler::node_name_length_menu;
screen->runNow();
} else if (selected == FrameToggles) { } else if (selected == FrameToggles) {
menuHandler::menuQueue = menuHandler::FrameToggles; menuHandler::menuQueue = menuHandler::FrameToggles;
screen->runNow(); screen->runNow();
@@ -1870,7 +1878,8 @@ void menuHandler::FrameToggles_menu()
{ {
enum optionsNumbers { enum optionsNumbers {
Finish, Finish,
nodelist, nodelist_nodes,
nodelist_location,
nodelist_lastheard, nodelist_lastheard,
nodelist_hopsignal, nodelist_hopsignal,
nodelist_distance, nodelist_distance,
@@ -1891,20 +1900,25 @@ void menuHandler::FrameToggles_menu()
static int lastSelectedIndex = 0; static int lastSelectedIndex = 0;
#ifndef USE_EINK #ifndef USE_EINK
optionsArray[options] = screen->isFrameHidden("nodelist") ? "Show Node List" : "Hide Node List"; optionsArray[options] = screen->isFrameHidden("nodelist_nodes") ? "Show Node List" : "Hide Node List";
optionsEnumArray[options++] = nodelist; optionsEnumArray[options++] = nodelist_nodes;
#endif #else
#ifdef USE_EINK
optionsArray[options] = screen->isFrameHidden("nodelist_lastheard") ? "Show NL - Last Heard" : "Hide NL - Last Heard"; optionsArray[options] = screen->isFrameHidden("nodelist_lastheard") ? "Show NL - Last Heard" : "Hide NL - Last Heard";
optionsEnumArray[options++] = nodelist_lastheard; optionsEnumArray[options++] = nodelist_lastheard;
optionsArray[options] = screen->isFrameHidden("nodelist_hopsignal") ? "Show NL - Hops/Signal" : "Hide NL - Hops/Signal"; optionsArray[options] = screen->isFrameHidden("nodelist_hopsignal") ? "Show NL - Hops/Signal" : "Hide NL - Hops/Signal";
optionsEnumArray[options++] = nodelist_hopsignal; optionsEnumArray[options++] = nodelist_hopsignal;
#endif
#if HAS_GPS
#ifndef USE_EINK
optionsArray[options] = screen->isFrameHidden("nodelist_location") ? "Show Node Location List" : "Hide Node Location List";
optionsEnumArray[options++] = nodelist_location;
#else
optionsArray[options] = screen->isFrameHidden("nodelist_distance") ? "Show NL - Distance" : "Hide NL - Distance"; optionsArray[options] = screen->isFrameHidden("nodelist_distance") ? "Show NL - Distance" : "Hide NL - Distance";
optionsEnumArray[options++] = nodelist_distance; optionsEnumArray[options++] = nodelist_distance;
#endif optionsArray[options] = screen->isFrameHidden("nodelist_bearings") ? "Show NL - Bearings" : "Hide NL - Bearings";
#if HAS_GPS
optionsArray[options] = screen->isFrameHidden("nodelist_bearings") ? "Show Bearings" : "Hide Bearings";
optionsEnumArray[options++] = nodelist_bearings; optionsEnumArray[options++] = nodelist_bearings;
#endif
optionsArray[options] = screen->isFrameHidden("gps") ? "Show Position" : "Hide Position"; optionsArray[options] = screen->isFrameHidden("gps") ? "Show Position" : "Hide Position";
optionsEnumArray[options++] = gps; optionsEnumArray[options++] = gps;
@@ -1943,8 +1957,12 @@ void menuHandler::FrameToggles_menu()
if (selected == Finish) { if (selected == Finish) {
screen->setFrames(Screen::FOCUS_DEFAULT); screen->setFrames(Screen::FOCUS_DEFAULT);
} else if (selected == nodelist) { } else if (selected == nodelist_nodes) {
screen->toggleFrameVisibility("nodelist"); screen->toggleFrameVisibility("nodelist_nodes");
menuHandler::menuQueue = menuHandler::FrameToggles;
screen->runNow();
} else if (selected == nodelist_location) {
screen->toggleFrameVisibility("nodelist_location");
menuHandler::menuQueue = menuHandler::FrameToggles; menuHandler::menuQueue = menuHandler::FrameToggles;
screen->runNow(); screen->runNow();
} else if (selected == nodelist_lastheard) { } else if (selected == nodelist_lastheard) {
@@ -2163,4 +2181,4 @@ void menuHandler::saveUIConfig()
} // namespace graphics } // namespace graphics
#endif #endif

View File

@@ -46,7 +46,8 @@ void drawScaledXBitmap16x16(int x, int y, int width, int height, const uint8_t *
} }
// Static variables for dynamic cycling // Static variables for dynamic cycling
static NodeListMode currentMode = MODE_LAST_HEARD; static ListMode_Node currentMode_Nodes = MODE_LAST_HEARD;
static ListMode_Location currentMode_Location = MODE_DISTANCE;
static int scrollIndex = 0; static int scrollIndex = 0;
// ============================= // =============================
@@ -55,7 +56,7 @@ static int scrollIndex = 0;
const char *getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node) const char *getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node)
{ {
static char nodeName[16]; // single static buffer we return static char nodeName[25]; // single static buffer we return
nodeName[0] = '\0'; nodeName[0] = '\0';
auto writeFallbackId = [&] { auto writeFallbackId = [&] {
@@ -109,9 +110,9 @@ const char *getSafeNodeName(OLEDDisplay *display, meshtastic_NodeInfoLite *node)
return nodeName; return nodeName;
} }
const char *getCurrentModeTitle(int screenWidth) const char *getCurrentModeTitle_Nodes(int screenWidth)
{ {
switch (currentMode) { switch (currentMode_Nodes) {
case MODE_LAST_HEARD: case MODE_LAST_HEARD:
return "Last Heard"; return "Last Heard";
case MODE_HOP_SIGNAL: case MODE_HOP_SIGNAL:
@@ -120,8 +121,18 @@ const char *getCurrentModeTitle(int screenWidth)
#else #else
return (isHighResolution) ? "Hops/Signal" : "Hops/Sig"; return (isHighResolution) ? "Hops/Signal" : "Hops/Sig";
#endif #endif
default:
return "Nodes";
}
}
const char *getCurrentModeTitle_Location(int screenWidth)
{
switch (currentMode_Location) {
case MODE_DISTANCE: case MODE_DISTANCE:
return "Distance"; return "Distance";
case MODE_BEARING:
return "Bearings";
default: default:
return "Nodes"; return "Nodes";
} }
@@ -140,10 +151,8 @@ int calculateMaxScroll(int totalEntries, int visibleRows)
void drawColumnSeparator(OLEDDisplay *display, int16_t x, int16_t yStart, int16_t yEnd) void drawColumnSeparator(OLEDDisplay *display, int16_t x, int16_t yStart, int16_t yEnd)
{ {
int columnWidth = display->getWidth() / 2;
int separatorX = x + columnWidth - 2;
for (int y = yStart; y <= yEnd; y += 2) { for (int y = yStart; y <= yEnd; y += 2) {
display->setPixel(separatorX, y); display->setPixel(x, y);
} }
} }
@@ -332,18 +341,15 @@ void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
} }
} }
void drawEntryDynamic(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth) void drawEntryDynamic_Nodes(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth)
{ {
switch (currentMode) { switch (currentMode_Nodes) {
case MODE_LAST_HEARD: case MODE_LAST_HEARD:
drawEntryLastHeard(display, node, x, y, columnWidth); drawEntryLastHeard(display, node, x, y, columnWidth);
break; break;
case MODE_HOP_SIGNAL: case MODE_HOP_SIGNAL:
drawEntryHopSignal(display, node, x, y, columnWidth); drawEntryHopSignal(display, node, x, y, columnWidth);
break; break;
case MODE_DISTANCE:
drawNodeDistance(display, node, x, y, columnWidth);
break;
default: default:
break; break;
} }
@@ -436,9 +442,15 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
locationScreen = true; locationScreen = true;
#if defined(M5STACK_UNITC6L) #if defined(M5STACK_UNITC6L)
int columnWidth = display->getWidth(); int columnWidth = display->getWidth();
#elif defined(T_LORA_PAGER)
int columnWidth = display->getWidth() / 3;
if (config.display.use_long_node_name) {
columnWidth = display->getWidth() / 2;
}
#else #else
int columnWidth = display->getWidth() / 2; int columnWidth = display->getWidth() / 2;
#endif #endif
display->clear(); display->clear();
// Draw the battery/time header // Draw the battery/time header
@@ -453,6 +465,11 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
int visibleNodeRows = totalRowsAvailable; int visibleNodeRows = totalRowsAvailable;
#if defined(M5STACK_UNITC6L) #if defined(M5STACK_UNITC6L)
int totalColumns = 1; int totalColumns = 1;
#elif defined(T_LORA_PAGER)
int totalColumns = 3;
if (config.display.use_long_node_name) {
totalColumns = 2;
}
#else #else
int totalColumns = 2; int totalColumns = 2;
#endif #endif
@@ -502,7 +519,9 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
// Draw column separator // Draw column separator
if (shownCount > 0) { if (shownCount > 0) {
const int firstNodeY = y + 3; const int firstNodeY = y + 3;
drawColumnSeparator(display, x, firstNodeY, lastNodeY); for (int horizontal_offset = 1; horizontal_offset < totalColumns; horizontal_offset++) {
drawColumnSeparator(display, columnWidth * horizontal_offset, firstNodeY, lastNodeY);
}
} }
#endif #endif
@@ -516,10 +535,11 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
// ============================= // =============================
#ifndef USE_EINK #ifndef USE_EINK
void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) // Node list for Last Heard and Hop Signal views
void drawDynamicListScreen_Nodes(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
// Static variables to track mode and duration // Static variables to track mode and duration
static NodeListMode lastRenderedMode = MODE_COUNT; static ListMode_Node lastRenderedMode = MODE_COUNT_NODE;
static unsigned long modeStartTime = 0; static unsigned long modeStartTime = 0;
unsigned long now = millis(); unsigned long now = millis();
@@ -532,23 +552,65 @@ void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
} }
#endif #endif
// On very first call (on boot or state enter) // On very first call (on boot or state enter)
if (lastRenderedMode == MODE_COUNT) { if (lastRenderedMode == MODE_COUNT_NODE) {
currentMode = MODE_LAST_HEARD; currentMode_Nodes = MODE_LAST_HEARD;
modeStartTime = now; modeStartTime = now;
} }
// Time to switch to next mode? // Time to switch to next mode?
if (now - modeStartTime >= getModeCycleIntervalMs()) { if (now - modeStartTime >= getModeCycleIntervalMs()) {
currentMode = static_cast<NodeListMode>((currentMode + 1) % MODE_COUNT); currentMode_Nodes = static_cast<ListMode_Node>((currentMode_Nodes + 1) % MODE_COUNT_NODE);
modeStartTime = now; modeStartTime = now;
} }
// Render screen based on currentMode // Render screen based on currentMode
const char *title = getCurrentModeTitle(display->getWidth()); const char *title = getCurrentModeTitle_Nodes(display->getWidth());
drawNodeListScreen(display, state, x, y, title, drawEntryDynamic); drawNodeListScreen(display, state, x, y, title, drawEntryDynamic_Nodes);
// Track the last mode to avoid reinitializing modeStartTime // Track the last mode to avoid reinitializing modeStartTime
lastRenderedMode = currentMode; lastRenderedMode = currentMode_Nodes;
}
// Node list for Distance and Bearings views
void drawDynamicListScreen_Location(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Static variables to track mode and duration
static ListMode_Location lastRenderedMode = MODE_COUNT_LOCATION;
static unsigned long modeStartTime = 0;
unsigned long now = millis();
#if defined(M5STACK_UNITC6L)
display->clear();
if (now - lastSwitchTime >= 3000) {
display->display();
lastSwitchTime = now;
}
#endif
// On very first call (on boot or state enter)
if (lastRenderedMode == MODE_COUNT_LOCATION) {
currentMode_Location = MODE_DISTANCE;
modeStartTime = now;
}
// Time to switch to next mode?
if (now - modeStartTime >= getModeCycleIntervalMs()) {
currentMode_Location = static_cast<ListMode_Location>((currentMode_Location + 1) % MODE_COUNT_LOCATION);
modeStartTime = now;
}
// Render screen based on currentMode
const char *title = getCurrentModeTitle_Location(display->getWidth());
// Render screen based on currentMode_Location
if (currentMode_Location == MODE_DISTANCE) {
drawNodeListScreen(display, state, x, y, title, drawNodeDistance);
} else if (currentMode_Location == MODE_BEARING) {
drawNodeListWithCompasses(display, state, x, y);
}
// Track the last mode to avoid reinitializing modeStartTime
lastRenderedMode = currentMode_Location;
} }
#endif #endif
@@ -569,14 +631,12 @@ void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
#endif #endif
drawNodeListScreen(display, state, x, y, title, drawEntryHopSignal); drawNodeListScreen(display, state, x, y, title, drawEntryHopSignal);
} }
void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
const char *title = "Distance"; const char *title = "Distance";
drawNodeListScreen(display, state, x, y, title, drawNodeDistance); drawNodeListScreen(display, state, x, y, title, drawNodeDistance);
} }
#endif #endif
void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
float heading = 0; float heading = 0;

View File

@@ -23,8 +23,11 @@ namespace NodeListRenderer
typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int); typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int);
typedef void (*NodeExtrasRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int, float, double, double); typedef void (*NodeExtrasRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int, float, double, double);
// Node list mode enumeration // Node list mode enumeration for Last Heard and Hop Signal views
enum NodeListMode { MODE_LAST_HEARD = 0, MODE_HOP_SIGNAL = 1, MODE_DISTANCE = 2, MODE_COUNT = 3 }; enum ListMode_Node { MODE_LAST_HEARD = 0, MODE_HOP_SIGNAL = 1, MODE_COUNT_NODE = 2 };
// Node list mode enumeration for Distance and Bearings views
enum ListMode_Location { MODE_DISTANCE = 0, MODE_BEARING = 1, MODE_COUNT_LOCATION = 2 };
// Main node list screen function // Main node list screen function
void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title, void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title,
@@ -35,7 +38,7 @@ void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t
void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth); void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth); void drawEntryHopSignal(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth); void drawNodeDistance(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
void drawEntryDynamic(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth); void drawEntryDynamic_Nodes(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth); void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
// Extras renderers // Extras renderers
@@ -46,11 +49,13 @@ void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16
void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); void drawDistanceScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); void drawDynamicListScreen_Nodes(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
void drawDynamicListScreen_Location(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); void drawNodeListWithCompasses(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
// Utility functions // Utility functions
const char *getCurrentModeTitle(int screenWidth); const char *getCurrentModeTitle_Nodes(int screenWidth);
const char *getCurrentModeTitle_Location(int screenWidth);
const char *getSafeNodeName(meshtastic_NodeInfoLite *node); const char *getSafeNodeName(meshtastic_NodeInfoLite *node);
void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char **fields); void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char **fields);