menu and modal almost working

This commit is contained in:
kkoenig1@optonline.com
2022-06-11 15:13:11 +02:00
committed by Raphael Coeffic
parent cab656b5d2
commit 66c500799c
4 changed files with 132 additions and 89 deletions
+103 -50
View File
@@ -21,6 +21,62 @@
#include "font.h"
#include "theme.h"
LvglWidgetFactory menuBodyWidgetFactory = { [] (lv_obj_t *parent) {
return lv_list_create(parent);
}, nullptr};
void menuBodyEventCallback(lv_event_t *e)
{
auto code = lv_event_get_code(e);
if (code == LV_EVENT_CLICKED) {
lv_obj_t *target = lv_event_get_target(e);
if (target != nullptr) {
long index = (long)lv_event_get_user_data(e);
MenuBody *mb = (MenuBody *) lv_obj_get_user_data(lv_obj_get_parent(target));
Menu *menu = mb->getParentMenu();
if (index < (int)mb->lines.size()) {
onKeyPress();
if (menu->multiple) {
if (mb->selectedIndex == index)
mb->lines[index].onPress();
else
mb->setIndex(index);
}
else {
mb->setIndex(index);
menu->deleteLater();
mb->lines[index].onPress();
}
}
}
}
}
MenuBody::MenuBody(Window * parent, const rect_t & rect):
Window(parent, rect, OPAQUE, 0, &menuBodyWidgetFactory)
{
setPageHeight(MENUS_LINE_HEIGHT);
}
void MenuBody::addLine(const std::string & text, std::function<void()> onPress, std::function<bool()> isChecked)
{
lines.emplace_back(text, std::move(onPress), std::move(isChecked));
lv_obj_t *btn = lv_list_add_btn(lvobj, nullptr, text.c_str());
lv_obj_set_style_bg_color(btn, makeLvColor(COLOR_THEME_SECONDARY2), LV_PART_MAIN | LV_STATE_CHECKED);
lv_obj_set_style_bg_color(btn, makeLvColor(COLOR_THEME_SECONDARY2), LV_PART_MAIN | LV_STATE_CHECKED | LV_STATE_FOCUSED);
lv_obj_set_style_bg_opa(btn, LV_OPA_100, LV_PART_MAIN);
lv_obj_set_style_bg_opa(btn, LV_OPA_100, LV_PART_MAIN | LV_STATE_CHECKED);
lv_obj_set_style_bg_opa(btn, LV_OPA_100, LV_PART_MAIN | LV_STATE_CHECKED | LV_STATE_FOCUSED);
lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE);
lv_obj_add_event_cb(btn, menuBodyEventCallback, LV_EVENT_CLICKED, (void *) (lines.size() - 1));
lv_obj_set_style_text_color(lvobj, makeLvColor(COLOR_THEME_PRIMARY2), LV_PART_MAIN | LV_STATE_FOCUSED);
}
void MenuBody::removeLines()
{
lines.clear();
lv_obj_clean(lvobj);
}
// ensure index is in range and also handle wrapping index
int MenuBody::rangeCheck(int index)
@@ -35,17 +91,14 @@ int MenuBody::rangeCheck(int index)
void MenuBody::setIndex(int index)
{
selectedIndex = index;
// calculate the correct scroll postion based on there being separators
int scrollY = 0;
for (int i = 0; i < selectedIndex; i++)
scrollY += lines[i].lineHeight();
if (index < (int)lines.size()) {
selectedIndex = index;
if (innerHeight > height()) {
lv_obj_scroll_to_y(lvobj, scrollY - 3 * MENUS_LINE_HEIGHT, LV_ANIM_OFF);
lv_obj_t *btn = lv_obj_get_child(lvobj, selectedIndex);
if (btn != nullptr) {
lv_obj_add_state(btn, LV_STATE_CHECKED);
}
}
invalidate();
}
void MenuBody::select(int index)
@@ -166,42 +219,42 @@ bool MenuBody::onTouchEnd(coord_t /*x*/, coord_t y)
void MenuBody::paint(BitmapBuffer * dc)
{
dc->clear(COLOR_THEME_PRIMARY2);
// dc->clear(COLOR_THEME_PRIMARY2);
int y = 0;
for (int i = 0; i < (signed)lines.size(); i++) {
auto& line = lines[i];
LcdFlags flags = COLOR_THEME_PRIMARY3 | MENU_FONT;
// int y = 0;
// for (int i = 0; i < (signed)lines.size(); i++) {
// auto& line = lines[i];
// LcdFlags flags = COLOR_THEME_PRIMARY3 | MENU_FONT;
// draw selection if appropriate
if (selectedIndex == i && ! line.isSeparator) {
flags = COLOR_THEME_PRIMARY2 | MENU_FONT;
if (COLOR_THEME_FOCUS != COLOR_THEME_PRIMARY2) {
dc->drawSolidFilledRect(0, y, width(),
MENUS_LINE_HEIGHT, COLOR_THEME_FOCUS);
}
}
// // draw selection if appropriate
// if (selectedIndex == i && ! line.isSeparator) {
// flags = COLOR_THEME_PRIMARY2 | MENU_FONT;
// if (COLOR_THEME_FOCUS != COLOR_THEME_PRIMARY2) {
// dc->drawSolidFilledRect(0, y, width(),
// MENUS_LINE_HEIGHT, COLOR_THEME_FOCUS);
// }
// }
if (line.isSeparator) {
dc->drawHorizontalLine(5, y + MENUS_SEPARATOR_HEIGHT / 2, width() - 10, 255, COLOR_THEME_SECONDARY1);
} else if (line.drawLine) {
line.drawLine(dc, 0, y, COLOR_THEME_PRIMARY3);
} else {
const char* text = line.text.data();
dc->drawText(10,
y + (MENUS_LINE_HEIGHT - getFontHeight(MENU_FONT)) / 2,
text[0] == '\0' ? "---" : text, flags);
}
// if (line.isSeparator) {
// dc->drawHorizontalLine(5, y + MENUS_SEPARATOR_HEIGHT / 2, width() - 10, 255, COLOR_THEME_SECONDARY1);
// } else if (line.drawLine) {
// line.drawLine(dc, 0, y, COLOR_THEME_PRIMARY3);
// } else {
// const char* text = line.text.data();
// dc->drawText(10,
// y + (MENUS_LINE_HEIGHT - getFontHeight(MENU_FONT)) / 2,
// text[0] == '\0' ? "---" : text, flags);
// }
Menu* menu = getParentMenu();
if (menu->multiple && line.isChecked) {
theme->drawCheckBox(dc, line.isChecked(), width() - 35,
y + (MENUS_LINE_HEIGHT - 20) / 2,
0);
}
// Menu* menu = getParentMenu();
// if (menu->multiple && line.isChecked) {
// theme->drawCheckBox(dc, line.isChecked(), width() - 35,
// y + (MENUS_LINE_HEIGHT - 20) / 2,
// 0);
// }
y += line.lineHeight();
}
// y += line.lineHeight();
// }
}
MenuWindowContent::MenuWindowContent(Menu* parent) :
@@ -214,17 +267,17 @@ MenuWindowContent::MenuWindowContent(Menu* parent) :
void MenuWindowContent::paint(BitmapBuffer * dc)
{
// the background
dc->clear(COLOR_THEME_SECONDARY1);
// // the background
// dc->clear(COLOR_THEME_SECONDARY1);
// the title
if (!title.empty()) {
dc->drawText(MENUS_WIDTH / 2,
(POPUP_HEADER_HEIGHT - getFontHeight(MENU_HEADER_FONT)) / 2,
title.c_str(), CENTERED | MENU_HEADER_FONT | COLOR_THEME_PRIMARY2);
dc->drawSolidHorizontalLine(0, POPUP_HEADER_HEIGHT - 1, MENUS_WIDTH,
COLOR_THEME_SECONDARY2);
}
// // the title
// if (!title.empty()) {
// dc->drawText(MENUS_WIDTH / 2,
// (POPUP_HEADER_HEIGHT - getFontHeight(MENU_HEADER_FONT)) / 2,
// title.c_str(), CENTERED | MENU_HEADER_FONT | COLOR_THEME_PRIMARY2);
// dc->drawSolidHorizontalLine(0, POPUP_HEADER_HEIGHT - 1, MENUS_WIDTH,
// COLOR_THEME_SECONDARY2);
// }
}
Menu::Menu(Window * parent, bool multiple):
+6 -15
View File
@@ -69,6 +69,7 @@ class MenuBody: public Window
MenuLine(MenuLine &&) = default;
protected:
friend void menuBodyEventCallback(lv_event_t *e);
bool isSeparator = false;
coord_t height = MENUS_LINE_HEIGHT;
std::string text;
@@ -78,11 +79,7 @@ class MenuBody: public Window
};
public:
MenuBody(Window * parent, const rect_t & rect):
Window(parent, rect, OPAQUE)
{
setPageHeight(MENUS_LINE_HEIGHT);
}
MenuBody(Window * parent, const rect_t & rect);
#if defined(DEBUG_WINDOWS)
std::string getName() const override
@@ -116,11 +113,7 @@ class MenuBody: public Window
bool onTouchEnd(coord_t x, coord_t y) override;
#endif
void addLine(const std::string & text, std::function<void()> onPress, std::function<bool()> isChecked)
{
lines.emplace_back(text, std::move(onPress), std::move(isChecked));
invalidate();
}
void addLine(const std::string & text, std::function<void()> onPress, std::function<bool()> isChecked);
void addCustomLine(std::function<void(BitmapBuffer * /*dc*/, coord_t /*x*/, coord_t /*y*/, LcdFlags /*flags*/)> drawLine, std::function<void()> onPress, std::function<bool()> isChecked)
{
@@ -133,11 +126,7 @@ class MenuBody: public Window
lines.emplace_back(true);
}
void removeLines()
{
lines.clear();
invalidate();
}
void removeLines();
void setCancelHandler(std::function<void()> handler)
{
@@ -147,6 +136,7 @@ class MenuBody: public Window
void paint(BitmapBuffer * dc) override;
protected:
friend void menuBodyEventCallback(lv_event_t *);
void selectNext(MENU_DIRECTION direction);
int rangeCheck(int);
void setIndex(int index);
@@ -264,6 +254,7 @@ class Menu: public ModalWindow
void paint(BitmapBuffer * dc) override;
protected:
friend void menuBodyEventCallback(lv_event_t *);
MenuWindowContent * content;
bool multiple;
Window * toolbar = nullptr;
+22 -5
View File
@@ -26,6 +26,10 @@ ModalWindow::ModalWindow(Window * parent, bool closeWhenClickOutside):
Window(parent->getFullScreenWindow(), {0, 0, LCD_W, LCD_H}),
closeWhenClickOutside(closeWhenClickOutside)
{
lv_obj_set_parent(lvobj, lv_layer_top());
lv_obj_set_style_bg_color(lvobj, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_bg_opa(lvobj, LV_OPA_50, LV_PART_MAIN);
lv_obj_add_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);
Layer::push(this);
}
@@ -33,20 +37,33 @@ void ModalWindow::deleteLater(bool detach, bool trash)
{
if (_deleted)
return;
lv_obj_clear_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);
Layer::pop(this);
Window::deleteLater(detach, trash);
}
#if defined(HARDWARE_TOUCH)
bool ModalWindow::onTouchEnd(coord_t x, coord_t y)
{
if (closeWhenClickOutside) {
onKeyPress();
deleteLater();
}
return true;
}
#endif
void ModalWindow::paint(BitmapBuffer * dc)
{
dc->drawFilledRect(0, 0, width(), height(), SOLID, BLACK, OPACITY(6));
// dc->drawFilledRect(0, 0, width(), height(), SOLID, BLACK, OPACITY(6));
}
void ModalWindowContent::paint(BitmapBuffer * dc)
{
dc->drawSolidFilledRect(0, 0, width(), POPUP_HEADER_HEIGHT, COLOR_THEME_SECONDARY1);
dc->drawText(FIELD_PADDING_LEFT, (POPUP_HEADER_HEIGHT - getFontHeight(FONT(STD))) / 2, title.c_str(), COLOR_THEME_PRIMARY2);
dc->drawSolidFilledRect(0, POPUP_HEADER_HEIGHT, width(), height() - POPUP_HEADER_HEIGHT, COLOR_THEME_SECONDARY3);
// dc->drawSolidFilledRect(0, 0, width(), POPUP_HEADER_HEIGHT, COLOR_THEME_SECONDARY1);
// dc->drawText(FIELD_PADDING_LEFT, (POPUP_HEADER_HEIGHT - getFontHeight(FONT(STD))) / 2, title.c_str(), COLOR_THEME_PRIMARY2);
// dc->drawSolidFilledRect(0, POPUP_HEADER_HEIGHT, width(), height() - POPUP_HEADER_HEIGHT, COLOR_THEME_SECONDARY3);
}
+1 -19
View File
@@ -38,25 +38,7 @@ class ModalWindow: public Window
void paint(BitmapBuffer * dc) override;
#if defined(HARDWARE_TOUCH)
bool onTouchStart(coord_t /*x*/, coord_t /*y*/) override
{
return true;
}
bool onTouchEnd(coord_t x, coord_t y) override
{
if (!Window::onTouchEnd(x, y) && closeWhenClickOutside) {
onKeyPress();
deleteLater();
}
return true;
}
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override
{
Window::onTouchSlide(x, y, startX, startY, slideX, slideY);
return true;
}
bool onTouchEnd(coord_t x, coord_t y) override;
#endif
void setCloseWhenClickOutside(bool value = true)