newtx/ui/dev_menu.h

146 lines
4.0 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
2024-02-05 09:57:39 +00:00
#define MENU_CMD_HANDLER_RET bool
2024-02-02 08:53:17 +00:00
#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;
2024-02-04 02:30:09 +00:00
int sel_ = -1;
bool check_item_ = false;
bool need_ret_parent_ = true;
2024-02-02 08:53:17 +00:00
int find_item(const char* text);
public:
2024-02-04 02:30:09 +00:00
dev_menu(bool check_item = false, bool need_ret_parent = true);
2024-02-02 08:53:17 +00:00
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);
2024-02-04 02:30:09 +00:00
void set_need_return_parent(bool need);
2024-02-02 08:53:17 +00:00
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
//
2024-02-04 02:30:09 +00:00
// sel - to receive current setting index
//
2024-02-02 08:53:17 +00:00
// Return: current menu index
2024-02-04 02:30:09 +00:00
int get_menu_text(std::vector<std::string>& text, int& sel);
2024-02-02 08:53:17 +00:00
};
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;
2024-02-05 09:57:39 +00:00
volatile bool ready_enable_ = true;
bool scanning_ = false;
int paper_total_ = 0;
int paper_cnt_ = 0;
2024-02-02 08:53:17 +00:00
SIZE font_size_ = {16, 16};
POINT hold_pos_ = {0, 0};
uint32_t his_cnt_;
uint32_t rol_cnt_;
2024-02-02 08:53:17 +00:00
std::map<int, MENU_CMD_CALLBACK> handler_;
std::unique_ptr<Lcd> lcd_;
std::unique_ptr<KeyMonitor> keyboard_;
2024-02-05 09:57:39 +00:00
bool do_menu_command(int cmd); // return whether should hold UI ?
2024-02-02 08:53:17 +00:00
void init(void);
void clear(void);
void refresh_lcd(bool cur_at_top);
void move_to(bool next);
void enter(void);
typedef struct _disp_data
{
uint8_t x;
uint8_t y;
uint8_t cnt; // clear width when ptr[0] == nullptr
uint8_t mask; // clear height when ptr[0] == nullptr
2024-02-02 08:53:17 +00:00
uint8_t *ptr[16];
}DISPDATA;
2024-02-05 09:57:39 +00:00
MUTEX ready_lck_;
chronograph ready_watch_;
DISPDATA ready_;
safe_fifo<DISPDATA> disp_data_;
safe_thread disp_thrd_;
void thread_test_hold_ui(void);
2024-02-02 08:53:17 +00:00
void thread_display(void);
2024-02-05 09:57:39 +00:00
void display_ready(void);
void set_ready_status_enabled(bool enable);
void reset_ready_watch(void);
int get_ready_watch_ms(void);
2024-02-02 08:53:17 +00:00
public:
ui_mgr();
protected:
virtual ~ui_mgr();
public:
void key_event(int key);
};