6 static rtk_draw_ops gfx;
8 static void calc_widget_rect(rtk_widget *w, rtk_rect *rect);
10 void rtk_setup(rtk_draw_ops *drawop)
15 rtk_widget *rtk_create_widget(void)
19 if(!(w = calloc(1, sizeof *w))) {
22 w->any.flags = VISIBLE | ENABLED | GEOMCHG | DIRTY;
26 void rtk_free_widget(rtk_widget *w)
30 if(w->type == RTK_WIN) {
32 rtk_widget *c = w->win.clist;
33 w->win.clist = w->win.clist->any.next;
42 int rtk_type(rtk_widget *w)
47 void rtk_move(rtk_widget *w, int x, int y)
51 w->any.flags |= GEOMCHG;
54 void rtk_pos(rtk_widget *w, int *xptr, int *yptr)
60 void rtk_resize(rtk_widget *w, int xsz, int ysz)
64 w->any.flags |= GEOMCHG;
67 void rtk_size(rtk_widget *w, int *xptr, int *yptr)
70 *yptr = w->any.height;
73 int rtk_set_text(rtk_widget *w, const char *str)
76 char *s = strdup(str);
82 calc_widget_rect(w, &rect);
83 rtk_resize(w, rect.width, rect.height);
87 const char *rtk_get_text(rtk_widget *w)
92 void rtk_set_value(rtk_widget *w, int val)
97 int rtk_get_value(rtk_widget *w)
102 void rtk_set_callback(rtk_widget *w, rtk_callback cbfunc, void *cls)
104 w->any.cbfunc = cbfunc;
108 void rtk_win_layout(rtk_widget *w, int layout)
110 w->win.layout = layout;
113 void rtk_win_clear(rtk_widget *w)
117 RTK_ASSERT_TYPE(w, RTK_WIN);
119 while(w->win.clist) {
121 w->win.clist = w->win.clist->any.next;
122 rtk_free_widget(tmp);
125 w->win.clist = w->win.ctail = 0;
128 void rtk_win_add(rtk_widget *par, rtk_widget *child)
130 RTK_ASSERT_TYPE(par, RTK_WIN);
132 if(rtk_win_has(par, child)) {
137 rtk_win_rm(child->any.par, child);
141 par->win.ctail->any.next = child;
142 par->win.ctail = child;
144 par->win.clist = par->win.ctail = child;
148 child->any.par = par;
151 void rtk_win_rm(rtk_widget *par, rtk_widget *child)
153 rtk_widget *prev, dummy;
155 RTK_ASSERT_TYPE(par, RTK_WIN);
157 dummy.any.next = par->win.clist;
159 while(prev->any.next) {
160 if(prev->any.next == child) {
161 if(!child->any.next) {
162 par->win.ctail = prev;
164 prev->any.next = child->any.next;
167 prev = prev->any.next;
169 par->win.clist = dummy.any.next;
172 int rtk_win_has(rtk_widget *par, rtk_widget *child)
176 RTK_ASSERT_TYPE(par, RTK_WIN);
188 /* --- button functions --- */
190 void rtk_bn_set_icon(rtk_widget *w, rtk_icon *icon)
192 RTK_ASSERT_TYPE(w, RTK_BUTTON);
196 rtk_icon *rtk_bn_get_icon(rtk_widget *w)
198 RTK_ASSERT_TYPE(w, RTK_BUTTON);
202 /* --- constructors --- */
204 rtk_widget *rtk_create_window(rtk_widget *par, const char *title, int x, int y, int width, int height)
208 if(!(w = rtk_create_widget())) {
211 if(par) rtk_win_add(par, w);
212 rtk_set_text(w, title);
214 rtk_resize(w, width, height);
218 rtk_widget *rtk_create_button(rtk_widget *par, const char *str, rtk_callback cbfunc)
222 if(!(w = rtk_create_widget())) {
225 if(par) rtk_win_add(par, w);
226 rtk_set_text(w, str);
227 rtk_set_callback(w, cbfunc, 0);
231 rtk_widget *rtk_create_iconbutton(rtk_widget *par, rtk_icon *icon, rtk_callback cbfunc)
235 if(!(w = rtk_create_widget())) {
238 if(par) rtk_win_add(par, w);
239 rtk_bn_set_icon(w, icon);
240 rtk_set_callback(w, cbfunc, 0);
244 rtk_widget *rtk_create_label(rtk_widget *par, const char *text)
248 if(!(w = rtk_create_widget())) {
251 if(par) rtk_win_add(par, w);
252 rtk_set_text(w, text);
256 rtk_widget *rtk_create_checkbox(rtk_widget *par, const char *text, int chk, rtk_callback cbfunc)
260 if(!(w = rtk_create_widget())) {
263 if(par) rtk_win_add(par, w);
264 rtk_set_text(w, text);
265 rtk_set_value(w, chk ? 1 : 0);
266 rtk_set_callback(w, cbfunc, 0);
270 /* --- icon functions --- */
271 rtk_iconsheet *rtk_load_iconsheet(const char *fname)
275 if(!(is = malloc(sizeof *is))) {
280 if(!(is->pixels = img_load_pixels(fname, &is->width, &is->height, IMG_FMT_RGBA32))) {
287 void rtk_free_iconsheet(rtk_iconsheet *is)
291 img_free_pixels(is->pixels);
295 is->icons = is->icons->next;
302 rtk_icon *rtk_define_icon(rtk_iconsheet *is, const char *name, int x, int y, int w, int h)
306 if(!(icon = malloc(sizeof *icon))) {
309 if(!(icon->name = strdup(name))) {
315 icon->scanlen = is->width;
316 icon->pixels = is->pixels + y * is->width + x;
322 #define OFFS (BEVELSZ + PAD)
323 #define CHKBOXSZ (BEVELSZ * 2 + 8)
325 static void calc_widget_rect(rtk_widget *w, rtk_rect *rect)
327 rtk_rect txrect = {0};
333 gfx.textrect(w->any.text, &txrect);
339 rect->width = w->bn.icon->width + OFFS * 2;
340 rect->height = w->bn.icon->height + OFFS * 2;
342 rect->width = txrect.width + OFFS * 2;
343 rect->height = txrect.height + OFFS * 2;
348 rect->width = txrect.width + CHKBOXSZ + OFFS * 2 + PAD;
349 rect->height = txrect.height + OFFS * 2;
353 rect->width = txrect.width + PAD * 2;
354 rect->height = txrect.height + PAD * 2;
358 rect->width = rect->height = 0;
362 static int need_relayout(rtk_widget *w)
366 if(w->any.flags & GEOMCHG) {
370 if(w->any.type == RTK_WIN) {
373 if(need_relayout(c)) {
382 static void calc_layout(rtk_widget *w)
387 if(w->any.type == RTK_WIN && w->win.layout != RTK_NONE) {
395 if(w->win.layout == RTK_VBOX) {
396 y += c->any.height + PAD;
398 x += c->any.width + PAD;
405 w->any.flags = (w->any.flags & ~GEOMCHG) | DIRTY;
408 static void draw_window(rtk_widget *w);
409 static void draw_button(rtk_widget *w);
410 static void draw_checkbox(rtk_widget *w);
412 void rtk_draw_widget(rtk_widget *w)
414 if(need_relayout(w)) {
418 switch(w->any.type) {
435 w->any.flags &= ~DIRTY;
438 static void widget_rect(rtk_widget *w, rtk_rect *rect)
442 rect->width = w->any.width;
443 rect->height = w->any.height;
446 static void abs_pos(rtk_widget *w, int *xpos, int *ypos)
454 abs_pos(w->any.par, &px, &py);
463 #define COL_BG 0xa0a0a0
464 #define COL_LBEV 0xcccccc
465 #define COL_SBEV 0x202020
468 static void draw_window(rtk_widget *w)
472 widget_rect(w, &rect);
473 gfx.fill(&rect, COL_BG);
476 static void draw_button(rtk_widget *w)
480 widget_rect(w, &rect);
481 abs_pos(w, &rect.x, &rect.y);
483 gfx.fill(&rect, COL_BG);
485 gfx.blit(rect.x + OFFS, rect.y + OFFS, w->bn.icon);
487 gfx.fill(&rect, 0x802020);
491 static void draw_checkbox(rtk_widget *w)