Menus can now have a title and a Cancel button
This commit is contained in:
+17
-6
@@ -108,6 +108,17 @@ class BitmapBufferBase
|
||||
this->offsetY = offsetY;
|
||||
}
|
||||
|
||||
inline void clearOffset()
|
||||
{
|
||||
setOffset(0, 0);
|
||||
}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
clearOffset();
|
||||
clearClippingRect();
|
||||
}
|
||||
|
||||
coord_t getOffsetX() const
|
||||
{
|
||||
return offsetX;
|
||||
@@ -146,8 +157,8 @@ class BitmapBufferBase
|
||||
inline const pixel_t * getPixelPtr(coord_t x, coord_t y) const
|
||||
{
|
||||
#if defined(PCBX10) && !defined(SIMU)
|
||||
x = width - x - 1;
|
||||
y = height - y - 1;
|
||||
x = _width - x - 1;
|
||||
y = _height - y - 1;
|
||||
#endif
|
||||
return &data[y * _width + x];
|
||||
}
|
||||
@@ -284,8 +295,8 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
||||
inline const pixel_t * getPixelPtr(coord_t x, coord_t y) const
|
||||
{
|
||||
#if defined(PCBX10) && !defined(SIMU)
|
||||
x = width - x - 1;
|
||||
y = height - y - 1;
|
||||
x = _width - x - 1;
|
||||
y = _height - y - 1;
|
||||
#endif
|
||||
return &data[y * _width + x];
|
||||
}
|
||||
@@ -293,8 +304,8 @@ class BitmapBuffer: public BitmapBufferBase<uint16_t>
|
||||
inline pixel_t * getPixelPtr(coord_t x, coord_t y)
|
||||
{
|
||||
#if defined(PCBX10) && !defined(SIMU)
|
||||
x = width - x - 1;
|
||||
y = height - y - 1;
|
||||
x = _width - x - 1;
|
||||
y = _height - y - 1;
|
||||
#endif
|
||||
return &data[y * _width + x];
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ void Choice::onEvent(event_t event)
|
||||
void Choice::openMenu()
|
||||
{
|
||||
auto menu = new Menu();
|
||||
if (!menuTitle.empty())
|
||||
menu->setTitle(menuTitle);
|
||||
|
||||
auto value = getValue();
|
||||
int count = 0;
|
||||
int current = -1;
|
||||
|
||||
+6
@@ -80,10 +80,16 @@ class Choice : public ChoiceBase {
|
||||
textHandler = std::move(handler);
|
||||
}
|
||||
|
||||
void setMenuTitle(const std::string value)
|
||||
{
|
||||
menuTitle = std::move(value);
|
||||
}
|
||||
|
||||
protected:
|
||||
const char * values = nullptr;
|
||||
int16_t vmin = 0;
|
||||
int16_t vmax = 0;
|
||||
std::string menuTitle;
|
||||
std::function<int16_t()> getValue;
|
||||
std::function<void(int16_t)> setValue;
|
||||
std::function<bool(int)> isValueAvailable;
|
||||
|
||||
@@ -101,6 +101,9 @@
|
||||
#define SCROLLBAR_COLOR COLOR(SCROLLBAR_COLOR_INDEX)
|
||||
#define MENU_COLOR COLOR(MENU_COLOR_INDEX)
|
||||
#define MENU_BGCOLOR COLOR(MENU_BGCOLOR_INDEX)
|
||||
#define MENU_LINE_COLOR COLOR(MENU_LINE_COLOR_INDEX)
|
||||
#define MENU_HIGHLIGHT_COLOR COLOR(MENU_HIGHLIGHT_COLOR_INDEX)
|
||||
#define MENU_HIGHLIGHT_BGCOLOR COLOR(MENU_HIGHLIGHT_BGCOLOR_INDEX)
|
||||
#define CUSTOM_COLOR COLOR(CUSTOM_COLOR_INDEX)
|
||||
|
||||
#endif
|
||||
|
||||
+51
-18
@@ -18,14 +18,16 @@
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
#include "font.h"
|
||||
|
||||
MenuWindow::MenuWindow(Menu * parent):
|
||||
Window(parent, {LCD_W / 2 - 100, LCD_H / 2, 200, 0}, OPAQUE)
|
||||
Window(parent, {(LCD_W - MENUS_WIDTH) / 2, (LCD_H - MENUS_WIDTH) / 2, MENUS_WIDTH, 0}, OPAQUE),
|
||||
body(this, {0, 0, width(), height()}, OPAQUE)
|
||||
{
|
||||
setFocus();
|
||||
body.setFocus();
|
||||
}
|
||||
|
||||
void MenuWindow::select(int index)
|
||||
void MenuBody::select(int index)
|
||||
{
|
||||
selectedIndex = index;
|
||||
if (innerHeight > height()) {
|
||||
@@ -35,7 +37,7 @@ void MenuWindow::select(int index)
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void MenuWindow::onEvent(event_t event)
|
||||
void MenuBody::onEvent(event_t event)
|
||||
{
|
||||
TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event);
|
||||
|
||||
@@ -61,7 +63,7 @@ void MenuWindow::onEvent(event_t event)
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool MenuWindow::onTouchEnd(coord_t x, coord_t y)
|
||||
bool MenuBody::onTouchEnd(coord_t x, coord_t y)
|
||||
{
|
||||
int index = y / MENUS_LINE_HEIGHT;
|
||||
lines[index].onPress();
|
||||
@@ -69,13 +71,18 @@ bool MenuWindow::onTouchEnd(coord_t x, coord_t y)
|
||||
}
|
||||
#endif
|
||||
|
||||
void MenuWindow::paint(BitmapBuffer * dc)
|
||||
void MenuBody::paint(BitmapBuffer * dc)
|
||||
{
|
||||
int width = (innerHeight > height() ? 195 : 200);
|
||||
dc->clear(MENU_BGCOLOR);
|
||||
for (auto i = 0; i < lines.size(); i++) {
|
||||
|
||||
for (auto i = 0; i < (int)lines.size(); i++) {
|
||||
auto & line = lines[i];
|
||||
LcdFlags flags = (selectedIndex == (int) i ? HIGHLIGHT_COLOR : MENU_COLOR);
|
||||
LcdFlags flags = MENU_COLOR;
|
||||
if (selectedIndex == i) {
|
||||
flags = MENU_HIGHLIGHT_COLOR;
|
||||
if (MENU_HIGHLIGHT_BGCOLOR != MENU_BGCOLOR)
|
||||
dc->drawSolidFilledRect(0, i * MENUS_LINE_HEIGHT, width(), MENUS_LINE_HEIGHT, MENU_HIGHLIGHT_BGCOLOR);
|
||||
}
|
||||
if (line.drawLine) {
|
||||
line.drawLine(dc, 0, i * MENUS_LINE_HEIGHT /*+ (lineHeight - 20) / 2*/, flags);
|
||||
}
|
||||
@@ -84,38 +91,64 @@ void MenuWindow::paint(BitmapBuffer * dc)
|
||||
dc->drawText(10, i * MENUS_LINE_HEIGHT + (MENUS_LINE_HEIGHT - 20) / 2, text[0] == '\0' ? "---" : text, flags);
|
||||
}
|
||||
if (i > 0) {
|
||||
dc->drawSolidHorizontalLine(0, i * MENUS_LINE_HEIGHT - 1, width, DISABLE_COLOR);
|
||||
dc->drawSolidHorizontalLine(0, i * MENUS_LINE_HEIGHT - 1, MENUS_WIDTH, MENU_LINE_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuWindow::paint(BitmapBuffer * dc)
|
||||
{
|
||||
// the background
|
||||
dc->clear(MENU_BGCOLOR);
|
||||
|
||||
// the title
|
||||
if (!title.empty()) {
|
||||
dc->drawText(MENUS_WIDTH / 2, (MENUS_HEADER_HEIGHT - getFontHeight(FONT(BOLD))) / 2, title.c_str(), CENTERED | FONT(BOLD));
|
||||
dc->drawSolidHorizontalLine(0, MENUS_HEADER_HEIGHT - 1, MENUS_WIDTH, MENU_LINE_COLOR);
|
||||
}
|
||||
|
||||
// the cancel button
|
||||
if (MENUS_FOOTER_HEIGHT > 0) {
|
||||
dc->drawText(MENUS_WIDTH / 2, height() - MENUS_FOOTER_HEIGHT + (MENUS_FOOTER_HEIGHT - getFontHeight(FONT(BOLD))) / 2, "Cancel", CENTERED);
|
||||
dc->drawSolidHorizontalLine(0, height() - MENUS_FOOTER_HEIGHT, MENUS_WIDTH, MENU_LINE_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::updatePosition()
|
||||
{
|
||||
if (!toolbar) {
|
||||
// there is no navigation bar at the left, we may center the window on screen
|
||||
int count = min<int>(MENUS_MAX_LINES, menuWindow.lines.size());
|
||||
coord_t h = count * MENUS_LINE_HEIGHT - 1;
|
||||
menuWindow.setTop((LCD_H - h) / 2 + 20);
|
||||
menuWindow.setHeight(h);
|
||||
auto headerHeight = menuWindow.title.empty() ? 0 : MENUS_HEADER_HEIGHT;
|
||||
auto bodyHeight = limit<coord_t>(MENUS_MIN_HEIGHT, menuWindow.body.lines.size() * MENUS_LINE_HEIGHT - 1, MENUS_MAX_HEIGHT);
|
||||
menuWindow.setTop((LCD_H - headerHeight - bodyHeight - MENUS_FOOTER_HEIGHT) / 2 + MENUS_OFFSET_TOP);
|
||||
menuWindow.setHeight(headerHeight + bodyHeight + MENUS_FOOTER_HEIGHT);
|
||||
menuWindow.body.setTop(headerHeight);
|
||||
menuWindow.body.setHeight(bodyHeight);
|
||||
}
|
||||
menuWindow.setInnerHeight(menuWindow.lines.size() * MENUS_LINE_HEIGHT - 1);
|
||||
menuWindow.body.setInnerHeight(menuWindow.body.lines.size() * MENUS_LINE_HEIGHT - 1);
|
||||
}
|
||||
|
||||
void Menu::setTitle(const std::string text)
|
||||
{
|
||||
menuWindow.setTitle(text);
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::addLine(const std::string & text, std::function<void()> onPress)
|
||||
{
|
||||
menuWindow.addLine(text, std::move(onPress));
|
||||
menuWindow.body.addLine(text, std::move(onPress));
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::addCustomLine(std::function<void(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags flags)> drawLine, std::function<void()> onPress)
|
||||
{
|
||||
menuWindow.addCustomLine(drawLine, std::move(onPress));
|
||||
menuWindow.body.addCustomLine(drawLine, std::move(onPress));
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void Menu::removeLines()
|
||||
{
|
||||
menuWindow.removeLines();
|
||||
menuWindow.body.removeLines();
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
|
||||
+54
-23
@@ -26,12 +26,14 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
class Menu;
|
||||
class MenuWindow;
|
||||
|
||||
class MenuWindow: public Window {
|
||||
class MenuBody: public Window {
|
||||
friend class MenuWindow;
|
||||
friend class Menu;
|
||||
|
||||
class MenuLine {
|
||||
friend class MenuWindow;
|
||||
friend class MenuBody;
|
||||
|
||||
public:
|
||||
MenuLine(std::string text, std::function<void()> onPress):
|
||||
@@ -57,19 +59,21 @@ class MenuWindow: public Window {
|
||||
};
|
||||
|
||||
public:
|
||||
explicit MenuWindow(Menu * parent);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() override
|
||||
MenuBody(Window * parent, const rect_t & rect, WindowFlags flags):
|
||||
Window(parent, rect, flags)
|
||||
{
|
||||
return "MenuWindow";
|
||||
setPageHeight(MENUS_LINE_HEIGHT);
|
||||
}
|
||||
|
||||
void select(int index);
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
|
||||
void setCancelHandler(std::function<void()> handler)
|
||||
{
|
||||
onCancel = handler;
|
||||
}
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
#endif
|
||||
|
||||
void addLine(const std::string & text, std::function<void()> onPress)
|
||||
{
|
||||
@@ -89,18 +93,13 @@ class MenuWindow: public Window {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void select(int index);
|
||||
void setCancelHandler(std::function<void()> handler)
|
||||
{
|
||||
onCancel = handler;
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::vector<MenuLine> lines;
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
@@ -111,6 +110,36 @@ class MenuWindow: public Window {
|
||||
std::function<void()> onCancel;
|
||||
};
|
||||
|
||||
class MenuWindow: public Window {
|
||||
friend class Menu;
|
||||
|
||||
public:
|
||||
explicit MenuWindow(Menu * parent);
|
||||
|
||||
~MenuWindow() override
|
||||
{
|
||||
body.detach();
|
||||
}
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() override
|
||||
{
|
||||
return "MenuWindow";
|
||||
}
|
||||
#endif
|
||||
|
||||
void setTitle(const std::string text)
|
||||
{
|
||||
title = std::move(text);
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
protected:
|
||||
MenuBody body;
|
||||
std::string title;
|
||||
};
|
||||
|
||||
class Menu : public Window {
|
||||
public:
|
||||
Menu() :
|
||||
@@ -129,7 +158,7 @@ class Menu : public Window {
|
||||
|
||||
void setCancelHandler(std::function<void()> handler)
|
||||
{
|
||||
menuWindow.setCancelHandler(handler);
|
||||
menuWindow.body.setCancelHandler(handler);
|
||||
}
|
||||
|
||||
void deleteLater()
|
||||
@@ -157,15 +186,17 @@ class Menu : public Window {
|
||||
menuWindow.setHeight(toolbar->height());
|
||||
}
|
||||
|
||||
void setTitle(const std::string text);
|
||||
|
||||
void addLine(const std::string & text, std::function<void()> onPress);
|
||||
|
||||
void addCustomLine(std::function<void(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags flags)> drawLine, std::function<void()> onPress);
|
||||
|
||||
void removeLines();
|
||||
|
||||
void select(int index)
|
||||
inline void select(int index)
|
||||
{
|
||||
menuWindow.select(index);
|
||||
menuWindow.body.select(index);
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
|
||||
Reference in New Issue
Block a user