newtx/ui/dev_menu.cpp

1417 lines
46 KiB
C++

#include "dev_menu.h"
#include <string.h>
// #include "Displaydef.h"
#include <base/words.h>
#include <sane/sane_name.h>
#include <base/ui.h>
#include "keymonitor.h"
#include "Lcd.h"
#include "font.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// dev_menu
dev_menu::dev_menu(bool check_item
, bool need_ret_parent)
: check_item_(check_item)
, need_ret_parent_(need_ret_parent)
{}
dev_menu::~dev_menu()
{
set_parent(nullptr);
for(auto& v: items_)
{
if(!v.leaf)
{
v.child->set_parent(nullptr);
v.child->release();
}
}
items_.clear();
}
int dev_menu::find_item(const char* text)
{
int ind = -1;
for(size_t i = 0; i < items_.size(); ++i)
{
if(items_[i].text == text)
{
ind = i;
break;
}
}
return ind;
}
void dev_menu::set_parent(dev_menu* parent)
{
if(parent_)
{
parent_->release();
if(items_.size() && items_[0].id == MENU_ID_RETURN)
items_.erase(items_.begin());
}
parent_ = parent;
if(parent_)
{
parent_->add_ref();
if(need_ret_parent_)
{
if(!items_.size() || items_[0].id != MENU_ID_RETURN)
{
MITEM mi;
mi.text = WORDS_MENU_RETURN;
mi.leaf = true;
mi.id = MENU_ID_RETURN;
items_.insert(items_.begin(), mi);
if(sel_ != -1)
sel_++;
}
}
}
}
bool dev_menu::add_menu(const char* text, int id, int pos)
{
int ind = find_item(text);
if(ind != -1)
return false;
MITEM mi;
mi.id = id;
mi.leaf = true;
mi.text = text;
if(pos < 0 || pos >= items_.size())
items_.push_back(mi);
else
items_.insert(items_.begin() + pos, mi);
return true;
}
bool dev_menu::add_menu(const char* text, dev_menu* submenu, int pos)
{
int ind = find_item(text);
if(ind != -1 || !submenu)
return false;
MITEM mi;
mi.child = submenu;
mi.leaf = false;
mi.text = text;
if(pos < 0 || pos >= items_.size())
items_.push_back(mi);
else
items_.insert(items_.begin() + pos, mi);
submenu->add_ref();
submenu->set_parent(this);
return true;
}
bool dev_menu::remove_menu(const char* text)
{
int ind = find_item(text);
if(ind == -1)
return false;
if(!items_[ind].leaf)
items_[ind].child->release();
items_.erase(items_.begin() + ind);
if(cur_ >= items_.size())
cur_ = items_.size() - 1;
return true;
}
bool dev_menu::move_to(bool next)
{
bool ret = false;
if(next)
{
if(cur_ < (int)items_.size() - 1)
{
cur_++;
ret = true;
}
}
else
{
if(cur_ > 0)
{
cur_--;
ret = true;
}
}
return ret;
}
bool dev_menu::select(const char* txt, bool apply_cur)
{
int ind = find_item(txt);
if(ind == -1)
return false;
sel_ = ind;
if(apply_cur)
cur_ = sel_;
return true;
}
void dev_menu::reset_pos(void)
{
if(reset_pos_)
reset_pos_(this);
else
cur_ = sel_ == -1 ? init_pos_ : sel_;
}
void dev_menu::set_default_pos(int pos)
{
init_pos_ = pos;
}
void dev_menu::set_default_pos(std::function<void(dev_menu*)> f)
{
reset_pos_ = f;
}
void dev_menu::clear(std::function<void(const char*)> erase_func)
{
for(auto& v: items_)
{
if(v.leaf)
{
if(erase_func)
erase_func(v.text.c_str());
}
else
{
v.child->clear(erase_func);
v.child->release();
}
}
items_.clear();
}
int dev_menu::count(void)
{
return items_.size();
}
std::string& dev_menu::name(void)
{
return name_;
}
dev_menu* dev_menu::get_sub_menu(const char* text)
{
dev_menu* sub = nullptr;
for(auto& v: items_)
{
if(v.text == text)
{
if(!v.leaf)
{
sub = v.child;
sub->add_ref();
}
break;
}
}
return sub;
}
dev_menu* dev_menu::get_sub_menu(int index, std::string* title)
{
dev_menu* sub = nullptr;
if(title)
*title = "";
if(index >= 0 && index < items_.size())
{
if(!items_[index].leaf)
{
sub = items_[index].child;
sub->add_ref();
}
if(title)
*title = items_[index].text;
}
return sub;
}
dev_menu* dev_menu::enter(int* id, std::string* text)
{
dev_menu *menu = this;
if(id)
*id = -1;
if(text)
*text = "";
if(cur_ >= 0 && cur_ < items_.size())
{
if(items_[cur_].leaf)
{
if(items_[cur_].id == MENU_ID_RETURN)
{
if(parent_)
menu = parent_;
}
else
{
if(id)
*id = items_[cur_].id;
if(text)
*text = items_[cur_].text;
if(check_item_)
sel_ = cur_;
}
}
else
{
menu = items_[cur_].child;
menu->reset_pos();
}
}
menu->add_ref();
return menu;
}
int dev_menu::get_menu_text(std::vector<std::string>& text, int& sel)
{
for(auto& v: items_)
text.push_back(v.text);
sel = sel_;
return cur_;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ui_mgr
namespace menu_command
{
enum
{
MENU_CMD_ID_CANCEL = 0,
MENU_CMD_ID_SEPARATE_LOW = 0x10,
MENU_CMD_ID_SEPARATE_MID,
MENU_CMD_ID_SEPARATE_HIGH,
MENU_CMD_ID_SLEEP_NEVER = 0x20,
MENU_CMD_ID_SLEEP_IMMEDIATELY,
MENU_CMD_ID_SLEEP_5MIN,
MENU_CMD_ID_SLEEP_10MIN,
MENU_CMD_ID_SLEEP_20MIN,
MENU_CMD_ID_SLEEP_30MIN,
MENU_CMD_ID_SLEEP_1H,
MENU_CMD_ID_SLEEP_2H,
MENU_CMD_ID_SLEEP_4H,
MENU_CMD_ID_LIFTER_LOW = 0x30,
MENU_CMD_ID_LIFTER_MID,
MENU_CMD_ID_LIFTER_HIGH,
MENU_CMD_ID_COUNT_MODE = 0x40,
MENU_CMD_ID_HANDLE_MODE = 0x50,
MENU_CMD_ID_CLEAR_PASSWAY = 0x60,
MENU_CMD_ID_GET_HISTORY_COUNT = 0x70,
MENU_CMD_ID_CLEAR_ROLLER_CNT = 0x80,
MENU_CMD_ID_GET_ROLLER_COUNT,
MENU_CMD_ID_SHUTDOWN = 0x90,
MENU_CMD_ID_WELCOME = 0xa0,
MENU_CMD_ID_SEQ_0 = 0x1000,
MENU_CMD_ID_SEQ_LAST = 0x7FFF,
};
static std::string command_string(int cmd)
{
RETURN_ENUM_STR(cmd, MENU_CMD_ID_CANCEL);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SEPARATE_LOW);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SEPARATE_MID);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SEPARATE_HIGH);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_NEVER);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_IMMEDIATELY);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_5MIN);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_10MIN);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_20MIN);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_30MIN);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_1H);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_2H);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SLEEP_4H);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_LIFTER_LOW);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_LIFTER_MID);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_LIFTER_HIGH);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_COUNT_MODE);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_HANDLE_MODE);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_CLEAR_PASSWAY);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_GET_HISTORY_COUNT);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_CLEAR_ROLLER_CNT);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_GET_ROLLER_COUNT);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_SHUTDOWN);
RETURN_ENUM_STR(cmd, MENU_CMD_ID_WELCOME);
char unk[40] = {0};
sprintf(unk, "Unknown menu command: %d", cmd);
return unk;
}
};
namespace welcome
{
static uint8_t ddjx[] = {128, 32
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0xC0, 0x80, 0x00, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xC0, 0x80, 0x80
, 0x80, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x40, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x02, 0x00, 0x00, 0x00, 0x04, 0x04
, 0x04, 0x04, 0x04, 0x08, 0x08, 0x88, 0x88, 0x08, 0x00, 0x00, 0x00, 0x10, 0xB0, 0x36, 0x66, 0xFF
, 0xFE, 0xF6, 0xE0, 0x80, 0x00, 0xC0, 0xE0, 0xF0, 0xD8, 0xDC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF4
, 0xFC, 0xFC, 0xF8, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0x60, 0x20, 0x20, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x3F, 0x7F, 0x27, 0x3E, 0x1F, 0x1E, 0x36, 0x00, 0x08, 0x0C
, 0x17, 0x7F, 0x3F, 0x1D, 0x3F, 0x63, 0x3E, 0x0C, 0x00, 0x00, 0x23, 0x3D, 0x1F, 0x7F, 0x5F, 0x15
, 0x30, 0x20, 0x00, 0x00, 0x16, 0x3F, 0x39, 0x1A, 0x1E, 0x0F, 0x1B, 0x18, 0x00, 0x00, 0x00, 0x0F
, 0x03, 0x7F, 0x7F, 0x7F, 0x7F, 0x13, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x08, 0x08, 0x08, 0x09, 0x0B, 0x03, 0x07, 0x17, 0x1F, 0x0F, 0x0F, 0x1F, 0x0B, 0x13
, 0x17, 0x17, 0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x1F, 0x0F, 0x0F, 0x0F, 0x17, 0x0F, 0x0F, 0x0F, 0x1F
, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x05, 0x05, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t mugui[] = {128, 32
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0
, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x18, 0x1C, 0x1C, 0x70, 0xE0, 0x80, 0x80, 0x90, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8
, 0xF0, 0xB0, 0x90, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x7C, 0xFC, 0xE4, 0x06, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF
, 0xFD, 0xFD, 0x6D, 0xEC, 0xEC, 0xFC, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8
, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8, 0xF8, 0xF0
, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0xBF, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
, 0xFF, 0x1D, 0x1D, 0x1D, 0x1F, 0x0F, 0x0E, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0
, 0xC0, 0xC0, 0xC0, 0xD8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x81, 0xDF, 0xFF, 0xFF, 0xFF
, 0xEF, 0xE0, 0xFE, 0xFF, 0xFC, 0xFF, 0xFE, 0xE8, 0xC0, 0xC0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0xC0
, 0xC0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF
, 0xFF, 0xFF, 0x9F, 0xBF, 0xBF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x9F, 0x07
, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x0C, 0x08, 0x08, 0x0C, 0x08
, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x06, 0x03, 0x03, 0x07, 0x0F, 0x0F, 0x87, 0xFF, 0xFF, 0xFF, 0xFF
, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0xFA, 0xFC, 0xFC, 0xFE, 0xFC, 0xF0, 0xF0, 0xFA, 0xFE, 0xFC, 0xF3, 0xF3, 0xF3, 0xF3, 0xF0, 0xF3
, 0xF3, 0xF7, 0xF3, 0xF3, 0xF0, 0xF0, 0xF8, 0xF1, 0xF1, 0xFD, 0xFE, 0xFF, 0xF7, 0xFB, 0xFF, 0xEF
, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xF8, 0xF8, 0xF8, 0xF0, 0xFC, 0xF8, 0xFA, 0xF8, 0xF8, 0xF8, 0xF8
, 0xF8, 0xF8, 0xF9, 0xF9, 0xFF, 0xFD, 0xFD, 0xFD, 0xF1, 0xF0, 0xF3, 0xF1, 0xFF, 0xFF, 0xFF, 0xF1
, 0xF7, 0xFF, 0xFF, 0xFD, 0xF1, 0xF0, 0xF0, 0xD7, 0xFF, 0xF7, 0xF9, 0xFF, 0xFF, 0xFF, 0xF1, 0xF3
, 0xE7, 0xEF, 0xFF, 0xF9, 0xF1, 0xF1, 0xE3, 0xF3, 0xF3, 0xE2, 0xE2, 0xE2, 0xA2, 0xC2, 0xC2, 0xC3
, 0xC3, 0xE3, 0xC7, 0x9F, 0x13, 0x8F, 0x9F, 0x1F, 0x87, 0xCB, 0xF3, 0xC7, 0xDF, 0xDF, 0xFF, 0xDF
, 0xFF, 0xA2, 0xE2, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x86, 0xC4, 0xC4, 0x8C, 0x0C, 0x8C
};
static uint8_t qiaoting[] = {128, 32
, 0x1C, 0x7F, 0xE7, 0x7E, 0x0F, 0x0B, 0x0C, 0xFF, 0xFF, 0x3F, 0x03, 0x03, 0x02, 0x02, 0x00, 0x07
, 0xD8, 0x88, 0x08, 0x0C, 0x0E, 0x0C, 0x18, 0x30, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xFC, 0xFC, 0xE0, 0xC0, 0xC0, 0x80, 0x80, 0x80
, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xF0, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x7C, 0x3E, 0x00, 0x00, 0x40, 0x70, 0xFC, 0x3F, 0xFC, 0x78, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x03, 0x06, 0x0C, 0x98, 0x00, 0x80
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x10, 0x31, 0x31, 0xF9, 0xF9, 0x7F, 0xFF, 0xFF, 0x7D, 0xFD, 0xFF, 0x7F, 0x7F, 0xF9, 0xF9, 0x31
, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x80, 0x80, 0x80, 0x8E, 0x9F, 0x1F, 0x3F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xFC
, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0x80, 0x80, 0x80, 0x80, 0x00, 0xE0, 0xE0, 0xC0
, 0x38, 0x3C, 0x18, 0x08, 0x0C, 0x18, 0x1D, 0x1C, 0x18, 0x3C, 0x38, 0x7C, 0x78, 0x78, 0xFC, 0x78
, 0x7C, 0xFC, 0xF8, 0xFC, 0x7C, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xCF
, 0x7F, 0x7F, 0xFF, 0xFF, 0xCF, 0xFF, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xFC, 0xF8, 0xF8, 0xFC, 0xF8
, 0xFC, 0xF8, 0xF8, 0xFC, 0x78, 0xF8, 0xFC, 0xF8, 0xFC, 0xF8, 0xFC, 0xF8, 0x78, 0xFC, 0xF8, 0xF8
, 0xFC, 0xF8, 0xF8, 0xFF, 0xF8, 0x78, 0xF8, 0xFF, 0x78, 0x78, 0xFF, 0xF8, 0x78, 0xF8, 0xFF, 0x78
, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF
, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
, 0x03, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x03, 0x01, 0x07, 0x01, 0x03, 0x07, 0x03, 0x07
, 0x07, 0x05, 0x07, 0x03, 0x03, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x60, 0x20, 0x60, 0x7F, 0x70, 0xF0, 0xFB, 0xBF, 0xB0, 0xF0, 0xBF, 0xF0, 0xF0, 0x70, 0x7F, 0x60
, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x1F, 0x1F, 0x1F, 0x1F
, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F
, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0x7E
};
static uint8_t* pics[] = {ddjx, mugui, qiaoting};
static int index_ = -1;
static uint8_t* get_current_pic(void)
{
if(index_ == -1)
{
srand(time(nullptr));
index_ = rand() % _countof(pics);
}
uint8_t* cur = pics[index_++];
index_ %= _countof(pics);
return cur;
}
};
// #define TEST_PLATFORM_EVENT
#ifdef TEST_PLATFORM_EVENT
platform_event to__("to");
#endif
ui_mgr::ui_mgr() : disp_data_("lcd-msg")
{
utils::init_log(LOG_TYPE_FILE);
perm_data_.reset(new permanent_data());
disp_data_.enable_wait_log(false);
init();
auto ke = [this](int key) -> MENU_CMD_HANDLER_RET
{
key_event(key);
};
lcd_.reset(new Lcd());
lcd_->Lcd_Initial_Lcd(false);
lcd_->clear();
ready_.cnt = custom_font::get_string_font(WORDS_STATUS_READY, ready_.ptr, custom_font::FONT_SIZE_32);
ready_.x = (Lcd::LCD_WIDTH - ready_.ptr[0][0] * ready_.cnt - 8) / 2;
ready_.y = (Lcd::LCD_HEIGHT - ready_.ptr[0][1]) / 2;
ready_.mask = 0;
keyboard_.reset(new KeyMonitor(ke));
auto display = [this](void*) -> void
{
#ifdef TEST_PLATFORM_EVENT
printf("\tdisplay thread starting, sleep 3000ms ...\n");
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
printf("\tdisplay thread trigger event ...\n");
to__.trigger();
#endif
thread_display();
};
#ifdef TEST_PLATFORM_EVENT
to__.enable_log(false);
#endif
disp_thrd_.start(display, nullptr, SIZE_MB(4), "thread_display");
#ifdef TEST_PLATFORM_EVENT
// display thread starting, sleep 3000ms ...
// [2024-02-18 08:01:54.349173] try wait 001: Failure
// [2024-02-18 08:01:54.849311] try wait 002: Failure
// [2024-02-18 08:01:55.349411] try wait 003: Failure
// [2024-02-18 08:01:55.849550] try wait 004: Failure
// [2024-02-18 08:01:56.349645] try wait 005: Failure
// display thread trigger event ...
// [2024-02-18 08:01:56.849441] try wait 006: OK
// [2024-02-18 08:01:57.349550] try wait 007: Failure
// [2024-02-18 08:01:57.849659] try wait 008: Failure
int up = 10000;
for(int i = 0; i < up; ++i)
{
bool wait = to__.wait(500);
printf("[%s] try wait %03d: %s\n", utils::format_current_time().c_str(), i + 1, wait ? "OK" : "Failure");
if(wait)
up = i + 3;
}
#endif
auto statu = [this](devui::LPMSGSTREAM pack) -> void
{
utils::log_mem_info("status message", pack, pack->whole_size());
if(pack->msg == devui::UI_STATUS_PEER_CONNECTED)
{
send_paper_count();
}
else if(pack->msg == devui::UI_STATUS_SCANNING)
{
devui::LPSCANSTREAM scan = (devui::LPSCANSTREAM)pack->data;
scanning_ = scan->mode != devui::SCAN_STOPPED;
set_ready_status_enabled(!scanning_ && (scan->err == 0 || stopped_by_ui_));
if(scanning_)
{
paper_cnt_ = 0;
if(scan->mode == devui::SCAN_PAUSED)
{
perm_data_->save();
if(scan->err)
{
devui::STATMSG msg;
msg.align_h = msg.align_v = devui::ALIGN_COMPONENT_MID;
msg.clear = devui::CLEAR_ALL;
msg.font = 16;
msg.msg_words_id = scan->err;
msg.reserved = 0;
display_status(&msg);
}
}
else
{
scan_mode_ = scan->mode;
display_scan_title();
perm_data_->set_speed(scan->speed);
paper_total_ = 0;
send_paper_count();
}
}
else
{
perm_data_->save();
send_paper_count();
if(scan->err)
{
devui::STATMSG msg;
msg.align_h = msg.align_v = devui::ALIGN_COMPONENT_MID;
msg.clear = devui::CLEAR_ALL;
msg.font = 16;
msg.msg_words_id = scan->err;
msg.reserved = 0;
if(!display_status(&msg))
set_ready_status_enabled(true);
}
}
}
else if(pack->msg == devui::UI_STATUS_PAPER_CNT)
{
if(int_by_status_)
display_scan_title();
DISPDATA dd;
char num[40] = {0};
int cnt = 0;
paper_cnt_++;
paper_total_++;
perm_data_->increase_count(*(uint32_t*)pack->data);
sprintf(num, "%03d", paper_cnt_);
dd.x = hold_pos_.x;
dd.y = hold_pos_.y;
dd.method = DISP_METHOD_PART_LINE;
dd.mask = 0;
dd.cnt = custom_font::get_string_font(num, dd.ptr);
cnt = disp_data_.save(dd, true);
sprintf(num, "%s%d", WORDS_STATUS_TOTAL, paper_total_);
dd.y += Lcd::LCD_LINE_PER_PAGE;
dd.x = Lcd::LCD_WIDTH;
dd.cnt = custom_font::get_string_font(num, dd.ptr, custom_font::FONT_SIZE_8);
for(int i = 0; i < dd.cnt; ++i)
dd.x -= dd.ptr[i][0] + 1;
cnt = disp_data_.save(dd, true);
}
else if(pack->msg == devui::UI_STATUS_MESSAGE)
{
int_by_status_ = true;
display_status(pack->data);
peer_connected_ = true;
if(((devui::LPSTATMSG)pack->data)->msg_words_id == ID_WORDS_STATUS_SCANNER_CONN + 1)
set_ready_status_enabled(true);
}
else if(pack->msg == devui::UI_STATUS_READY)
{
set_ready_status_enabled(true);
}
else if(pack->msg == devui::UI_CMD_ADD_MENU)
{
add_menu((devui::LPOPTMENU)pack->data);
}
else if(pack->msg == devui::UI_CMD_SET_OPTION_VALUE)
{
char *name = (char*)pack->data;
for(int i = 0; i < root_->count(); ++i)
{
dev_menu* m = root_->get_sub_menu(i);
if(m)
{
bool over = false;
if(m->name() == name)
{
char* val = utils::next_string(name);
over = true;
m->select(val, true);
utils::to_log(LOG_LEVEL_DEBUG, "select menu '%s' to '%s'\n", name, val);
}
m->release();
if(over)
break;
}
}
}
else if(pack->msg == devui::UI_STATUS_PEER_CLOSED)
{
peer_connected_ = *(bool*)pack->data;
set_ready_status_enabled(peer_connected_);
devui::STATMSG msg;
msg.align_h = msg.align_v = devui::ALIGN_COMPONENT_MID;
msg.clear = devui::CLEAR_ALL;
msg.font = 16;
msg.msg_words_id = ID_WORDS_STATUS_SCANNER_CONN + peer_connected_;
msg.reserved = 0;
if(!display_status(&msg))
set_ready_status_enabled(true);
}
};
devui::init_ui(statu, true);
}
ui_mgr::~ui_mgr()
{
run_ = false;
menu_mode_ = false;
disp_data_.trigger();
devui::uninit_ui();
clear();
perm_data_.reset(nullptr);
utils::uninit();
}
void ui_mgr::add_menu(void* data)
{
devui::LPOPTMENU opt = (devui::LPOPTMENU)data;
char *title = opt->name + opt->title_off,
*val = utils::next_string(title);
dev_menu *menu = root_->get_sub_menu(title);
std::string cur("");
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
set_option_value(menu->name().c_str(), text, strlen(text));
return false;
};
root_->remove_menu(title);
if(menu)
{
auto ef = [this](const char* text) -> void
{
handler_s_.erase(text);
};
menu->clear(ef);
menu->release();
menu = nullptr;
}
else
{
handler_s_.erase(title);
}
menu = new dev_menu(true);
menu->name() = opt->name;
while(val)
{
if(opt->cur_sel-- == 0)
cur = val;
handler_s_[val] = f;
menu->add_menu(val, MENU_ID_BY_TEXT);
val = utils::next_string(val);
}
menu->select(cur.c_str(), true);
root_->add_menu(title, menu, opt->pos);
menu->release();
}
bool ui_mgr::do_menu_command(int cmd, const char* text)
{
bool holdui = false;
utils::to_log(LOG_LEVEL_DEBUG, "Do menu command: %s(%s - %s)\n", menu_command::command_string(cmd).c_str(), cur_->name().c_str(), text);
if(cmd >= menu_command::MENU_CMD_ID_SEQ_0 && cmd <= menu_command::MENU_CMD_ID_SEQ_LAST)
{
if(handler_.count(menu_command::MENU_CMD_ID_SEQ_0))
holdui = handler_[menu_command::MENU_CMD_ID_SEQ_0](cur_, cmd - menu_command::MENU_CMD_ID_SEQ_0, text);
}
else if(handler_.count(cmd))
holdui = handler_[cmd](cur_, cmd, text);
else if(text && *text && handler_s_.count(text))
holdui = handler_s_[text](cur_, cmd, text);
// at last, we return to main menu OR parent ?
if(holdui)
menu_mode_ = false;
else
{
cur_->release();
cur_ = root_; // main menu
cur_->add_ref();
}
return holdui;
}
bool ui_mgr::set_option_value(const char* name, const char* val, size_t size)
{
std::string str(name);
str.append(1, '\0');
str += std::string(val, size);
str.append(2, '\0');
return devui::send_message(devui::UI_CMD_SET_OPTION_VALUE, (uint8_t*)&str[0], str.length());
}
bool ui_mgr::send_paper_count(void)
{
std::string val(std::to_string(perm_data_->roller_count()));
set_option_value(SANE_OPT_NAME(ROLLER_COUNT), val.c_str(), val.length());
val = std::to_string(perm_data_->history_count());
return set_option_value(SANE_OPT_NAME(HISTORY_COUNT), val.c_str(), val.length());
}
void ui_mgr::init(void)
{
dev_menu *child = nullptr;
root_ = new dev_menu();
// 计数模式、手动模式、清理纸道、历史张数、滚轴张数、清除滚轴张数(确定,取消)、进入休眠、关机
root_->add_menu(WORDS_MENU_COUNT_MODE, menu_command::MENU_CMD_ID_COUNT_MODE);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
// 保持界面:第一行显示当前保持的功能
// 第二行显示当前功能的信息,过程中只更新该行
//
// 任意按键的反应:第一行显示“退出当前功能”
// 第二行显示“确定”、“取消”,菜单键在此两项中跳转
DISPDATA dd;
memset(&dd, 0, sizeof(dd));
dd.cnt = dd.mask = -1;
dd.method = DISP_METHOD_CLEAR;
disp_data_.save(dd, true);
dd.mask = 0;
dd.cnt = custom_font::get_string_font(WORDS_MENU_COUNT_MODE, dd.ptr);
dd.method = DISP_METHOD_WHOLE_LINE;
disp_data_.save(dd, true);
dd.y = dd.ptr[0][1];
dd.cnt = custom_font::get_string_font(WORDS_FUNCTION_COUNT, dd.ptr);
hold_pos_.x = dd.x;
for(int i = 0; i < dd.cnt; ++i)
hold_pos_.x += dd.ptr[i][0] + 1;
hold_pos_.y = dd.y;
hold_pos_.x += 2;
dd.method = DISP_METHOD_PART_LINE;
disp_data_.save(dd, true);
devui::send_message(devui::UI_CMD_COUNT_PAPER);
return true;
};
handler_[menu_command::MENU_CMD_ID_COUNT_MODE] = f;
}
root_->add_menu(WORDS_MENU_MANUAL_MODE, menu_command::MENU_CMD_ID_HANDLE_MODE);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
return true;
};
handler_[menu_command::MENU_CMD_ID_HANDLE_MODE] = f;
}
root_->add_menu(WORDS_MENU_CLEAR_PASSWAY, menu_command::MENU_CMD_ID_CLEAR_PASSWAY);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
devui::send_message(devui::UI_CMD_CLEAN_PASSWAY);
return false;
};
handler_[menu_command::MENU_CMD_ID_CLEAR_PASSWAY] = f;
}
root_->add_menu(WORDS_MENU_HISTORY_COUNT, menu_command::MENU_CMD_ID_GET_HISTORY_COUNT);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
DISPDATA dd;
memset(&dd, 0, sizeof(dd));
// dd.cnt = dd.mask = -1;
// disp_data_.save(dd, true);
dd.mask = 0;
dd.cnt = custom_font::get_string_font(WORDS_MENU_HISTORY_COUNT, dd.ptr);
dd.method = DISP_METHOD_WHOLE_LINE;
disp_data_.save(dd, true);
dd.y = dd.ptr[0][1];
dd.x = dd.ptr[0][0] * 2;
dd.cnt = custom_font::get_string_font(std::to_string(perm_data_->history_count()).c_str(), dd.ptr);
disp_data_.save(dd, true);
return true;
};
handler_[menu_command::MENU_CMD_ID_GET_HISTORY_COUNT] = f;
}
root_->add_menu(WORDS_MENU_ROLLER_COUNT, menu_command::MENU_CMD_ID_GET_ROLLER_COUNT);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
DISPDATA dd;
char cnt[40] = {0};
memset(&dd, 0, sizeof(dd));
// dd.cnt = dd.mask = -1;
// disp_data_.save(dd, true);
dd.mask = 0;
dd.cnt = custom_font::get_string_font(WORDS_MENU_ROLLER_COUNT, dd.ptr);
dd.method = DISP_METHOD_WHOLE_LINE;
disp_data_.save(dd, true);
dd.y = dd.ptr[0][1];
dd.x = dd.ptr[0][0] * 2;
sprintf(cnt, "%u", perm_data_->roller_count());
dd.cnt = custom_font::get_string_font(cnt, dd.ptr);
disp_data_.save(dd, true);
return true;
};
handler_[menu_command::MENU_CMD_ID_GET_ROLLER_COUNT] = f;
}
{
child = new dev_menu(false, false);
child->add_menu(WORDS_MENU_YES, menu_command::MENU_CMD_ID_CLEAR_ROLLER_CNT);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
std::string str("");
perm_data_->clear_roller_count();
utils::add_2_string_array(str, SANE_OPT_NAME(ROLLER_COUNT));
utils::add_2_string_array(str, "0");
devui::send_message(devui::UI_CMD_SET_OPTION_VALUE, (uint8_t*)&str[0], str.length());
return false;
};
handler_[menu_command::MENU_CMD_ID_CLEAR_ROLLER_CNT] = f;
}
child->add_menu(WORDS_MENU_NO, menu_command::MENU_CMD_ID_CANCEL);
child->set_default_pos(1);
root_->add_menu(WORDS_MENU_RESET_ROLLOER_CNT, child);
child->release();
}
// 升降台位置(低中高)
{
child = new dev_menu(true);
child->add_menu(WORDS_MENU_LOW, menu_command::MENU_CMD_ID_LIFTER_LOW);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
return false;
};
handler_[menu_command::MENU_CMD_ID_LIFTER_LOW] = f;
}
child->add_menu(WORDS_MENU_MID, menu_command::MENU_CMD_ID_LIFTER_MID);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
return false;
};
handler_[menu_command::MENU_CMD_ID_LIFTER_MID] = f;
}
child->add_menu(WORDS_MENU_HIGH, menu_command::MENU_CMD_ID_LIFTER_HIGH);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
return false;
};
handler_[menu_command::MENU_CMD_ID_LIFTER_HIGH] = f;
}
child->select(WORDS_MENU_LOW);
root_->add_menu(WORDS_MENU_LIFTER_POS, child);
child->release();
}
// 调整系统时间
{
auto adjtm = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
int hour = -1,
min = -1;
if(id < seq_hour_)
{
hour = id;
}
else if(id < seq_min_)
{
min = id - seq_hour_;
}
if(hour != -1 || min != -1)
{
// adjust system time here ... (date -s "2022-01-01 09:30:00")
time_t t = time(nullptr);
struct tm* l = localtime(&t);
char cmd[40] = {0};
if(hour == -1)
hour = l->tm_hour;
if(min == -1)
min = l->tm_min;
sprintf(cmd, "date -s \"%04d-%02d-%02d %02d:%02d:%02d\""
, l->tm_year + 1900, l->tm_mon + 1, l->tm_mday
, hour, min, l->tm_sec);
system(cmd);
}
return false;
};
handler_[menu_command::MENU_CMD_ID_SEQ_0] = adjtm;
dev_menu* clck = new dev_menu();
child = new dev_menu();
for(int i = 0; i < 24; ++i)
{
char text[20] = {0};
sprintf(text, "%02d", i);
clck->add_menu(text, menu_command::MENU_CMD_ID_SEQ_0 + i);
}
auto h = [&](dev_menu* obj) -> void
{
time_t t = time(nullptr);
char text[20] = {0};
t /= 3600;
t %= 24;
sprintf(text, "%02d", t);
obj->select(text, true);
};
clck->set_default_pos(h);
child->add_menu(WORDS_MENU_ADJUST_HOUR, clck);
clck->release();
clck = new dev_menu();
for(int i = 0; i < 60; ++i)
{
char text[20] = {0};
sprintf(text, "%02d", i);
clck->add_menu(text, menu_command::MENU_CMD_ID_SEQ_0 + i + seq_hour_);
}
auto m = [&](dev_menu* obj) -> void
{
time_t t = time(nullptr);
char text[20] = {0};
t /= 60;
t %= 60;
sprintf(text, "%02d", t);
obj->select(text, true);
};
clck->set_default_pos(m);
child->add_menu(WORDS_MENU_ADJUST_MINUTE, clck);
clck->release();
root_->add_menu(WORDS_MENU_ADJUST_TIME, child);
child->release();
}
// 关机
{
child = new dev_menu(false, false);
child->add_menu(WORDS_MENU_YES, menu_command::MENU_CMD_ID_SHUTDOWN);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
system("poweroff");
return false;
};
handler_[menu_command::MENU_CMD_ID_SHUTDOWN] = f;
}
child->add_menu(WORDS_MENU_NO, menu_command::MENU_CMD_ID_CANCEL);
child->set_default_pos(1);
root_->add_menu(WORDS_MENU_SHUTDOWN, child);
child->release();
}
root_->add_menu(WORDS_MENU_WELCOME, menu_command::MENU_CMD_ID_WELCOME);
{
auto f = [this](MEMNU_CMD_HANDLER_PARAM) -> MENU_CMD_HANDLER_RET
{
DISPDATA dd;
dd.mask = 0;
dd.x = 0;
dd.y = 0;
dd.cnt = 1;
dd.ptr[0] = welcome::get_current_pic();
dd.method = DISP_METHOD_WHOLE_LINE;
disp_data_.save(dd, true);
return false;
};
handler_[menu_command::MENU_CMD_ID_WELCOME] = f;
}
cur_ = root_;
cur_->add_ref();
}
void ui_mgr::clear(void)
{
if(cur_)
cur_->release();
cur_ = nullptr;
if(root_)
root_->release();
root_ = nullptr;
}
void ui_mgr::refresh_lcd(bool cur_at_top)
{
std::vector<std::string> text, disp;
int val = -1, cur = cur_->get_menu_text(text, val), sel = 0,
rows = Lcd::LCD_HEIGHT / font_size_.cy;
if(cur >= 0 && cur < text.size())
{
disp.push_back(cur == val ? WORDS_MENU_SELECTED + text[cur] : text[cur]);
if(cur_at_top)
{
for(int i = cur + 1; i < text.size() && disp.size() < rows; ++i)
disp.push_back(i == val ? WORDS_MENU_SELECTED + text[i] : text[i]);
for(int i = cur - 1; i >= 0 && disp.size() < rows; --i, sel++)
disp.insert(disp.begin(), i == val ? WORDS_MENU_SELECTED + text[i] : text[i]);
}
else
{
for(int i = cur - 1; i >= 0 && disp.size() < rows; --i, sel++)
disp.insert(disp.begin(), i == val ? WORDS_MENU_SELECTED + text[i] : text[i]);
for(int i = cur + 1; i < text.size() && disp.size() < rows; ++i)
disp.push_back(i == val ? WORDS_MENU_SELECTED + text[i] : text[i]);
}
}
rows = 0;
for(int i = 0; i < disp.size(); ++i)
{
DISPDATA dd;
memset(&dd, 0, sizeof(dd));
dd.mask = i == sel ? 0x0ff : 0;
dd.x = disp[i].find(WORDS_MENU_SELECTED) == 0 ? 0 : font_size_.cx;
dd.y = rows;
dd.cnt = custom_font::get_string_font(disp[i].c_str(), dd.ptr);
dd.method = DISP_METHOD_WHOLE_LINE;
cur = disp_data_.save(dd, true);
rows += font_size_.cy;
}
}
void ui_mgr::move_to(bool next)
{
if(cur_)
{
if(cur_->move_to(next))
{
// refresh LCD
refresh_lcd(!next);
}
}
}
void ui_mgr::enter(void)
{
if(cur_)
{
int id = -1;
dev_menu* bef = cur_;
std::string text("");
cur_ = cur_->enter(&id, &text);
bef->release();
if(id != -1 || !text.empty())
{
bool holdui = do_menu_command(id, text.c_str());
set_ready_status_enabled(!holdui);
}
if(cur_ != bef)
{
// refresh LCD
refresh_lcd(true);
}
}
}
void ui_mgr::thread_display(void)
{
DISPDATA dd;
int wait = 10;
bool ready_msg = false;
// welcome
{
uint8_t *ptr[] = {welcome::get_current_pic()};
lcd_->write_line(ptr, 1);
}
while(run_)
{
if(disp_data_.take(dd, true, SEC_2_MS(wait)))
{
ready_msg = false;
if(dd.method == DISP_METHOD_PART_LINE)
lcd_->write_line(dd.ptr, dd.cnt, dd.x, dd.y, dd.mask);
else if(dd.method == DISP_METHOD_CLEAR)
lcd_->clear_pages();
else if(dd.method == DISP_METHOD_WHOLE_LINE)
lcd_->write_whole_line(dd.ptr, dd.cnt, dd.x, dd.y, dd.mask);
wait = 6;
}
else if(ready_enable_)
{
if(get_ready_watch_ms() / SEC_2_MS(1) >= wait)
{
display_ready(ready_msg);
if(ready_msg)
wait = 60;
else
wait = 60 - (time(nullptr) % 60);
ready_msg = true;
}
}
}
}
void ui_mgr::display_scan_title(void)
{
DISPDATA dd;
int_by_status_ = stopped_by_ui_ = false;
memset(&dd, 0, sizeof(dd));
dd.method = DISP_METHOD_CLEAR;
disp_data_.save(dd, true);
dd.cnt = custom_font::get_string_font(scan_mode_ == devui::SCAN_NORMAL ? WORDS_STATUS_SCANNING_NORMAL : WORDS_STATUS_SCANNING_COUNT, dd.ptr);
hold_pos_.x = dd.ptr[0][0] * 1;
hold_pos_.y = dd.ptr[0][1];
dd.method = DISP_METHOD_PART_LINE;
disp_data_.save(dd, true);
}
void ui_mgr::display_ready(bool time_only)
{
// set_ready_status_enabled(false);
menu_mode_ = false;
if(!time_only)
{
lcd_->write_whole_line(ready_.ptr, ready_.cnt, ready_.x, ready_.y, ready_.mask);
// {
// DISPDATA dd;
// memset(&dd, 0, sizeof(dd));
// dd.cnt = custom_font::get_string_font("0123456789", dd.ptr, custom_font::FONT_SIZE_8);
// lcd_->write_line(dd.ptr, dd.cnt, dd.x, dd.y, dd.mask);
// }
}
{
std::string now(utils::format_current_time());
size_t pos = now.find(" ");
DISPDATA dd;
if(pos++ != std::string::npos)
now.erase(0, pos);
pos = now.rfind(':');
if(pos != std::string::npos)
now.erase(pos);
memset(&dd, 0, sizeof(dd));
dd.cnt = custom_font::get_string_font(now.c_str(), dd.ptr, custom_font::FONT_SIZE_8);
dd.x = Lcd::LCD_WIDTH - (dd.ptr[0][0] + 1) * dd.cnt;
dd.y = 8;
lcd_->write_line(dd.ptr, dd.cnt, dd.x, dd.y, dd.mask);
}
}
bool ui_mgr::display_status(void* data)
{
devui::LPSTATMSG lpstatus = (devui::LPSTATMSG)data;
const char* text = words_from_id(lpstatus->msg_words_id);
DISPDATA dd;
custom_font::font_size fs = (custom_font::font_size)(lpstatus->font / 8 - 1);
if(!text || !text[0])
{
utils::to_log(LOG_LEVEL_DEBUG, "Error, No message text for ID %u.\n", lpstatus->msg_words_id);
return false;
}
if(lpstatus->font < 8)
fs = custom_font::FONT_SIZE_16;
memset(&dd, 0, sizeof(dd));
if(lpstatus->clear == devui::CLEAR_ALL)
{
dd.method = DISP_METHOD_CLEAR;
disp_data_.save(dd, true);
dd.method = DISP_METHOD_PART_LINE;
}
else if(lpstatus->clear == devui::CLEAR_NONE)
dd.method = DISP_METHOD_PART_LINE;
else
dd.method = DISP_METHOD_WHOLE_LINE;
dd.cnt = custom_font::get_string_font(text, dd.ptr, fs);
if(dd.cnt == 0)
{
utils::to_log(LOG_LEVEL_DEBUG, "No font size %u for status message '%s'.\n", lpstatus->font, text);
return false;
}
if(lpstatus->align_h != devui::ALIGN_COMPONENT_HEAD)
{
int w = 0;
for(int i = 0; i < dd.cnt; ++i)
w += dd.ptr[i][0] + 1;
if(lpstatus->align_h == devui::ALIGN_COMPONENT_MID)
dd.x = (Lcd::LCD_WIDTH - w) / 2;
else
dd.x = Lcd::LCD_WIDTH - w;
}
if(lpstatus->align_v == devui::ALIGN_COMPONENT_MID)
dd.y = (Lcd::LCD_HEIGHT - dd.ptr[0][0]) / 2;
else if(lpstatus->align_v == devui::ALIGN_COMPONENT_TAIL)
dd.y = Lcd::LCD_HEIGHT - dd.ptr[0][0];
set_ready_status_enabled(false);
disp_data_.save(dd, true);
if(paper_total_)
{
DISPDATA dd;
char num[40] = {0};
int cnt = 0;
sprintf(num, "%s%d", WORDS_STATUS_TOTAL, paper_total_);
dd.x = Lcd::LCD_WIDTH;
dd.cnt = custom_font::get_string_font(num, dd.ptr, custom_font::FONT_SIZE_8);
for(int i = 0; i < dd.cnt; ++i)
dd.x -= dd.ptr[i][0] + 1;
dd.y = Lcd::LCD_HEIGHT - dd.ptr[0][1];
dd.method = DISP_METHOD_PART_LINE;
dd.mask = 0;
cnt = disp_data_.save(dd, true);
}
return true;
}
void ui_mgr::set_ready_status_enabled(bool enable)
{
SIMPLE_LOCK(ready_lck_);
ready_enable_ = enable;
}
void ui_mgr::reset_ready_watch(void)
{
SIMPLE_LOCK(ready_lck_);
ready_watch_.reset();
}
int ui_mgr::get_ready_watch_ms(void)
{
SIMPLE_LOCK(ready_lck_);
return ready_watch_.elapse_ms();
}
void ui_mgr::key_event(int key)
{
if(scanning_)
{
if(key == (int)KeyMonitor::HGKey::Key_Cancle)
{
stopped_by_ui_ = true;
utils::to_log(LOG_LEVEL_DEBUG, "Do menu command: %s\n", "Stop scanning Immediately");
devui::send_message(devui::UI_CMD_STOP_SCAN);
}
return;
}
reset_ready_watch();
set_ready_status_enabled(true);
if(!menu_mode_)
{
menu_mode_ = true;
if(cur_)
cur_->release();
cur_ = root_;
if(cur_)
cur_->add_ref();
refresh_lcd(true);
return;
}
if(key == (int)KeyMonitor::HGKey::Key_Menu)
enter();
else if(key == (int)KeyMonitor::HGKey::Key_Left)
move_to(false);
else if(key == (int)KeyMonitor::HGKey::Key_Right)
move_to(true);
else if(key == (int)KeyMonitor::HGKey::Key_Cancle)
{
// stop scanning here ...
utils::to_log(LOG_LEVEL_DEBUG, "Do menu command: %s\n", "Stop scanning Immediately");
devui::send_message(devui::UI_CMD_STOP_SCAN);
}
else if(key == -1) // interrupted by status message, we return to main menu
{
if(cur_)
cur_->release();
cur_ = root_;
if(cur_)
{
cur_->add_ref();
cur_->reset_pos();
}
}
else
{
utils::to_log(LOG_LEVEL_ALL, "Unhandled keyboard event: %02X\n", key);
}
}