#include <stdlib.h>
-#include <SDL2/SDL.h>
+#include <SDL.h>
#include "system/stacktrace.h"
#include "system/lt.h"
#include "system/str.h"
#include "math/point.h"
#include "game/sprite_font.h"
+#include "system/log.h"
#include "./list_selector.h"
const Sprite_font *sprite_font;
const char **items;
size_t count;
+ size_t cursor;
+ int selected_item;
+ Vec position;
+ Vec font_scale;
+ float padding_bottom;
};
ListSelector *create_list_selector(const Sprite_font *sprite_font,
const char *items[],
- size_t count)
+ size_t count,
+ Vec font_scale,
+ float padding_bottom)
{
trace_assert(items);
Lt *lt = create_lt();
- if (lt == NULL) {
- return NULL;
- }
- ListSelector *list_selector = PUSH_LT(lt, nth_alloc(sizeof(ListSelector)), free);
+ ListSelector *list_selector = PUSH_LT(lt, nth_calloc(1, sizeof(ListSelector)), free);
if (list_selector == NULL) {
RETURN_LT(lt, NULL);
}
list_selector->lt = lt;
list_selector->sprite_font = sprite_font;
-
- list_selector->items = PUSH_LT(lt, nth_calloc(count, sizeof(const char*)), free);
- if (list_selector->items == NULL) {
- RETURN_LT(lt, NULL);
- }
-
- for (size_t i = 0; i < count; ++i) {
- list_selector->items[i] = PUSH_LT(lt, string_duplicate(items[i], NULL), free);
- if (list_selector->items[i] == NULL) {
- RETURN_LT(lt, NULL);
- }
- }
-
+ list_selector->items = items;
list_selector->count = count;
+ list_selector->cursor = 0;
+ list_selector->selected_item = -1;
+ list_selector->position = vec(0.0f, 0.0f);
+ list_selector->font_scale = font_scale;
+ list_selector->padding_bottom = padding_bottom;
return list_selector;
}
}
int list_selector_render(const ListSelector *list_selector,
- SDL_Renderer *renderer,
- Vec position,
- Vec font_scale,
- float padding_bottom)
+ SDL_Renderer *renderer)
{
trace_assert(list_selector);
trace_assert(renderer);
for (size_t i = 0; i < list_selector->count; ++i) {
+ const Vec current_position = vec_sum(
+ list_selector->position,
+ vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * list_selector->font_scale.y + list_selector->padding_bottom)));
+
if (sprite_font_render_text(
list_selector->sprite_font,
renderer,
- vec_sum(
- position,
- vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * font_scale.y + padding_bottom))),
- font_scale,
+ current_position,
+ list_selector->font_scale,
rgba(1.0f, 1.0f, 1.0f, 1.0f),
list_selector->items[i]) < 0) {
return -1;
}
+
+ if (i == list_selector->cursor) {
+ SDL_Rect boundary_box = rect_for_sdl(
+ sprite_font_boundary_box(
+ list_selector->sprite_font,
+ current_position,
+ list_selector->font_scale,
+ list_selector->items[i]));
+ if (SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) < 0) {
+ return -1;
+ }
+
+ if (SDL_RenderDrawRect(renderer, &boundary_box) < 0) {
+ return -1;
+ }
+ }
}
return 0;
{
trace_assert(list_selector);
trace_assert(event);
+
+ switch (event->type) {
+ case SDL_KEYDOWN:
+ switch (event->key.keysym.sym) {
+ case SDLK_UP:
+ if (list_selector->cursor > 0) {
+ list_selector->cursor--;
+ }
+ break;
+ case SDLK_DOWN:
+ if (list_selector->cursor < list_selector->count - 1) {
+ list_selector->cursor++;
+ }
+ break;
+ case SDLK_RETURN:
+ list_selector->selected_item = (int) list_selector->cursor;
+ break;
+ }
+ break;
+
+ case SDL_MOUSEMOTION: {
+ const Vec mouse_pos = vec((float)event->motion.x, (float)event->motion.y);
+ Vec position = list_selector->position;
+
+ for (size_t i = 0; i < list_selector->count; ++i) {
+ Rect boundary_box = sprite_font_boundary_box(
+ list_selector->sprite_font,
+ position,
+ list_selector->font_scale,
+ list_selector->items[i]);
+
+ if (rect_contains_point(boundary_box, mouse_pos)) {
+ list_selector->cursor = i;
+ }
+
+ position.y += boundary_box.h + list_selector->padding_bottom;
+ }
+ } break;
+
+ case SDL_MOUSEBUTTONDOWN: {
+ switch (event->button.button) {
+ case SDL_BUTTON_LEFT: {
+ list_selector->selected_item = (int) list_selector->cursor;
+ } break;
+ }
+ } break;
+ }
+
return 0;
}
-const char *list_selector_selected(const ListSelector *list_selector)
+int list_selector_selected(const ListSelector *list_selector)
{
trace_assert(list_selector);
- return NULL;
+ return list_selector->selected_item;
+}
+
+void list_selector_clean_selection(ListSelector *list_selector)
+{
+ trace_assert(list_selector);
+ list_selector->selected_item = -1;
+}
+
+void list_selector_move(ListSelector *list_selector, Vec position)
+{
+ list_selector->position = position;
}