Small bugfixes.
[xuni.git] / src / widget / listbox.c
blob459e73788632e8fd25718549ef989223cde32a4e
1 /*! \file listbox.c
3 */
5 #include <string.h>
7 #include "../graphics.h"
8 #include "../error.h"
9 #include "../memory.h"
10 #include "widgets.h"
11 #include "dump.h"
12 #include "listbox.h"
13 #include "box.h"
14 #include "label.h"
15 #include "scrollbar.h"
16 #include "panel.h"
18 static void free_listbox(struct xuni_t *xuni, struct widget_t *widget);
19 static void reposition_listbox(struct xuni_t *xuni, struct widget_t *widget);
20 static void rescale_listbox(struct xuni_t *xuni, struct widget_t *widget);
21 static void paint_listbox(struct xuni_t *xuni, struct widget_t *widget);
23 void listbox_widget_event(struct xuni_t *xuni, struct widget_t *widget,
24 enum widget_event_t event) {
26 static void (*function[])(struct xuni_t *xuni, struct widget_t *widget)
27 = {
29 free_listbox,
31 paint_listbox,
32 reposition_listbox,
33 rescale_listbox
36 call_widget_event_func(xuni, widget, event, function,
37 sizeof(function) / sizeof(*function));
40 double real_scale_width(struct widget_t *widget) {
41 double w = 1.0;
43 w *= widget->pos->scale.w / 100.0;
44 if(widget->base) w *= real_scale_width(widget->base);
46 return w;
49 double real_scale_height(struct widget_t *widget) {
50 double h = 1.0;
52 h *= widget->pos->scale.h / 100.0;
53 if(widget->base) h *= real_scale_height(widget->base);
55 return h;
58 double calculate_scrollbar_width(struct widget_t *widget,
59 struct xuni_t *xuni) {
61 double ratio;
63 ratio = (widget->pos->scale.w / 100.0 * xuni->smode->screen->w)
64 / (widget->pos->scale.h / 100.0 * xuni->smode->screen->h);
66 return (100.0 / 15.0) / (real_scale_width(widget));
69 double calculate_scrollbar_height(struct widget_t *widget,
70 struct xuni_t *xuni) {
72 return (100.0 / 15.0) / (real_scale_height(widget));
75 void init_listbox(struct widget_t *widget, struct xuni_t *xuni,
76 enum scrollbar_use_t allow, enum scrollbar_use_t force) {
78 double width = calculate_scrollbar_width(widget, xuni);
79 double height = calculate_scrollbar_height(widget, xuni);
80 /*double boxsize = 100.0 / 20.0;*/
81 double boxsize = get_box_width(xuni, xuni->theme->current) * 4;
82 double boxsizeh = get_box_height(xuni, xuni->theme->current) * 4;
83 int w = 0, h = 0;
85 /*printf("%f %f\n", boxsize, boxsizeh);*/
87 if(force & SCROLLBAR_USE_VERTICAL) w = width;
88 if(force & SCROLLBAR_USE_HORIZONTAL) h = height;
90 widget->type = WIDGET_LISTBOX;
91 widget->p.listbox = xuni_memory_allocate(sizeof(*widget->p.listbox));
93 widget->p.listbox->scroll.allow = allow;
94 widget->p.listbox->scroll.force = force;
95 widget->p.listbox->scroll.current = force;
97 widget->p.listbox->maxwidth = 100;
98 /*widget->p.listbox->yclip = 0;*/
100 add_allocate_widget_compose(widget, "listbox area");
102 init_widget_pos(last_compose_widget(widget),
103 0, 0, 100.0 - w, 100.0 - h, POS_PACK_NONE);
104 init_box(last_compose_widget(widget), BOX_STYLE_ALWAYSIN, 0);
105 last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_INDEPENDENT;
107 add_allocate_widget_compose(widget, "listbox vertical scrollbar");
109 init_widget_pos(last_compose_widget(widget),
110 100.0 - width, 0, width, 100.0 - h, POS_PACK_NONE);
111 init_scrollbar(last_compose_widget(widget), xuni, widget->pos->scale.h,
112 SCROLLBAR_ORIENTATION_VERTICAL);
113 if((force & SCROLLBAR_USE_VERTICAL) == 0) {
114 last_compose_widget(widget)->visibility
115 &= ~WIDGET_VISIBILITY_VISIBLE;
118 add_allocate_widget_compose(widget, "listbox horizontal scrollbar");
120 init_widget_pos(last_compose_widget(widget),
121 0, 100.0 - height, 100.0 - w, height, POS_PACK_NONE);
122 init_scrollbar(last_compose_widget(widget), xuni, widget->pos->scale.h,
123 SCROLLBAR_ORIENTATION_HORIZONTAL);
124 if((force & SCROLLBAR_USE_HORIZONTAL) == 0) {
125 last_compose_widget(widget)->visibility
126 &= ~WIDGET_VISIBILITY_VISIBLE;
129 add_allocate_widget_compose(widget, "listbox data");
131 init_widget_pos(last_compose_widget(widget), boxsize, boxsizeh,
132 100.0 - boxsize * 2 - w, 100.0 - boxsizeh * 2 - h, POS_PACK_NONE);
133 init_panel(last_compose_widget(widget));
134 last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_INDEPENDENT;
136 last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_NOT_COMPOSE;
138 widget->visibility &= ~WIDGET_VISIBILITY_NOT_COMPOSE;
141 void add_listbox_item(struct xuni_t *xuni, struct widget_t *widget,
142 size_t font, const char *data) {
144 struct widget_t *prev = last_compose_widget(widget);
145 const char *p;
146 int x, y;
148 if(prev && prev->pos) {
149 x = prev->pos->scale.x;
150 y = prev->pos->scale.y; /* !!! */
151 x = 0;
152 y = 0;
154 else {
155 x = 0 /*widget->pos->scale.x*/;
156 y = 0 /*widget->pos->scale.y*/;
159 add_allocate_widget_compose(widget, "listbox item");
161 init_widget_pos(last_compose_widget(widget),
162 x, y, 0, 0, POS_PACK_TOP);
164 p = xuni_memory_duplicate_string(data);
165 init_label(last_compose_widget(widget),
166 font, p, LABEL_ALIGN_LEFT, 255, 255, 255);
167 xuni_memory_decrement((void *)p);
169 last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_INDEPENDENT;
171 widget_event(xuni, last_compose_widget(widget), WIDGET_EVENT_RESCALE);
174 struct widget_t *listbox_sel_item(struct widget_t *widget) {
175 struct widget_t *data = widget->compose->widget[WID_LISTBOX_DATA];
176 size_t x;
178 if(!data->compose) return 0;
180 for(x = 0; x < data->compose->widgets; x ++) {
181 if(data->compose->widget[x]->sel) {
182 return data->compose->widget[x];
186 /*log_message(ERROR_TYPE_WARNING, 0, __FILE__, __LINE__,
187 "No listbox item selected");
188 print_widget_backtrace(widget);*/
190 return 0;
193 void listbox_calculate_scrollbar_max(struct xuni_t *xuni,
194 struct widget_t *widget) {
196 struct widget_t *area = widget->compose->widget[WID_LISTBOX_DATA];
197 struct widget_t *first;
198 struct widget_t *last = last_compose_widget(area);
199 int max, height;
201 /*printf("rescale_listbox()\n");*/
203 if(last) {
204 first = area->compose->widget[0];
205 /* !!! area->pos->real.h isn't quite right */
206 /*widget->pos->real.y = prev->pos->real.y + prev->p.label->label->h;*/
207 /*max = last->pos->real.y + last->pos->real.h
208 - area->pos->real.y - area->pos->real.h;*/
210 height = get_box_height(xuni, xuni->theme->current) / 100.0
211 * xuni->smode->height;
213 max = ((last->pos->real.y - area->pos->real.y)
214 - (first->pos->real.y - area->pos->real.y)
215 + last->pos->real.h)
216 - (area->pos->real.h - last->pos->real.h) - height * 2;
218 #if !1
219 printf("get_real_pos(y): %i\n",
220 get_real_pos(last->pos->scale.y, area->pos->real.w));
221 printf("last->pos->real.y: %i\n", last->pos->real.y);
222 printf("first total: %i\n",
223 /*(last->pos->real.y - area->pos->real.y + last->pos->real.h));*/
224 (get_real_pos(last->pos->scale.y, area->pos->real.w)
225 - area->pos->real.y + last->pos->real.h));
226 printf("last->pos->real.y: %i\n", last->pos->real.y);
227 printf("last->pos->real.h: %i\n", last->pos->real.h);
228 printf("area->pos->real.y: %i\n", area->pos->real.y);
229 printf("area->pos->real.h: %i\n", area->pos->real.h);
230 printf("max: %i\n", max);
231 #endif
233 else max = 0;
235 set_scrollbar_max(xuni, widget->compose->widget[WID_LISTBOX_VSCROLL],
236 max);
239 static void free_listbox(struct xuni_t *xuni, struct widget_t *widget) {
240 xuni_memory_free(widget->p.listbox);
243 static void paint_listbox(struct xuni_t *xuni, struct widget_t *widget) {
244 /*size_t x, start = 3;*/
245 /*int height, width;*/
246 int yclip;
248 widget_event(xuni, widget->compose->widget[WID_LISTBOX_BOX],
249 WIDGET_EVENT_PAINT);
251 /*height = get_box_height(xuni, xuni->theme->current) / 100.0
252 * xuni->smode->height;
253 width = get_box_width(xuni, xuni->theme->current) / 100.0
254 * xuni->smode->width;*/
256 yclip = get_scrollbar_pos_int(
257 widget->compose->widget[WID_LISTBOX_VSCROLL]);
258 /*wclip = widget->compose->widget[WID_LISTBOX_BOX]->pos->real.w - width * 2;
259 hclip = widget->compose->widget[WID_LISTBOX_BOX]->pos->real.h;*/
261 #if !1
262 /*clear_widget_clip(xuni, widget->compose->widget[WID_LISTBOX_DATA]);*/
264 /* !!! why does +width work but +height not? */
265 add_widget_clip(xuni, widget->compose->widget[WID_LISTBOX_DATA],
266 0, -yclip + width, 0, yclip /*+ width*/, /*-width * 2*/0, 0);
267 #endif
269 widget_event(xuni, widget->compose->widget[WID_LISTBOX_DATA],
270 WIDGET_EVENT_PAINT);
272 #if 0
273 /* !!! why does +width work but +height not? */
274 add_widget_clip(xuni, widget->compose->widget[WID_LISTBOX_DATA],
275 0, -(-yclip + width), 0, -yclip /*+ width*/, /*-width * 2*/0, 0);
276 #endif
278 widget_event(xuni, widget->compose->widget[WID_LISTBOX_VSCROLL],
279 WIDGET_EVENT_PAINT);
280 widget_event(xuni, widget->compose->widget[WID_LISTBOX_HSCROLL],
281 WIDGET_EVENT_PAINT);
284 static void reposition_listbox(struct xuni_t *xuni, struct widget_t *widget) {
285 int yclip = get_scrollbar_pos_int(
286 widget->compose->widget[WID_LISTBOX_VSCROLL]);
287 int xclip = get_scrollbar_pos_int(
288 widget->compose->widget[WID_LISTBOX_HSCROLL]);
290 listbox_calculate_scrollbar_max(xuni, widget);
291 set_scrollbar_max(xuni, widget->compose->widget[WID_LISTBOX_HSCROLL],
292 widget->p.listbox->maxwidth);
294 clear_widget_clip(xuni, widget->compose->widget[WID_LISTBOX_DATA]);
296 add_panel_clip(xuni, widget->compose->widget[WID_LISTBOX_DATA],
297 -xclip, -yclip, xclip, yclip, 0, 0);
298 /*add_widget_clip(xuni, widget->compose->widget[WID_LISTBOX_DATA],
299 width, 0, 0, 0, -width * 2, 0);*/
302 static void rescale_listbox(struct xuni_t *xuni, struct widget_t *widget) {
303 #if 0
304 double width = calculate_scrollbar_width(widget, xuni);
305 double boxsize = (get_box_width(xuni->theme->current) / 100.0) * 2.0
306 * widget->pos->real.w;
307 double boxsizeh = (get_box_height(xuni->theme->current) / 100.0) * 2.0
308 * widget->pos->real.h;
309 /*double boxsizeh = get_box_height(xuni->theme->current)
310 * (get_box_height(xuni->theme->current) / 100.0);*/
311 struct widget_t *data = widget->compose->widget[WID_LISTBOX_DATA];
313 data->pos->scale.x = boxsize;
314 data->pos->scale.y = boxsizeh;
315 data->pos->scale.w = 100.0 - width - boxsize * 2;
316 data->pos->scale.h = 100.0 - boxsizeh * 2;
318 widget_compose_event(xuni, widget, WIDGET_EVENT_RESCALE);
319 #endif