diff options
Diffstat (limited to 'src/gwin/gwin.c')
-rw-r--r-- | src/gwin/gwin.c | 152 |
1 files changed, 142 insertions, 10 deletions
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index 11dcdaf1..a9d9d823 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -167,11 +167,40 @@ color_t gwinGetDefaultBgColor(void) { GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit) { if (!(pgw = _gwindowCreate(g, pgw, pInit, &basegwinVMT, 0))) return 0; + + #if GWIN_NEED_HIERARCHY + pgw->parent = NULL; + pgw->sibling = NULL; + pgw->child = NULL; + #endif + gwinSetVisible(pgw, pInit->show); + return pgw; } void gwinDestroy(GHandle gh) { + if (!gh) { + // should log a runtime error here + return; + } + + #if GWIN_NEED_HIERARCHY + GHandle tmp; + + // recursively destroy our children first + for(tmp = gh->child; tmp; tmp = tmp->sibling) + gwinDestroy(tmp); + + // remove myself from the hierarchy + gwinRemoveChild(gh); + + // issue a redraw of my parent if any + if (gh->parent) { + gwinRedraw(gh->parent); + } + #endif + // Make the window invisible gwinSetVisible(gh, FALSE); @@ -211,7 +240,17 @@ void gwinSetVisible(GHandle gh, bool_t visible) { } bool_t gwinGetVisible(GHandle gh) { - return (gh->flags & GWIN_FLG_VISIBLE) ? TRUE : FALSE; + #if GWIN_NEED_HIERARCHY + // return TRUE if all widgets (itself + parents) are visble, false otherwise + GHandle e = gh; + for (e = gh; e; e = e->parent) { + if (!(e->flags & GWIN_FLG_VISIBLE)) + return FALSE; + } + return TRUE; + #else + return (gh->flags & GWIN_FLG_VISIBLE) ? TRUE : FALSE; + #endif } void gwinSetEnabled(GHandle gh, bool_t enabled) { @@ -229,7 +268,17 @@ void gwinSetEnabled(GHandle gh, bool_t enabled) { } bool_t gwinGetEnabled(GHandle gh) { - return (gh->flags & GWIN_FLG_ENABLED) ? TRUE : FALSE; + #if GWIN_NEED_HIERARCHY + // return TRUE if all widgets (itself + parents) are enabled, false otherwise + GHandle e = gh; + for (e = gh; e; e = e->parent) { + if (!(e->flags & GWIN_FLG_ENABLED)) + return FALSE; + } + return TRUE; + #else + return (gh->flags & GWIN_FLG_ENABLED) ? TRUE : FALSE; + #endif } void gwinMove(GHandle gh, coord_t x, coord_t y) { @@ -241,7 +290,13 @@ void gwinResize(GHandle gh, coord_t width, coord_t height) { } void gwinRedraw(GHandle gh) { - _gwm_redraw(gh, GWIN_WMFLG_PRESERVE|GWIN_WMFLG_NOBGCLEAR); + _gwm_redraw(gh, GWIN_WMFLG_PRESERVE | GWIN_WMFLG_NOBGCLEAR); + + #if GWIN_NEED_HIERARCHY + GHandle tmp; + for (tmp = gh->child; tmp; tmp = tmp->sibling) + gwinRedraw(tmp); + #endif } #if GDISP_NEED_TEXT @@ -250,10 +305,81 @@ void gwinRedraw(GHandle gh) { } #endif +#if GWIN_NEED_HIERARCHY + void gwinAddChild(GHandle parent, GHandle child, bool_t last) { + child->parent = parent; + child->sibling = NULL; + child->child = NULL; + + if (!parent) + return; + + if (last && parent->child) { + GHandle s = parent->child; + while (s->sibling) + s = s->sibling; + s->sibling = child; + } else { + child->sibling = parent->child; + parent->child = child; + } + + // clear the area of the current child position as it will be moved + gwinClear(child); + + // window coordinates until now are relative, make them absolute now. + child->x += parent->x; + child->y += parent->y; + + // redraw the window + gwinRedraw(parent); + } + + void gwinRemoveChild(GHandle gh) { + if(!gh || !gh->parent) { + // without a parent, removing is impossible + // should log a runtime error here + return; + } + + if (gh->parent->child == gh) { + // we are the first child, update parent + gh->parent->child = gh->sibling; + } else { + // otherwise find our predecessor + GHandle tmp = gh->parent->child; + while (tmp && tmp->sibling != gh) + tmp = tmp->sibling; + + if(!tmp) { + // our parent's children list is corrupted + // should log a runtime error here + return; + } + + tmp->sibling = gh->sibling; + } + } + + void gwinRedrawChildren(GHandle gh) { + GHandle tmp; + for (tmp = gh->child; tmp; tmp = tmp->sibling) + gwinRedraw(tmp); + } + + GHandle gwinGetFirstChild(GHandle gh) { + return gh->child; + } + + GHandle gwinGetNextChild(GHandle gh) { + return gh->sibling; + } +#endif + void gwinClear(GHandle gh) { /* * Don't render anything when the window is not visible but - * still call the AfterClear() routine as some widgets will + * still call tthe AfterClear() routine as some widgets will * need this to clear internal buffers or similar */ if (!((gh->flags & GWIN_FLG_VISIBLE))) { @@ -261,14 +387,20 @@ void gwinClear(GHandle gh) { gh->vmt->AfterClear(gh); } else { - #if GDISP_NEED_CLIP - gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); - #endif + #if GDISP_NEED_CLIP + gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); + #endif - gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor); - if (gh->vmt->AfterClear) - gh->vmt->AfterClear(gh); + gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor); + if (gh->vmt->AfterClear) + gh->vmt->AfterClear(gh); } + + #if GWIN_NEED_HIERARCHY + GHandle tmp; + for (tmp = gh->child; tmp; tmp = tmp->sibling) + gwinClear(tmp); + #endif } void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) { |