Fix screen stack popping and add a menu
This commit is contained in:
163
MenuScreen.h
Normal file
163
MenuScreen.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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 "macros.h"
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#include "SystemFonts.h"
|
||||
#include "ScreenManager.h"
|
||||
#include "Screen.h"
|
||||
|
||||
struct MenuScreenItem {
|
||||
|
||||
enum class Type{
|
||||
NONE,
|
||||
SCREEN,
|
||||
BACK,
|
||||
};
|
||||
|
||||
MenuScreenItem()
|
||||
: m_text(nullptr)
|
||||
, m_screen(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)
|
||||
: m_text(item)
|
||||
, m_screen(nullptr)
|
||||
, m_type(Type::BACK)
|
||||
{}
|
||||
|
||||
const char *m_text;
|
||||
Screen *m_screen;
|
||||
Type m_type;
|
||||
};
|
||||
|
||||
class MenuScreen : public Screen {
|
||||
public:
|
||||
|
||||
static constexpr std::size_t MAX_ITEMS = 10;
|
||||
|
||||
MenuScreen(BSP::DisplayDriver &display,
|
||||
ScreenManager &manager,
|
||||
std::initializer_list<MenuScreenItem> items)
|
||||
: m_driver(display)
|
||||
, m_manager(manager)
|
||||
, 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;
|
||||
// const uint32_t font_width = default_font_width;
|
||||
|
||||
m_driver.clear();
|
||||
|
||||
for (std::size_t i = 0; i < m_num_items; i++) {
|
||||
uint32_t x = 0;
|
||||
uint32_t y = 8 + (font.size + 8) * i;
|
||||
const char *spacer = " ";
|
||||
if (i == m_selected) {
|
||||
spacer = ">";
|
||||
}
|
||||
m_driver.string_at(&x, y, spacer, &font);
|
||||
m_driver.string_at(&x, y, m_items[i].m_text, &font);
|
||||
}
|
||||
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;
|
||||
render();
|
||||
}
|
||||
|
||||
void disable() override {
|
||||
m_driver.clear();
|
||||
}
|
||||
|
||||
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::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;
|
||||
MenuScreenItem m_items[MAX_ITEMS];
|
||||
std::size_t m_num_items;
|
||||
std::size_t m_selected;
|
||||
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user