Full color support, rework the directory structure
This commit is contained in:
184
firmware/Application/Screens/MenuScreen.h
Normal file
184
firmware/Application/Screens/MenuScreen.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Max Regan
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#include "Bsp/macros.h"
|
||||
|
||||
#include "Application/SystemFonts.h"
|
||||
#include "Application/ScreenManager.h"
|
||||
#include "Application/Screens/Screen.h"
|
||||
|
||||
struct MenuScreenItem {
|
||||
|
||||
enum class Type {
|
||||
NONE,
|
||||
SCREEN,
|
||||
FUNCTION,
|
||||
BACK,
|
||||
};
|
||||
|
||||
MenuScreenItem()
|
||||
: m_text(nullptr)
|
||||
, m_type(Type::NONE)
|
||||
{}
|
||||
|
||||
MenuScreenItem(const char *item, Screen &m_screen)
|
||||
: m_text(item)
|
||||
, m_screen(&m_screen)
|
||||
, m_type(Type::SCREEN)
|
||||
{}
|
||||
|
||||
MenuScreenItem(const char *item, void (*function)())
|
||||
: m_text(item)
|
||||
, m_function(function)
|
||||
, m_type(Type::FUNCTION)
|
||||
{}
|
||||
|
||||
MenuScreenItem(const char *item)
|
||||
: m_text(item)
|
||||
, m_type(Type::BACK)
|
||||
{}
|
||||
|
||||
const char *m_text;
|
||||
union {
|
||||
Screen *m_screen;
|
||||
void (* m_function)();
|
||||
};
|
||||
Type m_type;
|
||||
};
|
||||
|
||||
class MenuScreen : public Screen {
|
||||
public:
|
||||
|
||||
static constexpr std::size_t MAX_ITEMS = 5;
|
||||
|
||||
MenuScreen(BSP::DisplayDriver &display,
|
||||
ScreenManager &manager,
|
||||
const char *title,
|
||||
std::initializer_list<MenuScreenItem> items)
|
||||
: m_driver(display)
|
||||
, m_manager(manager)
|
||||
, m_title(title)
|
||||
, m_items()
|
||||
, m_num_items{0}
|
||||
, m_selected{0}
|
||||
{
|
||||
for (auto &item : items) {
|
||||
m_items[m_num_items++] = item;
|
||||
|
||||
// Leave room for "back"
|
||||
if (m_num_items == MAX_ITEMS - 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
new (&m_items[m_num_items++]) MenuScreenItem("Back");
|
||||
}
|
||||
|
||||
void render() {
|
||||
const struct font &font = default_font;
|
||||
|
||||
//m_driver.clear();
|
||||
|
||||
uint32_t x = 0;
|
||||
uint32_t y = 0;
|
||||
m_driver.string_at(&x, y, m_title, &font);
|
||||
y += font.height + 1;
|
||||
|
||||
m_driver.draw_hline(0, y++, m_driver.get_width());
|
||||
m_driver.draw_hline(0, y++, m_driver.get_width());
|
||||
|
||||
|
||||
for (std::size_t i = 0; i < m_num_items; i++) {
|
||||
const char *spacer = " ";
|
||||
if (i == m_selected) {
|
||||
spacer = ">";
|
||||
}
|
||||
x = 0;
|
||||
m_driver.string_at(&x, y, spacer, &font);
|
||||
m_driver.string_at(&x, y, m_items[i].m_text, &font);
|
||||
y += font.height;
|
||||
}
|
||||
m_driver.refresh();
|
||||
}
|
||||
|
||||
Common::ReturnCode init() {
|
||||
return Common::ReturnCode::OK;
|
||||
}
|
||||
|
||||
Common::Schedule::NextTime execute() override {
|
||||
return Common::Schedule::NextTime::never();
|
||||
}
|
||||
|
||||
void enable() override {
|
||||
m_selected = 0;
|
||||
m_driver.clear();
|
||||
render();
|
||||
}
|
||||
|
||||
void disable() override {
|
||||
}
|
||||
|
||||
void notify_up_button() override {
|
||||
if (m_selected == 0) {
|
||||
m_selected = m_num_items - 1;
|
||||
} else {
|
||||
m_selected--;
|
||||
}
|
||||
|
||||
render();
|
||||
}
|
||||
|
||||
void notify_middle_button() override {
|
||||
MenuScreenItem &item = m_items[m_selected];
|
||||
if (item.m_type == MenuScreenItem::Type::SCREEN) {
|
||||
m_manager.push_screen(*item.m_screen);
|
||||
} else if (item.m_type == MenuScreenItem::Type::FUNCTION) {
|
||||
item.m_function();
|
||||
m_manager.pop_screen();
|
||||
} else if (item.m_type == MenuScreenItem::Type::BACK) {
|
||||
m_manager.pop_screen();
|
||||
}
|
||||
}
|
||||
|
||||
void notify_down_button() override {
|
||||
if (m_selected == m_num_items - 1) {
|
||||
m_selected = 0;
|
||||
} else {
|
||||
m_selected++;
|
||||
}
|
||||
|
||||
render();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
BSP::DisplayDriver &m_driver;
|
||||
ScreenManager &m_manager;
|
||||
const char *m_title;
|
||||
MenuScreenItem m_items[MAX_ITEMS];
|
||||
std::size_t m_num_items;
|
||||
std::size_t m_selected;
|
||||
};
|
||||
Reference in New Issue
Block a user