X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Frtk.c;h=4bb93c82b36cde044c1592f9185e7d87c52aeb58;hb=bba16e9faf7ff0e4089ba75c06baef713da04a4a;hp=bdfca65be54f8771e99caa7121edfef4a093bcd4;hpb=c82eddaf769c3e93e08c30c965d18251b08ca7bc;p=retroray diff --git a/src/rtk.c b/src/rtk.c index bdfca65..4bb93c8 100644 --- a/src/rtk.c +++ b/src/rtk.c @@ -2,6 +2,7 @@ #include #include "imago2.h" #include "rtk_impl.h" +#include "app.h" static rtk_draw_ops gfx; @@ -11,6 +12,12 @@ static void draw_button(rtk_widget *w); static void draw_checkbox(rtk_widget *w); static void draw_separator(rtk_widget *w); +static void invalfb(rtk_widget *w); + + +static rtk_widget *hover, *focused, *pressed; + + void rtk_setup(rtk_draw_ops *drawop) { gfx = *drawop; @@ -52,7 +59,7 @@ void rtk_move(rtk_widget *w, int x, int y) { w->any.x = x; w->any.y = y; - w->any.flags |= GEOMCHG; + w->any.flags |= GEOMCHG | DIRTY; } void rtk_pos(rtk_widget *w, int *xptr, int *yptr) @@ -65,7 +72,7 @@ void rtk_resize(rtk_widget *w, int xsz, int ysz) { w->any.width = xsz; w->any.height = ysz; - w->any.flags |= GEOMCHG; + w->any.flags |= GEOMCHG | DIRTY; } void rtk_size(rtk_widget *w, int *xptr, int *yptr) @@ -74,6 +81,14 @@ void rtk_size(rtk_widget *w, int *xptr, int *yptr) *yptr = w->any.height; } +void rtk_get_rect(rtk_widget *w, rtk_rect *r) +{ + r->x = w->any.x; + r->y = w->any.y; + r->width = w->any.width; + r->height = w->any.height; +} + int rtk_set_text(rtk_widget *w, const char *str) { rtk_rect rect; @@ -85,6 +100,7 @@ int rtk_set_text(rtk_widget *w, const char *str) calc_widget_rect(w, &rect); rtk_resize(w, rect.width, rect.height); + rtk_invalidate(w); return 0; } @@ -96,6 +112,7 @@ const char *rtk_get_text(rtk_widget *w) void rtk_set_value(rtk_widget *w, int val) { w->any.value = val; + rtk_invalidate(w); } int rtk_get_value(rtk_widget *w) @@ -109,6 +126,16 @@ void rtk_set_callback(rtk_widget *w, rtk_callback cbfunc, void *cls) w->any.cbcls = cls; } +void rtk_invalidate(rtk_widget *w) +{ + w->any.flags |= DIRTY; +} + +void rtk_validate(rtk_widget *w) +{ + w->any.flags &= ~DIRTY; +} + void rtk_win_layout(rtk_widget *w, int layout) { w->win.layout = layout; @@ -127,6 +154,7 @@ void rtk_win_clear(rtk_widget *w) } w->win.clist = w->win.ctail = 0; + rtk_invalidate(w); } void rtk_win_add(rtk_widget *par, rtk_widget *child) @@ -150,6 +178,7 @@ void rtk_win_add(rtk_widget *par, rtk_widget *child) child->any.next = 0; child->any.par = par; + rtk_invalidate(par); } void rtk_win_rm(rtk_widget *par, rtk_widget *child) @@ -171,6 +200,7 @@ void rtk_win_rm(rtk_widget *par, rtk_widget *child) prev = prev->any.next; } par->win.clist = dummy.any.next; + rtk_invalidate(par); } int rtk_win_has(rtk_widget *par, rtk_widget *child) @@ -190,6 +220,12 @@ int rtk_win_has(rtk_widget *par, rtk_widget *child) } /* --- button functions --- */ +void rtk_bn_mode(rtk_widget *w, int mode) +{ + RTK_ASSERT_TYPE(w, RTK_BUTTON); + w->bn.mode = mode; + rtk_invalidate(w); +} void rtk_bn_set_icon(rtk_widget *w, rtk_icon *icon) { @@ -200,6 +236,7 @@ void rtk_bn_set_icon(rtk_widget *w, rtk_icon *icon) calc_widget_rect(w, &rect); rtk_resize(w, rect.width, rect.height); + rtk_invalidate(w); } rtk_icon *rtk_bn_get_icon(rtk_widget *w) @@ -451,15 +488,24 @@ static void calc_layout(rtk_widget *w) w->any.width = rect.width; w->any.height = rect.height; - w->any.flags = (w->any.flags & ~GEOMCHG) | DIRTY; + w->any.flags &= ~GEOMCHG; + rtk_invalidate(w); } void rtk_draw_widget(rtk_widget *w) { + int dirty; + if(need_relayout(w)) { + dbgmsg("calc layout %s\n", w->any.text ? w->any.text : "?"); calc_layout(w); } + dirty = w->any.flags & DIRTY; + if(!dirty && w->any.type != RTK_WIN) { + return; + } + switch(w->any.type) { case RTK_WIN: draw_window(w); @@ -481,7 +527,10 @@ void rtk_draw_widget(rtk_widget *w) break; } - w->any.flags &= ~DIRTY; + if(dirty) { + rtk_validate(w); + invalfb(w); + } } static void widget_rect(rtk_widget *w, rtk_rect *rect) @@ -510,6 +559,7 @@ static void abs_pos(rtk_widget *w, int *xpos, int *ypos) } #define COL_BG 0xff666666 +#define COL_BGHL 0xff808080 #define COL_LBEV 0xffaaaaaa #define COL_SBEV 0xff222222 #define COL_TEXT 0xff000000 @@ -566,12 +616,18 @@ static void draw_window(rtk_widget *w) { rtk_rect rect; rtk_widget *c; + int win_dirty = w->any.flags & DIRTY; - widget_rect(w, &rect); - gfx.fill(&rect, COL_BG); + if(win_dirty) { + widget_rect(w, &rect); + gfx.fill(&rect, COL_BG); + } c = w->win.clist; while(c) { + if(win_dirty) { + rtk_invalidate(c); + } rtk_draw_widget(c); c = c->any.next; } @@ -579,13 +635,20 @@ static void draw_window(rtk_widget *w) static void draw_button(rtk_widget *w) { + int pressed; rtk_rect rect; widget_rect(w, &rect); abs_pos(w, &rect.x, &rect.y); + if(w->bn.mode == RTK_TOGGLEBN) { + pressed = w->any.value; + } else { + pressed = w->any.flags & PRESS; + } + if(rect.width > 2 && rect.height > 2) { - draw_frame(&rect, FRM_OUTSET); + draw_frame(&rect, pressed ? FRM_INSET : FRM_OUTSET); rect.x++; rect.y++; @@ -593,9 +656,10 @@ static void draw_button(rtk_widget *w) rect.height -= 2; } - gfx.fill(&rect, COL_BG); + gfx.fill(&rect, w->any.flags & HOVER ? COL_BGHL : COL_BG); if(w->bn.icon) { - gfx.blit(rect.x + OFFS, rect.y + OFFS, w->bn.icon); + int offs = w->any.flags & PRESS ? PAD + 1 : PAD; + gfx.blit(rect.x + offs, rect.y + offs, w->bn.icon); } else { gfx.fill(&rect, 0xff802020); } @@ -632,3 +696,150 @@ static void draw_separator(rtk_widget *w) draw_frame(&rect, FRM_INSET); } + + +static int hittest(rtk_widget *w, int x, int y) +{ + if(x < w->any.x || y < w->any.y) return 0; + if(x >= w->any.x + w->any.width) return 0; + if(y >= w->any.y + w->any.height) return 0; + return 1; +} + +static void sethover(rtk_widget *w) +{ + if(hover == w) return; + + if(hover) { + hover->any.flags &= ~HOVER; + + if(hover->type != RTK_WIN) { + rtk_invalidate(hover); + invalfb(hover); + } + } + hover = w; + if(w) { + w->any.flags |= HOVER; + + if(w->type != RTK_WIN) { + rtk_invalidate(w); + invalfb(w); + } + } +} + +static void setpress(rtk_widget *w) +{ + if(pressed == w) return; + + if(pressed) { + pressed->any.flags &= ~PRESS; + rtk_invalidate(pressed); + invalfb(pressed); + } + pressed = w; + if(w) { + w->any.flags |= PRESS; + rtk_invalidate(w); + invalfb(w); + } +} + +static void click(rtk_widget *w, int x, int y) +{ + switch(w->type) { + case RTK_BUTTON: + if(w->bn.mode == RTK_TOGGLEBN) { + case RTK_CHECKBOX: + w->any.value ^= 1; + } + if(w->any.cbfunc) { + w->any.cbfunc(w, w->any.cbcls); + } + rtk_invalidate(w); + invalfb(w); + break; + + default: + break; + } +} + +int rtk_input_key(rtk_widget *w, int key, int press) +{ + return 0; +} + +int rtk_input_mbutton(rtk_widget *w, int bn, int press, int x, int y) +{ + if(!hittest(w, x, y)) { + return 0; + } + + if(press) { + if(hover && hittest(hover, x, y)) { + setpress(hover); + } + } else { + if(pressed && hittest(pressed, x, y)) { + click(pressed, x, y); + } + setpress(0); + } + + return 1; +} + +int rtk_input_mmotion(rtk_widget *w, int x, int y) +{ + rtk_widget *c; + + if(!hittest(w, x, y)) { + int res = hover ? 1 : 0; + sethover(0); + return res; + } + + if(w->type == RTK_WIN) { + c = w->win.clist; + while(c) { + if(hittest(c, x, y)) { + return rtk_input_mmotion(c, x, y); + } + c = c->any.next; + } + } + + if(hover != w) { + sethover(w); + return 1; + } + return 0; +} + + +void rtk_rect_union(rtk_rect *a, const rtk_rect *b) +{ + int x0, y0, x1, y1; + + x0 = a->x; + y0 = a->y; + x1 = a->x + a->width; + y1 = a->y + a->height; + + if(b->x < x0) x0 = b->x; + if(b->y < y0) y0 = b->y; + if(b->x + b->width > x1) x1 = b->x + b->width; + if(b->y + b->height > y1) y1 = b->y + b->height; + + a->x = x0; + a->y = y0; + a->width = x1 - x0; + a->height = y1 - y0; +} + +static void invalfb(rtk_widget *w) +{ + app_redisplay(w->any.x, w->any.y, w->any.width, w->any.height); +}