Revert "added menu separators"
This reverts commit 35a4ebc7fe5b86eec23ddf8a9291d539f44e14b4.
This commit is contained in:
committed by
Peter Feerick
parent
bd3781c95e
commit
cda649db1f
+25
-102
@@ -21,59 +21,15 @@
|
||||
#include "font.h"
|
||||
#include "theme.h"
|
||||
|
||||
|
||||
// ensure index is in range and also handle wrapping index
|
||||
int MenuBody::rangeCheck(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
index = lines.size() - 1;
|
||||
else if (index > lines.size() - 1)
|
||||
index = 0;
|
||||
|
||||
return 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 (innerHeight > height()) {
|
||||
setScrollPositionY(scrollY - 3 * MENUS_LINE_HEIGHT);
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void MenuBody::select(int index)
|
||||
{
|
||||
// adjust the selection based on separators
|
||||
for (int i = 0; i <= index; i++) {
|
||||
if (lines[i].isSeparator)
|
||||
index++;
|
||||
index = rangeCheck(index);
|
||||
selectedIndex = index;
|
||||
if (innerHeight > height()) {
|
||||
setScrollPositionY(MENUS_LINE_HEIGHT * index - 3 * MENUS_LINE_HEIGHT);
|
||||
}
|
||||
|
||||
setIndex(index);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void MenuBody::selectNext(MENU_DIRECTION direction)
|
||||
{
|
||||
// look for the next non separator line
|
||||
int index = selectedIndex + direction;
|
||||
index = rangeCheck(index);
|
||||
while (lines[index].isSeparator) {
|
||||
index += direction;
|
||||
index = rangeCheck(index);
|
||||
}
|
||||
|
||||
setIndex(index);
|
||||
}
|
||||
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void MenuBody::onEvent(event_t event)
|
||||
{
|
||||
@@ -81,13 +37,13 @@ void MenuBody::onEvent(event_t event)
|
||||
|
||||
if (event == EVT_ROTARY_RIGHT) {
|
||||
if (!lines.empty()) {
|
||||
selectNext(DIRECTION_UP);
|
||||
select(int((selectedIndex + 1) % lines.size()));
|
||||
onKeyPress();
|
||||
}
|
||||
}
|
||||
else if (event == EVT_ROTARY_LEFT) {
|
||||
if (!lines.empty()) {
|
||||
selectNext(DIRECTION_DOWN);
|
||||
select(int(selectedIndex <= 0 ? lines.size() - 1 : selectedIndex - 1));
|
||||
onKeyPress();
|
||||
}
|
||||
}
|
||||
@@ -127,39 +83,22 @@ void MenuBody::onEvent(event_t event)
|
||||
bool MenuBody::onTouchEnd(coord_t /*x*/, coord_t y)
|
||||
{
|
||||
Menu * menu = getParentMenu();
|
||||
|
||||
int index = 0;
|
||||
|
||||
// dynamically find the selected element based on variable line heights
|
||||
coord_t yAccumulator = 0;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (y >= yAccumulator && y <= yAccumulator + lines[i].lineHeight()) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
yAccumulator += lines[i].lineHeight();
|
||||
}
|
||||
|
||||
// dont allow selecting separators
|
||||
if (lines[index].isSeparator)
|
||||
return false;
|
||||
|
||||
int index = y / MENUS_LINE_HEIGHT;
|
||||
if (index < (int)lines.size()) {
|
||||
onKeyPress();
|
||||
if (menu->multiple) {
|
||||
if (selectedIndex == index)
|
||||
lines[index].onPress();
|
||||
else
|
||||
setIndex(index);
|
||||
select(index);
|
||||
menu->invalidate();
|
||||
}
|
||||
else {
|
||||
setIndex(index);
|
||||
select(index);
|
||||
menu->deleteLater();
|
||||
lines[index].onPress();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -168,43 +107,37 @@ void MenuBody::paint(BitmapBuffer * dc)
|
||||
{
|
||||
dc->clear(COLOR_THEME_PRIMARY2);
|
||||
|
||||
int y = 0;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
for (unsigned i = 0; i < lines.size(); i++) {
|
||||
auto& line = lines[i];
|
||||
LcdFlags flags = COLOR_THEME_SECONDARY1 | MENU_FONT;
|
||||
|
||||
// draw selection if appropriate
|
||||
if (selectedIndex == i && ! line.isSeparator) {
|
||||
if (selectedIndex == (int)i) {
|
||||
flags = COLOR_THEME_PRIMARY2 | MENU_FONT;
|
||||
if (COLOR_THEME_FOCUS != COLOR_THEME_PRIMARY2) {
|
||||
dc->drawSolidFilledRect(0, y, width(),
|
||||
dc->drawSolidFilledRect(0, i * MENUS_LINE_HEIGHT, width(),
|
||||
MENUS_LINE_HEIGHT, COLOR_THEME_FOCUS);
|
||||
}
|
||||
}
|
||||
|
||||
if (line.isSeparator) {
|
||||
dc->drawHorizontalLine(5, y + MENUS_SEPARATOR_HEIGHT / 2, width() - 10, 255, COLOR_THEME_SECONDARY2);
|
||||
} else if (line.drawLine) {
|
||||
line.drawLine(dc, 0, y, flags);
|
||||
if (line.drawLine) {
|
||||
line.drawLine(dc, 0, i * MENUS_LINE_HEIGHT, flags);
|
||||
} else {
|
||||
const char* text = line.text.data();
|
||||
dc->drawText(10,
|
||||
y + (MENUS_LINE_HEIGHT - getFontHeight(MENU_FONT)) / 2,
|
||||
i * MENUS_LINE_HEIGHT +
|
||||
(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,
|
||||
i * MENUS_LINE_HEIGHT + (MENUS_LINE_HEIGHT - 20) / 2,
|
||||
0);
|
||||
}
|
||||
|
||||
// if (i > 0 && ! lines[i].isSeparator && ! lines[i-1].isSeparator) {
|
||||
// dc->drawSolidHorizontalLine(0, y, MENUS_WIDTH, COLOR_THEME_SECONDARY2);
|
||||
// }
|
||||
|
||||
y += line.lineHeight();
|
||||
if (i > 0) {
|
||||
dc->drawSolidHorizontalLine(0, i * MENUS_LINE_HEIGHT, MENUS_WIDTH,
|
||||
COLOR_THEME_SECONDARY2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,22 +173,18 @@ Menu::Menu(Window * parent, bool multiple):
|
||||
|
||||
void Menu::updatePosition()
|
||||
{
|
||||
// calcualte the correct menu height given that the line heights are variable
|
||||
coord_t height = 0;
|
||||
for (int i = 0; i < content->body.lines.size(); i++)
|
||||
height += content->body.lines[i].lineHeight();
|
||||
|
||||
if (!toolbar) {
|
||||
// there is no navigation bar at the left, we may center the window on screen
|
||||
auto headerHeight = content->title.empty() ? 0 : POPUP_HEADER_HEIGHT;
|
||||
auto bodyHeight = limit<coord_t>(MENUS_MIN_HEIGHT, height, MENUS_MAX_HEIGHT);
|
||||
auto bodyHeight = limit<coord_t>(
|
||||
MENUS_MIN_HEIGHT, content->body.lines.size() * MENUS_LINE_HEIGHT,
|
||||
MENUS_MAX_HEIGHT);
|
||||
content->setTop((LCD_H - headerHeight - bodyHeight) / 2 + MENUS_OFFSET_TOP);
|
||||
content->setHeight(headerHeight + bodyHeight);
|
||||
content->body.setTop(headerHeight);
|
||||
content->body.setHeight(bodyHeight);
|
||||
}
|
||||
|
||||
content->body.setInnerHeight(height);
|
||||
content->body.setInnerHeight(content->body.lines.size() * MENUS_LINE_HEIGHT);
|
||||
}
|
||||
|
||||
void Menu::setTitle(std::string text)
|
||||
@@ -270,12 +199,6 @@ void Menu::addLine(const std::string & text, std::function<void()> onPress, std:
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::addSeparator()
|
||||
{
|
||||
content->body.addSeparator();
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::addCustomLine(std::function<void(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags flags)> drawLine, std::function<void()> onPress, std::function<bool()> isChecked)
|
||||
{
|
||||
content->body.addCustomLine(std::move(drawLine), std::move(onPress), std::move(isChecked));
|
||||
|
||||
+197
-267
@@ -17,300 +17,230 @@
|
||||
* Lesser General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
#include "font.h"
|
||||
#include "theme.h"
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include "modal_window.h"
|
||||
|
||||
// ensure index is in range and also handle wrapping index
|
||||
int MenuBody::rangeCheck(int index)
|
||||
class Menu;
|
||||
class MenuWindowContent;
|
||||
|
||||
class MenuBody: public Window
|
||||
{
|
||||
if (index < 0)
|
||||
index = lines.size() - 1;
|
||||
else if (index > lines.size() - 1)
|
||||
index = 0;
|
||||
friend class MenuWindowContent;
|
||||
friend class Menu;
|
||||
|
||||
return index;
|
||||
}
|
||||
class MenuLine {
|
||||
friend class MenuBody;
|
||||
|
||||
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();
|
||||
public:
|
||||
MenuLine(std::string text, std::function<void()> onPress, std::function<bool()> isChecked):
|
||||
text(std::move(text)),
|
||||
onPress(std::move(onPress)),
|
||||
isChecked(std::move(isChecked))
|
||||
{
|
||||
}
|
||||
|
||||
if (innerHeight > height()) {
|
||||
setScrollPositionY(scrollY - 3 * MENUS_LINE_HEIGHT);
|
||||
}
|
||||
MenuLine(std::function<void(BitmapBuffer * /*dc*/, coord_t /*x*/, coord_t /*y*/, LcdFlags /*flags*/)> drawLine, std::function<void()> onPress, std::function<bool()> isChecked):
|
||||
drawLine(std::move(drawLine)),
|
||||
onPress(std::move(onPress)),
|
||||
isChecked(std::move(isChecked))
|
||||
{
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
MenuLine(MenuLine &) = delete;
|
||||
|
||||
void MenuBody::select(int index)
|
||||
{
|
||||
// adjust the selection based on separators
|
||||
for (int i = 0; i <= index; i++) {
|
||||
if (lines[i].isSeparator)
|
||||
index++;
|
||||
index = rangeCheck(index);
|
||||
}
|
||||
MenuLine(MenuLine &&) = default;
|
||||
|
||||
setIndex(index);
|
||||
}
|
||||
protected:
|
||||
std::string text;
|
||||
std::function<void(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags flags)> drawLine;
|
||||
std::function<void()> onPress;
|
||||
std::function<bool()> isChecked;
|
||||
};
|
||||
|
||||
void MenuBody::selectNext(MENU_DIRECTION direction)
|
||||
{
|
||||
// look for the next non separator line
|
||||
int index = selectedIndex + direction;
|
||||
index = rangeCheck(index);
|
||||
while (lines[index].isSeparator) {
|
||||
index += direction;
|
||||
index = rangeCheck(index);
|
||||
}
|
||||
public:
|
||||
MenuBody(Window * parent, const rect_t & rect):
|
||||
Window(parent, rect, OPAQUE)
|
||||
{
|
||||
setPageHeight(MENUS_LINE_HEIGHT);
|
||||
}
|
||||
|
||||
setIndex(index);
|
||||
}
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
{
|
||||
return "MenuBody";
|
||||
}
|
||||
#endif
|
||||
|
||||
void select(int index);
|
||||
|
||||
int selection() const
|
||||
{
|
||||
return selectedIndex;
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
return lines.size();
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void MenuBody::onEvent(event_t event)
|
||||
{
|
||||
TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event);
|
||||
|
||||
if (event == EVT_ROTARY_RIGHT) {
|
||||
if (!lines.empty()) {
|
||||
selectNext(DIRECTION_UP);
|
||||
onKeyPress();
|
||||
}
|
||||
}
|
||||
else if (event == EVT_ROTARY_LEFT) {
|
||||
if (!lines.empty()) {
|
||||
selectNext(DIRECTION_DOWN);
|
||||
onKeyPress();
|
||||
}
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
if (!lines.empty()) {
|
||||
onKeyPress();
|
||||
if (selectedIndex < 0) {
|
||||
select(0);
|
||||
}
|
||||
else {
|
||||
Menu * menu = getParentMenu();
|
||||
if (menu->multiple) {
|
||||
lines[selectedIndex].onPress();
|
||||
menu->invalidate();
|
||||
}
|
||||
else {
|
||||
menu->deleteLater();
|
||||
lines[selectedIndex].onPress();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
onKeyPress();
|
||||
if (onCancel) {
|
||||
onCancel();
|
||||
}
|
||||
Window::onEvent(event);
|
||||
}
|
||||
else {
|
||||
Window::onEvent(event);
|
||||
}
|
||||
}
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool MenuBody::onTouchEnd(coord_t /*x*/, coord_t y)
|
||||
{
|
||||
Menu * menu = getParentMenu();
|
||||
|
||||
int index = 0;
|
||||
|
||||
// dynamically find the selected element based on variable line heights
|
||||
coord_t yAccumulator = 0;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
if (y >= yAccumulator && y <= yAccumulator + lines[i].lineHeight()) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
yAccumulator += lines[i].lineHeight();
|
||||
}
|
||||
|
||||
// dont allow selecting separators
|
||||
if (lines[index].isSeparator)
|
||||
return false;
|
||||
|
||||
if (index < (int)lines.size()) {
|
||||
onKeyPress();
|
||||
if (menu->multiple) {
|
||||
if (selectedIndex == index)
|
||||
lines[index].onPress();
|
||||
else
|
||||
setIndex(index);
|
||||
menu->invalidate();
|
||||
}
|
||||
else {
|
||||
setIndex(index);
|
||||
menu->deleteLater();
|
||||
lines[index].onPress();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
#endif
|
||||
|
||||
void MenuBody::paint(BitmapBuffer * dc)
|
||||
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 addCustomLine(std::function<void(BitmapBuffer * /*dc*/, coord_t /*x*/, coord_t /*y*/, LcdFlags /*flags*/)> drawLine, std::function<void()> onPress, std::function<bool()> isChecked)
|
||||
{
|
||||
lines.emplace_back(std::move(drawLine), std::move(onPress), std::move(isChecked));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void removeLines()
|
||||
{
|
||||
lines.clear();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void setCancelHandler(std::function<void()> handler)
|
||||
{
|
||||
onCancel = std::move(handler);
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
protected:
|
||||
std::vector<MenuLine> lines;
|
||||
int selectedIndex = 0;
|
||||
std::function<void()> onCancel;
|
||||
|
||||
inline Menu * getParentMenu();
|
||||
};
|
||||
|
||||
class MenuWindowContent: public ModalWindowContent
|
||||
{
|
||||
dc->clear(COLOR_THEME_PRIMARY2);
|
||||
friend class Menu;
|
||||
|
||||
int y = 0;
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
auto& line = lines[i];
|
||||
LcdFlags flags = COLOR_THEME_SECONDARY1 | MENU_FONT;
|
||||
public:
|
||||
explicit MenuWindowContent(Menu * parent);
|
||||
|
||||
// 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);
|
||||
void deleteLater(bool detach = true, bool trash = true) override
|
||||
{
|
||||
if (_deleted)
|
||||
return;
|
||||
|
||||
body.deleteLater(true, false);
|
||||
ModalWindowContent::deleteLater(detach, trash);
|
||||
}
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
{
|
||||
return "MenuWindowContent";
|
||||
}
|
||||
#endif
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
protected:
|
||||
MenuBody body;
|
||||
};
|
||||
|
||||
class Menu: public ModalWindow
|
||||
{
|
||||
friend class MenuBody;
|
||||
|
||||
public:
|
||||
explicit Menu(Window * parent, bool multiple = false);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
{
|
||||
return "Menu";
|
||||
}
|
||||
#endif
|
||||
|
||||
void setCancelHandler(std::function<void()> handler)
|
||||
{
|
||||
content->body.setCancelHandler(std::move(handler));
|
||||
}
|
||||
|
||||
void setWaitHandler(std::function<void()> handler)
|
||||
{
|
||||
waitHandler = std::move(handler);
|
||||
}
|
||||
|
||||
void setFocusBody(uint8_t flag = SET_FOCUS_DEFAULT)
|
||||
{
|
||||
content->body.setFocus(flag);
|
||||
}
|
||||
|
||||
void setToolbar(Window * window)
|
||||
{
|
||||
toolbar = window;
|
||||
content->setLeft(toolbar->right());
|
||||
content->setTop(toolbar->top());
|
||||
content->setHeight(toolbar->height());
|
||||
}
|
||||
|
||||
void setTitle(std::string text);
|
||||
|
||||
void addLine(const std::string & text, std::function<void()> onPress, std::function<bool()> isChecked = nullptr);
|
||||
|
||||
void addCustomLine(std::function<void(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags flags)> drawLine, std::function<void()> onPress, std::function<bool()> isChecked = nullptr);
|
||||
|
||||
void removeLines();
|
||||
|
||||
unsigned count() const
|
||||
{
|
||||
return content->body.count();
|
||||
}
|
||||
|
||||
int selection() const
|
||||
{
|
||||
return content->body.selection();
|
||||
}
|
||||
|
||||
void select(int index)
|
||||
{
|
||||
content->body.select(index);
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
ModalWindow::checkEvents();
|
||||
if (waitHandler) {
|
||||
waitHandler();
|
||||
}
|
||||
}
|
||||
|
||||
if (line.isSeparator) {
|
||||
dc->drawHorizontalLine(5, y + MENUS_SEPARATOR_HEIGHT / 2, width() - 10, 255, COLOR_THEME_SECONDARY2);
|
||||
} else if (line.drawLine) {
|
||||
line.drawLine(dc, 0, y, flags);
|
||||
} else {
|
||||
const char* text = line.text.data();
|
||||
dc->drawText(10,
|
||||
y + (MENUS_LINE_HEIGHT - getFontHeight(MENU_FONT)) / 2,
|
||||
text[0] == '\0' ? "---" : text, flags);
|
||||
}
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
Menu* menu = getParentMenu();
|
||||
if (menu->multiple && line.isChecked) {
|
||||
theme->drawCheckBox(dc, line.isChecked(), width() - 35,
|
||||
y + (MENUS_LINE_HEIGHT - 20) / 2,
|
||||
0);
|
||||
}
|
||||
protected:
|
||||
MenuWindowContent * content;
|
||||
bool multiple;
|
||||
Window * toolbar = nullptr;
|
||||
std::function<void()> waitHandler;
|
||||
void updatePosition();
|
||||
};
|
||||
|
||||
// if (i > 0 && ! lines[i].isSeparator && ! lines[i-1].isSeparator) {
|
||||
// dc->drawSolidHorizontalLine(0, y, MENUS_WIDTH, COLOR_THEME_SECONDARY2);
|
||||
// }
|
||||
|
||||
y += line.lineHeight();
|
||||
}
|
||||
}
|
||||
|
||||
MenuWindowContent::MenuWindowContent(Menu* parent) :
|
||||
ModalWindowContent(parent, {(LCD_W - MENUS_WIDTH) / 2,
|
||||
(LCD_H - MENUS_WIDTH) / 2, MENUS_WIDTH, 0}),
|
||||
body(this, {0, 0, width(), height()})
|
||||
Menu * MenuBody::getParentMenu()
|
||||
{
|
||||
body.setFocus(SET_FOCUS_DEFAULT);
|
||||
return static_cast<Menu *>(getParent()->getParent());
|
||||
}
|
||||
|
||||
void MenuWindowContent::paint(BitmapBuffer * dc)
|
||||
{
|
||||
// the background
|
||||
dc->clear(COLOR_THEME_PRIMARY2);
|
||||
|
||||
// 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);
|
||||
dc->drawSolidHorizontalLine(0, POPUP_HEADER_HEIGHT - 1, MENUS_WIDTH,
|
||||
COLOR_THEME_SECONDARY2);
|
||||
}
|
||||
}
|
||||
|
||||
Menu::Menu(Window * parent, bool multiple):
|
||||
ModalWindow(parent, true),
|
||||
content(createMenuWindow(this)),
|
||||
multiple(multiple)
|
||||
{
|
||||
}
|
||||
|
||||
void Menu::updatePosition()
|
||||
{
|
||||
// calcualte the correct menu height given that the line heights are variable
|
||||
coord_t height = 0;
|
||||
for (int i = 0; i < content->body.lines.size(); i++)
|
||||
height += content->body.lines[i].lineHeight();
|
||||
|
||||
if (!toolbar) {
|
||||
// there is no navigation bar at the left, we may center the window on screen
|
||||
auto headerHeight = content->title.empty() ? 0 : POPUP_HEADER_HEIGHT;
|
||||
auto bodyHeight = limit<coord_t>(MENUS_MIN_HEIGHT, height, MENUS_MAX_HEIGHT);
|
||||
content->setTop((LCD_H - headerHeight - bodyHeight) / 2 + MENUS_OFFSET_TOP);
|
||||
content->setHeight(headerHeight + bodyHeight);
|
||||
content->body.setTop(headerHeight);
|
||||
content->body.setHeight(bodyHeight);
|
||||
}
|
||||
|
||||
content->body.setInnerHeight(height);
|
||||
}
|
||||
|
||||
void Menu::setTitle(std::string text)
|
||||
{
|
||||
content->setTitle(std::move(text));
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::addLine(const std::string & text, std::function<void()> onPress, std::function<bool()> isChecked)
|
||||
{
|
||||
content->body.addLine(text, std::move(onPress), std::move(isChecked));
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::addSeparator()
|
||||
{
|
||||
content->body.addSeparator();
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::addCustomLine(std::function<void(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags flags)> drawLine, std::function<void()> onPress, std::function<bool()> isChecked)
|
||||
{
|
||||
content->body.addCustomLine(std::move(drawLine), std::move(onPress), std::move(isChecked));
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::removeLines()
|
||||
{
|
||||
content->body.removeLines();
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void Menu::onEvent(event_t event)
|
||||
{
|
||||
if (toolbar && (event == EVT_KEY_BREAK(KEY_PGDN) || event == EVT_KEY_LONG(KEY_PGDN))) {
|
||||
toolbar->onEvent(event);
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
deleteLater();
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_ENTER) && !multiple) {
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Menu::paint(BitmapBuffer * dc)
|
||||
{
|
||||
ModalWindow::paint(dc);
|
||||
|
||||
rect_t r(content->getRect());
|
||||
if (toolbar) {
|
||||
r.x = toolbar->left();
|
||||
r.w += toolbar->width();
|
||||
}
|
||||
dc->drawSolidRect(r.x - 1, r.y - 1, r.w + 2, r.h + 2, 1, COLOR_THEME_SECONDARY2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user