newtx/ui/dev_menu.h

125 lines
3.1 KiB
C
Raw Normal View History

2024-02-02 08:53:17 +00:00
// device liquid crystal display menu
//
// Date: 2024-01-31
//
// Keyboard layout: Four buttons
//
// Enter - to access current selection
//
// Up - to select previous item
//
// Down - to select next item
//
// Stop - to stop scanning right now
#pragma once
#include <base/utils.h>
#include <functional>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <thread>
#define MENU_ID_RETURN -1 // ID of menu item that return to parent
#define LINK_DEFINE(x, y) x##y
#define MEMNU_CMD_HANDLER_PARAM dev_menu* menu, int id
#define MENU_CMD_HANDLER_RET void
#define MENU_CMD_CALLBACK std::function<MENU_CMD_HANDLER_RET(MEMNU_CMD_HANDLER_PARAM)>
class dev_menu : public refer
{
dev_menu* parent_ = nullptr;
typedef struct _menu_item
{
std::string text;
bool leaf;
union
{
int id; // valid on leaf
dev_menu *child; // valid on !leaf
};
}MITEM;
std::vector<MITEM> items_;
int cur_ = 0;
int find_item(const char* text);
public:
dev_menu();
protected:
virtual ~dev_menu();
void set_parent(dev_menu* parent);
public:
bool add_menu(const char* text, int id);
bool add_menu(const char* text, dev_menu* submenu);
bool remove_menu(const char* text);
bool move_to(bool next); // true - move to next, false - move to previous. if at end position of move direction, return false
bool select(const char* txt);
void reset_pos(void);
// Function: access current menu
//
// Parameter: id - to receive ID of current menu item if leaf, fill '-1' if a submenu
//
// Return: current menu, user should call 'release' after use
dev_menu* enter(int* id);
// Function: get all menus text
//
// Parameter: text - to receive the menu text
//
// Return: current menu index
int get_menu_text(std::vector<std::string>& text);
};
class KeyMonitor;
class Lcd;
class ui_mgr : public refer
{
dev_menu* root_ = nullptr;
dev_menu* cur_ = nullptr;
volatile bool menu_mode_ = false; // whether LCD is displaying menu
volatile bool run_ = true;
SIZE font_size_ = {16, 16};
std::map<int, MENU_CMD_CALLBACK> handler_;
std::unique_ptr<Lcd> lcd_;
std::unique_ptr<KeyMonitor> keyboard_;
void do_menu_command(int cmd);
void init(void);
void clear(void);
void refresh_lcd(bool cur_at_top);
void move_to(bool next);
void enter(void);
int get_string_font(const char* text, uint8_t** ptr);
typedef struct _disp_data
{
uint8_t x;
uint8_t y;
uint8_t rows;
uint8_t cols;
uint8_t cnt; // 0 to clear
uint8_t mask;
uint8_t *ptr[16];
}DISPDATA;
safe_fifo<DISPDATA> disp_data_;
std::unique_ptr<std::thread> disp_thrd_;
void thread_display(void);
public:
ui_mgr();
protected:
virtual ~ui_mgr();
public:
void key_event(int key);
};