135 lines
3.3 KiB
C
135 lines
3.3 KiB
C
// 27 april 2015
|
|
#include "ui.h"
|
|
#include "uipriv.h"
|
|
|
|
struct bin {
|
|
uiBin b;
|
|
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;
|
|
|
|
// ensure clean removal by making sure the bin has no OS parent
|
|
if (uiBinHasOSParent(uiBin(b)))
|
|
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 left, top, right, bottom;
|
|
intmax_t cwid, cht;
|
|
|
|
if (b->mainControl == NULL) {
|
|
*width = 0;
|
|
*height = 0;
|
|
return;
|
|
}
|
|
|
|
// first do margins
|
|
left = b->marginLeft;
|
|
top = b->marginTop;
|
|
right = b->marginRight;
|
|
bottom = b->marginBottom;
|
|
uiBinTranslateMargins(uiBin(b), &left, &top, &right, &bottom, d);
|
|
*width = left + right;
|
|
*height = top + bottom;
|
|
|
|
// then do the control
|
|
uiControlPreferredSize(b->mainControl, d, &cwid, &cht);
|
|
*width += cwid;
|
|
*height += cht;
|
|
}
|
|
|
|
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 left, top, right, bottom;
|
|
|
|
if (b->mainControl == NULL)
|
|
return;
|
|
left = b->marginLeft;
|
|
top = b->marginTop;
|
|
right = b->marginRight;
|
|
bottom = b->marginBottom;
|
|
uiBinTranslateMargins(uiBin(b), &left, &top, &right, &bottom, d);
|
|
x += left;
|
|
y += top;
|
|
width -= left + right;
|
|
height -= top + bottom;
|
|
uiControlResize(b->mainControl, x, y, width, height, d);
|
|
}
|
|
|
|
static void binSetMainControl(uiBin *bb, uiControl *mainControl)
|
|
{
|
|
struct bin *b = (struct bin *) bb;
|
|
|
|
if (b->mainControl != NULL)
|
|
uiControlSetParent(b->mainControl, NULL);
|
|
b->mainControl = mainControl;
|
|
if (b->mainControl != NULL)
|
|
uiControlSetParent(b->mainControl, uiContainer(b));
|
|
uiContainerUpdate(uiContainer(b));
|
|
}
|
|
|
|
static void binSetMargins(uiBin *bb, intmax_t left, intmax_t top, intmax_t right, intmax_t bottom)
|
|
{
|
|
struct bin *b = (struct bin *) bb;
|
|
|
|
b->marginLeft = left;
|
|
b->marginRight = right;
|
|
b->marginTop = top;
|
|
b->marginBottom = bottom;
|
|
uiContainerUpdate(uiContainer(b));
|
|
}
|
|
|
|
uiBin *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;
|
|
|
|
uiBin(b)->SetMainControl = binSetMainControl;
|
|
uiBin(b)->SetMargins = binSetMargins;
|
|
// these are defined by each OS's bin.c
|
|
uiBin(b)->HasOSParent = binHasOSParent;
|
|
uiBin(b)->SetOSParent = binSetOSParent;
|
|
uiBin(b)->RemoveOSParent = binRemoveOSParent;
|
|
uiBin(b)->ResizeRootAndUpdate = binResizeRootAndUpdate;
|
|
uiBin(b)->TranslateMargins = binTranslateMargins;
|
|
|
|
return uiBin(b);
|
|
}
|