menu and modal almost working
This commit is contained in:
committed by
Raphael Coeffic
parent
cab656b5d2
commit
66c500799c
+103
-50
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user