aboutsummaryrefslogtreecommitdiffstats
path: root/src/gwin/gwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gwin/gwin.c')
-rw-r--r--src/gwin/gwin.c150
1 files changed, 140 insertions, 10 deletions
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 54f42077..b9a488d3 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -142,6 +142,12 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit
_gwm_redim(pgw, pInit->x, pInit->y, pInit->width, pInit->height);
#endif
+ #if GWIN_NEED_HIERARCHY
+ pgw->parent = NULL;
+ pgw->sibling = NULL;
+ pgw->child = NULL;
+ #endif
+
return (GHandle)pgw;
}
@@ -189,6 +195,27 @@ GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pI
}
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);
@@ -228,7 +255,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) {
@@ -246,7 +283,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) {
@@ -258,7 +305,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
@@ -267,10 +320,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))) {
@@ -278,14 +402,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) {