From 654c71f3ee7b94e94853d02cdaa12b0b4a7d4ffc Mon Sep 17 00:00:00 2001 From: Jasper Date: Sun, 22 May 2022 14:24:40 +0200 Subject: [PATCH] Select a mission --- include/AMI.h | 3 +++ include/View.h | 5 +++++ include/events.h | 3 +++ include/widgets.h | 6 ++++++ src/AMI.cpp | 25 +++++++++++++++++++++++ src/App.cpp | 29 ++++++++++++++++++++++++++ src/widgets.cpp | 52 +++++++++++++++++++++++++++++++++++++++++------ 7 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 include/events.h diff --git a/include/AMI.h b/include/AMI.h index 63fb35d..3e8f913 100644 --- a/include/AMI.h +++ b/include/AMI.h @@ -1,11 +1,13 @@ #pragma once #include "View.h" +#include "events.h" #include "widgets.h" #include #include +#include #include class AMI final : public View { @@ -14,6 +16,7 @@ public: ~AMI(); void draw() override; + void handle_events(std::queue& events) override; private: TTF_Font* avenir; diff --git a/include/View.h b/include/View.h index e1943c1..ae8ac98 100644 --- a/include/View.h +++ b/include/View.h @@ -1,13 +1,18 @@ #pragma once +#include "events.h" + #include +#include + class View { public: View(SDL_Renderer* renderer); virtual ~View(); virtual void draw() = 0; + virtual void handle_events(std::queue& events) = 0; protected: SDL_Renderer* renderer; diff --git a/include/events.h b/include/events.h new file mode 100644 index 0000000..91355ad --- /dev/null +++ b/include/events.h @@ -0,0 +1,3 @@ +#pragma once + +enum class Event { Next, Prev, Confirm }; \ No newline at end of file diff --git a/include/widgets.h b/include/widgets.h index 98bf83b..f1d7fb0 100644 --- a/include/widgets.h +++ b/include/widgets.h @@ -85,10 +85,16 @@ public: virtual void draw() override; + void select_next(); + void select_prev(); + size_t get_selection(); + protected: int element_height; Alignment element_alignment; + size_t selection; + std::vector elements; void place_element(Widget* element, int index); diff --git a/src/AMI.cpp b/src/AMI.cpp index 763efe0..cf68804 100644 --- a/src/AMI.cpp +++ b/src/AMI.cpp @@ -1,10 +1,14 @@ #include "AMI.h" #include "defines.h" +#include "events.h" #include "util.h" #include "widgets.h" +#include + #include +#include #include constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp"; @@ -62,4 +66,25 @@ void AMI::draw() { for (const auto& widget : widgets) { widget->draw(); } +} + +void AMI::handle_events(std::queue& events) { + while (!events.empty()) { + Event e = events.front(); + events.pop(); + switch (e) { + case Event::Next: + missions_widget->select_next(); + break; + case Event::Prev: + missions_widget->select_prev(); + break; + case Event::Confirm: + std::cout << fmt::format("Selected mission {}\n", + missions_widget->get_selection()); + break; + default: + throw std::runtime_error(fmt::format("Unknown event: {}", (int)e)); + } + } } \ No newline at end of file diff --git a/src/App.cpp b/src/App.cpp index 183bc59..cf61cce 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -1,11 +1,15 @@ #include "App.h" #include "AMI.h" +#include "events.h" #include +#include #include +#include #include +#include #include App::App() : view{AppView::AMI} { init_sdl(); } @@ -48,12 +52,37 @@ int App::run() { } void App::handle_events() { + std::queue events; SDL_Event e; while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { running = false; + } else if (e.type == SDL_KEYUP) { + switch (e.key.keysym.sym) { + case SDLK_DOWN: + case SDLK_RIGHT: + events.push(Event::Next); + break; + case SDLK_UP: + case SDLK_LEFT: + events.push(Event::Prev); + break; + case SDLK_RETURN: + case SDLK_KP_ENTER: + events.push(Event::Confirm); + break; + // We can just ignore other keypresses, so no need for a default clause + } } } + + switch (view) { + case AppView::AMI: + ami->handle_events(events); + break; + default: + throw std::runtime_error(fmt::format("Unknown view: {}", (int)view)); + } } void App::render() { diff --git a/src/widgets.cpp b/src/widgets.cpp index d2861a5..04eb529 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -7,8 +7,19 @@ #include #include +#include #include +constexpr uint8_t LIST_SELECTION_BG_R = 0x77; +constexpr uint8_t LIST_SELECTION_BG_G = 0x33; +constexpr uint8_t LIST_SELECTION_BG_B = 0x33; +constexpr uint8_t LIST_OTHER_BG_R = 0x22; +constexpr uint8_t LIST_OTHER_BG_G = 0x22; +constexpr uint8_t LIST_OTHER_BG_B = 0x22; +constexpr uint8_t LIST_NORMAL_BG_R = 0x00; +constexpr uint8_t LIST_NORMAL_BG_G = 0x00; +constexpr uint8_t LIST_NORMAL_BG_B = 0x00; + PositionInfo::PositionInfo() : x{0}, y{0}, align{Alignment::LEFT} {} Widget::Widget(SDL_Renderer* renderer) : renderer{renderer}, rect{0, 0, 0, 0} {} @@ -144,7 +155,7 @@ SDL_Texture* TextWidget::generate_text(const std::string& text) { ListWidget::ListWidget(SDL_Renderer* renderer, int element_height, Alignment element_alignment) : Widget{renderer}, element_height{element_height}, - element_alignment{element_alignment} {} + element_alignment{element_alignment}, selection{0} {} ListWidget::~ListWidget() {} @@ -163,12 +174,19 @@ void ListWidget::draw() { // Since the elements are sorted, we can stop the loop now. break; } - if (i % 2 == 1) { - SDL_SetRenderDrawColor(renderer, 0x11, 0x11, 0x11, 0xFF); - SDL_Rect fill_rect = { - .x = pos.x, .y = element_pos.y, .w = rect.w, .h = element_height}; - SDL_RenderFillRect(renderer, &fill_rect); + if (i == selection) { + SDL_SetRenderDrawColor(renderer, LIST_SELECTION_BG_R, LIST_SELECTION_BG_G, + LIST_SELECTION_BG_B, 0xFF); + } else if (i % 2 == 1) { + SDL_SetRenderDrawColor(renderer, LIST_OTHER_BG_R, LIST_OTHER_BG_G, + LIST_OTHER_BG_B, 0xFF); + } else { + SDL_SetRenderDrawColor(renderer, LIST_NORMAL_BG_R, LIST_NORMAL_BG_G, + LIST_NORMAL_BG_B, 0xFF); } + SDL_Rect fill_rect = { + .x = pos.x, .y = element_pos.y, .w = rect.w, .h = element_height}; + SDL_RenderFillRect(renderer, &fill_rect); element->draw(); if (i != elements.size() - 1) { int border_y = element_pos.y + element->get_height(); @@ -178,6 +196,28 @@ void ListWidget::draw() { } } +void ListWidget::select_next() { + size_t n = elements.size(); + if (n == 0) { + return; + } + selection = (selection + 1) % n; +} + +void ListWidget::select_prev() { + size_t n = elements.size(); + if (n == 0) { + return; + } + if (selection == 0) { + selection = n - 1; + } else { + selection = selection - 1; + } +} + +size_t ListWidget::get_selection() { return selection; } + void ListWidget::place_element(Widget* element, int index) { int x = rect.x; switch (element_alignment) {