1 #include "select_list.h"
2 
3 #include "graphics/button.h"
4 #include "graphics/color.h"
5 #include "graphics/generic_button.h"
6 #include "graphics/lang_text.h"
7 #include "graphics/panel.h"
8 #include "graphics/text.h"
9 #include "graphics/window.h"
10 #include "input/input.h"
11 
12 #define MAX_ITEMS_PER_LIST 20
13 
14 enum {
15     MODE_TEXT,
16     MODE_GROUP,
17 };
18 
19 static void select_item(int id, int list_id);
20 
21 static generic_button buttons_list1[MAX_ITEMS_PER_LIST] = {
22     {5, 8, 190, 18, select_item, button_none, 0, 0},
23     {5, 28, 190, 18, select_item, button_none, 1, 0},
24     {5, 48, 190, 18, select_item, button_none, 2, 0},
25     {5, 68, 190, 18, select_item, button_none, 3, 0},
26     {5, 88, 190, 18, select_item, button_none, 4, 0},
27     {5, 108, 190, 18, select_item, button_none, 5, 0},
28     {5, 128, 190, 18, select_item, button_none, 6, 0},
29     {5, 148, 190, 18, select_item, button_none, 7, 0},
30     {5, 168, 190, 18, select_item, button_none, 8, 0},
31     {5, 188, 190, 18, select_item, button_none, 9, 0},
32     {5, 208, 190, 18, select_item, button_none, 10, 0},
33     {5, 228, 190, 18, select_item, button_none, 11, 0},
34     {5, 248, 190, 18, select_item, button_none, 12, 0},
35     {5, 268, 190, 18, select_item, button_none, 13, 0},
36     {5, 288, 190, 18, select_item, button_none, 14, 0},
37     {5, 308, 190, 18, select_item, button_none, 15, 0},
38     {5, 328, 190, 18, select_item, button_none, 16, 0},
39     {5, 348, 190, 18, select_item, button_none, 17, 0},
40     {5, 368, 190, 18, select_item, button_none, 18, 0},
41     {5, 388, 190, 18, select_item, button_none, 19, 0},
42 };
43 
44 static generic_button buttons_list2[MAX_ITEMS_PER_LIST] = {
45     {205, 8, 190, 18, select_item, button_none, 0, 1},
46     {205, 28, 190, 18, select_item, button_none, 1, 1},
47     {205, 48, 190, 18, select_item, button_none, 2, 1},
48     {205, 68, 190, 18, select_item, button_none, 3, 1},
49     {205, 88, 190, 18, select_item, button_none, 4, 1},
50     {205, 108, 190, 18, select_item, button_none, 5, 1},
51     {205, 128, 190, 18, select_item, button_none, 6, 1},
52     {205, 148, 190, 18, select_item, button_none, 7, 1},
53     {205, 168, 190, 18, select_item, button_none, 8, 1},
54     {205, 188, 190, 18, select_item, button_none, 9, 1},
55     {205, 208, 190, 18, select_item, button_none, 10, 1},
56     {205, 228, 190, 18, select_item, button_none, 11, 1},
57     {205, 248, 190, 18, select_item, button_none, 12, 1},
58     {205, 268, 190, 18, select_item, button_none, 13, 1},
59     {205, 288, 190, 18, select_item, button_none, 14, 1},
60     {205, 308, 190, 18, select_item, button_none, 15, 1},
61     {205, 328, 190, 18, select_item, button_none, 16, 1},
62     {205, 348, 190, 18, select_item, button_none, 17, 1},
63     {205, 368, 190, 18, select_item, button_none, 18, 1},
64     {205, 388, 190, 18, select_item, button_none, 19, 1},
65 };
66 
67 static struct {
68     int x;
69     int y;
70     int mode;
71     int group;
72     const uint8_t **items;
73     int num_items;
74     void (*callback)(int);
75     int focus_button_id;
76 } data;
77 
init_group(int x,int y,int group,int num_items,void (* callback)(int))78 static void init_group(int x, int y, int group, int num_items, void (*callback)(int))
79 {
80     data.x = x;
81     data.y = y;
82     data.mode = MODE_GROUP;
83     data.group = group;
84     data.num_items = num_items;
85     data.callback = callback;
86 }
87 
init_text(int x,int y,const uint8_t ** items,int num_items,void (* callback)(int))88 static void init_text(int x, int y, const uint8_t **items, int num_items, void (*callback)(int))
89 {
90     data.x = x;
91     data.y = y;
92     data.mode = MODE_TEXT;
93     data.items = items;
94     data.num_items = num_items;
95     data.callback = callback;
96 }
97 
items_in_first_list(void)98 static int items_in_first_list(void)
99 {
100     return data.num_items / 2 + data.num_items % 2;
101 }
102 
draw_item(int item_id,int x,int y,int selected)103 static void draw_item(int item_id, int x, int y, int selected)
104 {
105     color_t color = selected ? COLOR_FONT_BLUE : COLOR_BLACK;
106     if (data.mode == MODE_GROUP) {
107         lang_text_draw_centered_colored(data.group, item_id, data.x + x, data.y + y, 190, FONT_NORMAL_PLAIN, color);
108     } else {
109         text_draw_centered(data.items[item_id], data.x + x, data.y + y, 190, FONT_NORMAL_PLAIN, color);
110     }
111 }
112 
draw_foreground(void)113 static void draw_foreground(void)
114 {
115     if (data.num_items > MAX_ITEMS_PER_LIST) {
116         int max_first = items_in_first_list();
117         outer_panel_draw(data.x, data.y, 26, (20 * max_first + 24) / BLOCK_SIZE);
118         for (int i = 0; i < max_first; i++) {
119             draw_item(i, 5, 11 + 20 * i, i + 1 == data.focus_button_id);
120         }
121         for (int i = 0; i < data.num_items - max_first; i++) {
122             draw_item(i + max_first, 205, 11 + 20 * i, MAX_ITEMS_PER_LIST + i + 1 == data.focus_button_id);
123         }
124     } else {
125         outer_panel_draw(data.x, data.y, 13, (20 * data.num_items + 24) / BLOCK_SIZE);
126         for (int i = 0; i < data.num_items; i++) {
127             draw_item(i, 5, 11 + 20 * i, i + 1 == data.focus_button_id);
128         }
129     }
130 }
131 
handle_input(const mouse * m,const hotkeys * h)132 static void handle_input(const mouse *m, const hotkeys *h)
133 {
134     if (data.num_items > MAX_ITEMS_PER_LIST) {
135         int items_first = items_in_first_list();
136         if (generic_buttons_handle_mouse(m, data.x, data.y, buttons_list1, items_first, &data.focus_button_id)) {
137             return;
138         }
139         int second_id = 0;
140         generic_buttons_handle_mouse(m, data.x, data.y, buttons_list2, data.num_items - items_first, &second_id);
141         if (second_id > 0) {
142             data.focus_button_id = second_id + MAX_ITEMS_PER_LIST;
143         }
144     } else {
145         if (generic_buttons_handle_mouse(m, data.x, data.y, buttons_list1, data.num_items, &data.focus_button_id)) {
146             return;
147         }
148     }
149     if (input_go_back_requested(m, h)) {
150         window_go_back();
151     }
152 }
153 
select_item(int id,int list_id)154 void select_item(int id, int list_id)
155 {
156     window_go_back();
157     if (list_id == 0) {
158         data.callback(id);
159     } else {
160         data.callback(id + items_in_first_list());
161     }
162 }
163 
window_select_list_show(int x,int y,int group,int num_items,void (* callback)(int))164 void window_select_list_show(int x, int y, int group, int num_items, void (*callback)(int))
165 {
166     window_type window = {
167         WINDOW_SELECT_LIST,
168         window_draw_underlying_window,
169         draw_foreground,
170         handle_input
171     };
172     init_group(x, y, group, num_items, callback);
173     window_show(&window);
174 }
175 
window_select_list_show_text(int x,int y,const uint8_t ** items,int num_items,void (* callback)(int))176 void window_select_list_show_text(int x, int y, const uint8_t **items, int num_items, void (*callback)(int))
177 {
178     window_type window = {
179         WINDOW_SELECT_LIST,
180         window_draw_underlying_window,
181         draw_foreground,
182         handle_input
183     };
184     init_text(x, y, items, num_items, callback);
185     window_show(&window);
186 }
187