// 27 april 2015 #include "uipriv_windows.h" struct bin { uiContainer c; void (*baseDestroy)(uiControl *); uiControl *mainControl; intmax_t marginLeft; intmax_t marginTop; intmax_t marginRight; intmax_t marginBottom; }; static void binDestroy(uiControl *c) { struct bin *b = (struct bin *) c; HWND hwnd; // ensure clean removal by making sure the bin has no OS parent hwnd = (HWND) uiControlHandle(uiControl(b)); if (GetAncestor(hwnd, GA_PARENT) != initialParent) complain("attempt to destroy bin %p while it has an OS parent", b); // don't chain up to base here; we need to destroy children ourselves first if (b->mainControl != NULL) { uiControlSetParent(b->mainControl, NULL); uiControlDestroy(b->mainControl); } // NOW we can chain up to base (*(b->baseDestroy))(uiControl(b)); uiFree(b); } static void binPreferredSize(uiControl *c, uiSizing *d, intmax_t *width, intmax_t *height) { struct bin *b = (struct bin *) c; intmax_t marginX, marginY; if (b->mainControl == NULL) { *width = 0; *height = 0; return; } uiControlPreferredSize(b->mainControl, d, width, height); marginX = uiWindowsDlgUnitsToX(b->marginLeft, d->Sys->BaseX) + uiWindowsDlgUnitsToX(b->marginRight, d->Sys->BaseX); marginY = uiWindowsDlgUnitsToY(b->marginTop, d->Sys->BaseY) + uiWindowsDlgUnitsToY(b->marginBottom, d->Sys->BaseY); *width += marginX; *height += marginY; } static void binSysFunc(uiControl *c, uiControlSysFuncParams *p) { struct bin *b = (struct bin *) c; if (b->mainControl != NULL) uiControlSysFunc(b->mainControl, p); } static void binResizeChildren(uiContainer *c, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d) { struct bin *b = (struct bin *) c; intmax_t marginLeft, marginTop; if (b->mainControl == NULL) return; marginLeft = uiWindowsDlgUnitsToX(b->marginLeft, d->Sys->BaseX); marginTop = uiWindowsDlgUnitsToY(b->marginTop, d->Sys->BaseY); x += marginLeft; y += marginTop; width -= marginLeft + uiWindowsDlgUnitsToX(b->marginRight, d->Sys->BaseX); height -= marginTop + uiWindowsDlgUnitsToY(b->marginBottom, d->Sys->BaseY); uiControlResize(b->mainControl, x, y, width, height, d); } uiContainer *newBin(void) { struct bin *b; b = uiNew(struct bin); uiMakeContainer(uiContainer(b)); b->baseDestroy = uiControl(b)->Destroy; uiControl(b)->Destroy = binDestroy; uiControl(b)->PreferredSize = binPreferredSize; uiControl(b)->SysFunc = binSysFunc; uiContainer(b)->ResizeChildren = binResizeChildren; return uiContainer(b); } void binSetMainControl(uiContainer *c, uiControl *mainControl) { struct bin *b = (struct bin *) c; if (b->mainControl != NULL) uiControlSetParent(b->mainControl, NULL); b->mainControl = mainControl; if (b->mainControl != NULL) uiControlSetParent(b->mainControl, uiContainer(b)); uiContainerUpdate(uiContainer(b)); } void binSetMargins(uiContainer *c, intmax_t left, intmax_t top, intmax_t right, intmax_t bottom) { struct bin *b = (struct bin *) c; b->marginLeft = left; b->marginRight = right; b->marginTop = top; b->marginBottom = bottom; uiContainerUpdate(uiContainer(b)); } void binSetParent(uiContainer *c, uintptr_t osParent) { struct bin *b = (struct bin *) c; HWND hwnd; HWND newParent = (HWND) osParent; hwnd = (HWND) uiControlHandle(uiControl(b)); if (newParent == NULL) newParent = initialParent; if (SetParent(hwnd, newParent) == 0) logLastError("error changing bin's parent in binSetParent()"); }