]> git.lizzy.rs Git - nothing.git/blob - src/ui/list_selector.c
(#606) Center ListSelector in LevelPicker
[nothing.git] / src / ui / list_selector.c
1 #include <stdlib.h>
2
3 #include <SDL2/SDL.h>
4
5 #include "system/stacktrace.h"
6 #include "system/lt.h"
7 #include "system/nth_alloc.h"
8 #include "system/str.h"
9 #include "math/point.h"
10 #include "game/sprite_font.h"
11
12 #include "./list_selector.h"
13
14 struct ListSelector
15 {
16     Lt *lt;
17     const Sprite_font *sprite_font;
18     const char **items;
19     size_t count;
20 };
21
22 ListSelector *create_list_selector(const Sprite_font *sprite_font,
23                                    const char *items[],
24                                    size_t count)
25 {
26     trace_assert(items);
27
28     Lt *lt = create_lt();
29     if (lt == NULL) {
30         return NULL;
31     }
32
33     ListSelector *list_selector = PUSH_LT(lt, nth_alloc(sizeof(ListSelector)), free);
34     if (list_selector == NULL) {
35         RETURN_LT(lt, NULL);
36     }
37     list_selector->lt = lt;
38
39     list_selector->sprite_font = sprite_font;
40
41     list_selector->items = PUSH_LT(lt, nth_calloc(count, sizeof(const char*)), free);
42     if (list_selector->items == NULL) {
43         RETURN_LT(lt, NULL);
44     }
45
46     for (size_t i = 0; i < count; ++i) {
47         list_selector->items[i] = PUSH_LT(lt, string_duplicate(items[i], NULL), free);
48         if (list_selector->items[i] == NULL) {
49             RETURN_LT(lt, NULL);
50         }
51     }
52
53     list_selector->count = count;
54
55     return list_selector;
56 }
57
58 void destroy_list_selector(ListSelector *list_selector)
59 {
60     trace_assert(list_selector);
61     RETURN_LT0(list_selector->lt);
62 }
63
64 int list_selector_render(const ListSelector *list_selector,
65                          SDL_Renderer *renderer,
66                          Vec position,
67                          Vec font_scale,
68                          float padding_bottom)
69 {
70     trace_assert(list_selector);
71     trace_assert(renderer);
72
73     for (size_t i = 0; i < list_selector->count; ++i) {
74         if (sprite_font_render_text(
75                 list_selector->sprite_font,
76                 renderer,
77                 vec_sum(
78                     position,
79                     vec(0.0f, (float) i * ((float) FONT_CHAR_HEIGHT * font_scale.y + padding_bottom))),
80                 font_scale,
81                 rgba(1.0f, 1.0f, 1.0f, 1.0f),
82                 list_selector->items[i]) < 0) {
83             return -1;
84         }
85     }
86
87     return 0;
88 }
89
90 Vec list_selector_size(const ListSelector *list_selector,
91                        Vec font_scale,
92                        float padding_bottom)
93 {
94     trace_assert(list_selector);
95
96     Vec result = vec(0.0f, 0.0f);
97
98     for (size_t i = 0; i < list_selector->count; ++i) {
99         Rect boundary_box = sprite_font_boundary_box(
100             list_selector->sprite_font,
101             vec(0.0f, 0.0f),
102             font_scale,
103             list_selector->items[i]);
104
105         result.x = fmaxf(result.x, boundary_box.w);
106         result.y += boundary_box.y + padding_bottom;
107     }
108
109     return result;
110 }
111
112 int list_selector_update(ListSelector *list_selector, float delta_time)
113 {
114     trace_assert(list_selector);
115     (void) delta_time;
116
117     return 0;
118 }
119
120 int list_selector_event(ListSelector *list_selector, const SDL_Event *event)
121 {
122     trace_assert(list_selector);
123     trace_assert(event);
124     return 0;
125 }
126
127 const char *list_selector_selected(const ListSelector *list_selector)
128 {
129     trace_assert(list_selector);
130     return NULL;
131 }