mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 22:57:50 +03:00
79 lines
2.7 KiB
C++
79 lines
2.7 KiB
C++
#pragma once
|
|
#include <freertos/FreeRTOS.h>
|
|
#include <freertos/semphr.h>
|
|
#include <freertos/task.h>
|
|
|
|
#include <functional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "Activity.h"
|
|
|
|
/**
|
|
* ListSelectionActivity is a reusable base class for activities that display
|
|
* a scrollable list of items with selection capabilities.
|
|
*
|
|
* Features:
|
|
* - Automatic pagination based on screen size
|
|
* - Page skipping when holding navigation buttons
|
|
* - Configurable title, empty message, and button labels
|
|
*/
|
|
class ListSelectionActivity : public Activity {
|
|
protected:
|
|
TaskHandle_t displayTaskHandle = nullptr;
|
|
SemaphoreHandle_t renderingMutex = nullptr;
|
|
size_t selectorIndex = 0;
|
|
bool updateRequired = false;
|
|
unsigned long enterTime = 0;
|
|
|
|
// Configuration
|
|
std::string title;
|
|
std::string emptyMessage;
|
|
std::string backLabel;
|
|
std::string confirmLabel;
|
|
std::function<size_t()> getItemCount;
|
|
std::function<std::string(size_t)> getItemText;
|
|
std::function<void(size_t)> onItemSelected;
|
|
std::function<void()> onBack;
|
|
|
|
// Constants
|
|
static constexpr int SKIP_PAGE_MS = 700;
|
|
static constexpr unsigned long IGNORE_INPUT_MS = 300;
|
|
static constexpr int LINE_HEIGHT = 30;
|
|
static constexpr int START_Y = 60;
|
|
static constexpr int BOTTOM_BAR_HEIGHT = 60;
|
|
|
|
static void taskTrampoline(void* param);
|
|
[[noreturn]] void displayTaskLoop();
|
|
void render() const;
|
|
int getPageItems() const;
|
|
virtual void loadItems() {} // Override to load items on enter
|
|
|
|
public:
|
|
explicit ListSelectionActivity(const std::string& activityName, GfxRenderer& renderer,
|
|
MappedInputManager& mappedInput, const std::string& title,
|
|
std::function<size_t()> getItemCount, std::function<std::string(size_t)> getItemText,
|
|
std::function<void(size_t)> onItemSelected, std::function<void()> onBack,
|
|
const std::string& emptyMessage = "No items available",
|
|
const std::string& backLabel = "« Back", const std::string& confirmLabel = "Select")
|
|
: Activity(activityName, renderer, mappedInput),
|
|
title(title),
|
|
emptyMessage(emptyMessage),
|
|
backLabel(backLabel),
|
|
confirmLabel(confirmLabel),
|
|
getItemCount(getItemCount),
|
|
getItemText(getItemText),
|
|
onItemSelected(onItemSelected),
|
|
onBack(onBack) {}
|
|
|
|
virtual ~ListSelectionActivity() = default;
|
|
|
|
void onEnter() override;
|
|
void onExit() override;
|
|
void loop() override;
|
|
|
|
// Allow subclasses to set initial selection
|
|
void setInitialSelection(size_t index) { selectorIndex = index; }
|
|
size_t getCurrentSelection() const { return selectorIndex; }
|
|
};
|