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