17#include <goodisplay/gdey029T94.h>
19static const char*
TAG =
"ListView";
55 if (!preservePosition_) {
59 preservePosition_ =
false;
60 if (selection_ >= itemCount_) {
61 selection_ = itemCount_ > 0 ? itemCount_ - 1 : 0;
68 LOG_D(
TAG,
"init: title='%s', items=%d, visible=%d", title, itemCount_, visibleItems_);
77 if (index < itemCount_ && index != selection_) {
89 if (items_ && selection_ < itemCount_) {
90 return &items_[selection_];
100void ListView::navigate(
bool down) {
101 if (itemCount_ == 0)
return;
104 if (selection_ < itemCount_ - 1) {
112 if (selection_ > 0) {
116 selection_ = itemCount_ - 1;
123 LOG_D(
TAG,
"navigate: sel=%d, scroll=%d", selection_, scrollPos_);
130void ListView::ensureVisible() {
131 if (selection_ >= scrollPos_ + visibleItems_) {
132 scrollPos_ = selection_ - visibleItems_ + 1;
134 if (selection_ < scrollPos_) {
135 scrollPos_ = selection_;
162 void* userData =
nullptr;
167 if (onSelect_ && items_ && selection_ < itemCount_) {
169 userData = items_[selection_].userData;
174 onSelect_(sel, userData);
184 void* userData =
nullptr;
185 uint16_t sel = 0xFFFF;
188 if (items_ && selection_ < itemCount_) {
190 userData = items_[selection_].userData;
193 onMenu_(sel, userData);
226 return ui::tr(
"core.hint_ok_back");
238 auto* gfx =
static_cast<Gdey029T94*
>(
display->getNativeHandle());
245 const uint16_t width =
display->getWidth();
246 const uint16_t height =
display->getHeight();
249 gfx->fillScreen(EPD_WHITE);
252 gfx->setFont(
nullptr);
253 gfx->setTextColor(EPD_BLACK);
255 gfx->setTextWrap(
false);
262 for (uint8_t i = 0; i < visibleItems_; i++) {
263 uint16_t itemIndex = scrollPos_ + i;
265 drawRow(gfx, itemIndex, y, rowWidth);
269 if (itemCount_ == 0 && emptyText_) {
272 gfx->setTextColor(EPD_BLACK);
274 gfx->getTextBounds(emptyText_, 0, 0, &x1, &y1, &w, &h);
275 int x = (width -
static_cast<int>(w)) / 2;
276 int y =
LIST_START_Y + (visibleItems_ * itemHeight_) / 2 - h / 2;
277 gfx->setCursor(x < 0 ? 0 : x, y);
282 if (itemCount_ > visibleItems_) {
284 int listHeight = visibleItems_ * itemHeight_;
286 itemCount_, visibleItems_, scrollPos_);
290 char positionStr[16];
291 const char* prefix =
nullptr;
292 if (itemCount_ > 0) {
293 snprintf(positionStr,
sizeof(positionStr),
"%u/%u ", selection_ + 1, itemCount_);
294 prefix = positionStr;
310void ListView::drawRow(Gdey029T94* gfx, uint16_t itemIndex,
int y,
int rowWidth) {
311 gfx->setFont(
nullptr);
313 gfx->setTextWrap(
false);
316 gfx->fillRect(0, y, rowWidth, itemHeight_, EPD_WHITE);
318 if (itemIndex >= itemCount_)
return;
320 const ListItem& item = items_[itemIndex];
321 bool isSelected = (itemIndex == selection_);
324 gfx->fillRect(2, y + 1, rowWidth - 4, itemHeight_ - 2, EPD_BLACK);
325 gfx->setTextColor(EPD_WHITE);
327 gfx->setTextColor(EPD_BLACK);
330 bool handled =
false;
332 handled = itemRenderer_(gfx, item, itemIndex,
333 0, y, rowWidth, itemHeight_,
334 isSelected, itemRendererCtx_);
340 char iconStr[2] = {
static_cast<char>(item.
icon),
'\0'};
341 gfx->setCursor(textX, y + 4);
344 uint16_t color = isSelected ? EPD_WHITE : EPD_BLACK;
345 gfx->drawLine(textX, y + 10, textX + 6, y + 10, color);
349 uint16_t bullet_color = isSelected ? EPD_WHITE : EPD_BLACK;
350 gfx->fillCircle(textX + 2, y + itemHeight_ / 2, 2, bullet_color);
354 gfx->setCursor(textX, y + 4);
372 if (!items_ || index >= itemCount_)
return;
391 if (!items_ || itemCount_ >=
MAX_ITEMS)
return;
392 if (index > itemCount_) index = itemCount_;
393 uint16_t oldCount = itemCount_;
397 if (oldCount > 0 && index <= selection_ && selection_ + 1 < itemCount_) {
411 if (!items_ || itemCount_ == 0 || index >= itemCount_)
return;
413 if (selection_ > index) {
416 if (selection_ >= itemCount_) {
417 selection_ = itemCount_ > 0 ? itemCount_ - 1 : 0;
Internationalization with English fallbacks in code and overlay translations loaded at runtime from a...
constexpr int SCROLL_INDICATOR_WIDTH
Scroll indicator column width in pixels.
static constexpr uint8_t VISIBLE_ITEMS
Visible item count derived from available list area.
static constexpr int LIST_START_Y
static constexpr int ITEM_PADDING_X
static constexpr int TITLE_Y
Display layout constants.
Shared RAII wrappers for firmware resources.
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_D(tag, fmt,...)
Scoped guard for a FreeRTOS recursive mutex.
void repaintPartial()
Requests a redraw; the actual repaint happens once per render cycle.
const char * getFooterHint() const override
Returns footer hint text for this list.
void(*)(uint16_t index, void *userData) SelectCallback
const ListItem * getSelectedItem() const
Returns the currently selected item.
static constexpr uint16_t MAX_ITEMS
InputResult onKey(char key) override
Handles key input for list navigation and actions.
void insertItem(uint16_t index)
Reflects a caller-side insertion at index and marks dirty.
void setSelection(uint16_t index)
Sets the selected item index.
void render(bool partial) override
Renders list rows, selection, scroll indicators, and footer.
InputResult onLongPress(char key) override
void init(const char *title, const ListItem *items, uint16_t count)
Initializes list data and selection state.
void removeItem(uint16_t index)
Reflects a caller-side removal at index and marks dirty.
void updateItem(uint16_t index)
Marks the list dirty after the caller updated a backing item.
void markDirty() override
const char * customFooter_
static ViewStack & instance()
Returns singleton view-stack instance.
void push(IView *view, void *context=nullptr)
IDisplay * getDisplayInstance()
Returns lazily created singleton display instance.
constexpr int SCROLL_INDICATOR_WIDTH
Scroll indicator column width in pixels.
void drawFooterBar(Gdey029T94 *gfx, uint16_t width, uint16_t height, const char *prefix, const char *hint, bool force=false)
Draws footer bar with optional prefix and hint text.
void drawHeaderLeft(Gdey029T94 *gfx, const char *title, int x, int y, uint16_t width, int underlineOffset=18)
void printTruncated(Gdey029T94 *gfx, const char *text, int maxWidthPx)
Print text at the current cursor, truncated with an ellipsis to fit maxWidthPx. Caller must have alre...
void printText(Gdey029T94 *gfx, const char *text)
Draws CP437 text with the built-in 6x8 glyph font, byte-for-byte.
void drawScrollIndicator(Gdey029T94 *gfx, int x, int y, int listHeight, uint16_t totalItems, uint16_t visibleItems, uint16_t scrollPos)
Draws scroll arrows and scrollbar thumb.
Centralized key-code constants for cdc_views.
const char * tr(const char *key)
Look up a translation by string key.
static ListView s_sharedListView
Convenience factory/helper function.
static constexpr char KEY_MENU
Open context menu / digit '3'.
static constexpr char KEY_DOWN
Move selection down (numeric '8').
static constexpr char KEY_NO
Cancel / Back / Backspace.
static constexpr int TITLE_Y
Layout constants mirror the ones used by T9InputView.
ListView * showListView(const char *title, const ListItem *items, uint16_t count, ListView::SelectCallback onSelect, const char *hint=nullptr)
Shows a shared list view instance with selection callback.
static constexpr char KEY_UP
Move selection up (numeric '2').
static constexpr char KEY_YES
Confirm / OK / Save.