Select a mission
This commit is contained in:
		@ -1,11 +1,13 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "View.h"
 | 
			
		||||
#include "events.h"
 | 
			
		||||
#include "widgets.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL2/SDL.h>
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <queue>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
class AMI final : public View {
 | 
			
		||||
@ -14,6 +16,7 @@ public:
 | 
			
		||||
  ~AMI();
 | 
			
		||||
 | 
			
		||||
  void draw() override;
 | 
			
		||||
  void handle_events(std::queue<Event>& events) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  TTF_Font* avenir;
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,18 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "events.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL2/SDL.h>
 | 
			
		||||
 | 
			
		||||
#include <queue>
 | 
			
		||||
 | 
			
		||||
class View {
 | 
			
		||||
public:
 | 
			
		||||
  View(SDL_Renderer* renderer);
 | 
			
		||||
  virtual ~View();
 | 
			
		||||
 | 
			
		||||
  virtual void draw() = 0;
 | 
			
		||||
  virtual void handle_events(std::queue<Event>& events) = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  SDL_Renderer* renderer;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								include/events.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								include/events.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
enum class Event { Next, Prev, Confirm };
 | 
			
		||||
@ -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<Widget*> elements;
 | 
			
		||||
 | 
			
		||||
  void place_element(Widget* element, int index);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								src/AMI.cpp
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/AMI.cpp
									
									
									
									
									
								
							@ -1,10 +1,14 @@
 | 
			
		||||
#include "AMI.h"
 | 
			
		||||
 | 
			
		||||
#include "defines.h"
 | 
			
		||||
#include "events.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "widgets.h"
 | 
			
		||||
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
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<Event>& 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));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								src/App.cpp
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/App.cpp
									
									
									
									
									
								
							@ -1,11 +1,15 @@
 | 
			
		||||
#include "App.h"
 | 
			
		||||
 | 
			
		||||
#include "AMI.h"
 | 
			
		||||
#include "events.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL2/SDL.h>
 | 
			
		||||
#include <SDL2/SDL_events.h>
 | 
			
		||||
#include <SDL2/SDL_image.h>
 | 
			
		||||
#include <SDL2/SDL_keycode.h>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
#include <queue>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
App::App() : view{AppView::AMI} { init_sdl(); }
 | 
			
		||||
@ -48,12 +52,37 @@ int App::run() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void App::handle_events() {
 | 
			
		||||
  std::queue<Event> 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() {
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,19 @@
 | 
			
		||||
#include <SDL2/SDL_image.h>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user