// 26 may 2015 #include "out/ui.h" #include "uipriv.h" struct controlBase { uiControl *parent; int hidden; int disabled; }; static uintmax_t type_uiControl = 0; uintmax_t uiTypeControl(void) { if (type_uiControl == 0) type_uiControl = uiRegisterType("uiControl", 0, 0); return type_uiControl; } #define controlBase(c) ((struct controlBase *) (c->Internal)) static void controlBaseDestroy(uiControl *c) { struct controlBase *cb = controlBase(c); if (cb->parent != NULL) complain("attempt to destroy uiControl %p while it has a parent", c); uiControlCommitDestroy(c); uiFree(cb); uiFree(c); } static uiControl *controlBaseParent(uiControl *c) { struct controlBase *cb = controlBase(c); return cb->parent; } static void controlBaseSetParent(uiControl *c, uiControl *parent) { struct controlBase *cb = controlBase(c); if (parent != NULL && cb->parent != NULL) complain("attempt to reparent uiControl %p (has parent %p, attempt to give parent %p)", c, cb->parent, parent); if (parent == NULL && cb->parent == NULL) complain("attempt to double unparent uiControl %p", c); // this must come first; GTK+ CommitSetParent() needs the old parent uiControlCommitSetParent(c, parent); cb->parent = parent; // for situations such as where the old parent was disabled but the new one is not, etc. uiControlUpdateState(c); } static void controlBaseQueueResize(uiControl *c) { queueResize(c); } static int controlBaseContainerVisible(uiControl *c) { struct controlBase *cb = controlBase(c); if (cb->hidden) return 0; if (cb->parent == NULL) return 1; return uiControlContainerVisible(cb->parent); } static void controlBaseShow(uiControl *c) { struct controlBase *cb = controlBase(c); cb->hidden = 0; uiControlUpdateState(c); } static void controlBaseHide(uiControl *c) { struct controlBase *cb = controlBase(c); cb->hidden = 1; uiControlUpdateState(c); } static int controlBaseContainerEnabled(uiControl *c) { struct controlBase *cb = controlBase(c); if (cb->disabled) return 0; if (cb->parent == NULL) return 1; return uiControlContainerEnabled(cb->parent); } static void controlBaseEnable(uiControl *c) { struct controlBase *cb = controlBase(c); cb->disabled = 0; uiControlUpdateState(c); } static void controlBaseDisable(uiControl *c) { struct controlBase *cb = controlBase(c); cb->disabled = 1; uiControlUpdateState(c); } static void controlBaseUpdateState(uiControl *c) { if (uiControlContainerVisible(c)) uiControlCommitShow(c); else uiControlCommitHide(c); if (uiControlContainerEnabled(c)) uiControlCommitEnable(c); else uiControlCommitDisable(c); uiControlContainerUpdateState(c); // and queue a resize, just in case we showed/hid something uiControlQueueResize(c); } static void controlBaseContainerUpdateState(uiControl *c) { // by default not a container; do nothing } uiControl *uiNewControl(uintmax_t type) { uiControl *c; c = uiControl(newTyped(type)); uiControl(c)->Internal = uiNew(struct controlBase); uiControl(c)->Destroy = controlBaseDestroy; uiControl(c)->Parent = controlBaseParent; uiControl(c)->SetParent = controlBaseSetParent; uiControl(c)->QueueResize = controlBaseQueueResize; uiControl(c)->ContainerVisible = controlBaseContainerVisible; uiControl(c)->Show = controlBaseShow; uiControl(c)->Hide = controlBaseHide; uiControl(c)->ContainerEnabled = controlBaseContainerEnabled; uiControl(c)->Enable = controlBaseEnable; uiControl(c)->Disable = controlBaseDisable; uiControl(c)->UpdateState = controlBaseUpdateState; uiControl(c)->ContainerUpdateState = controlBaseContainerUpdateState; return uiControl(c); }