libui/redo/control.c

157 lines
3.0 KiB
C
Raw Normal View History

2015-05-29 13:56:11 -05:00
// 26 may 2015
2015-08-27 11:05:11 -05:00
#include "ui.h"
#include "uipriv.h"
2015-05-29 13:56:11 -05:00
struct controlBase {
uiControl *parent;
2015-05-29 13:56:11 -05:00
int hidden;
int disabled;
};
static uintmax_t type_uiControl = 0;
2015-08-27 11:05:11 -05:00
uintmax_t uiControlType(void)
{
if (type_uiControl == 0)
2015-08-27 11:05:11 -05:00
type_uiControl = uiRegisterType("uiControl", 0, sizeof (uiControl));
return type_uiControl;
}
2015-05-29 13:56:11 -05:00
#define controlBase(c) ((struct controlBase *) (c->Internal))
2015-08-27 11:05:11 -05:00
void uiControlDestroy(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
if (cb->parent != NULL)
complain("attempt to destroy uiControl %p while it has a parent", c);
2015-08-27 11:05:11 -05:00
(*(c->CommitDestroy))(c);
2015-05-29 13:56:11 -05:00
uiFree(cb);
uiFree(c);
}
2015-08-27 11:05:11 -05:00
uintptr_t uiControlHandle(uiControl *c)
{
return (*(c->Handle))(c);
}
uiControl *uiControlParent(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
return cb->parent;
}
2015-08-27 11:05:11 -05:00
int isToplevel(uiControl *c)
{
return uiIsA(c, uiWindowType(), 0) != NULL;
}
// returns self if self is a window
uiControl *toplevelOwning(uiControl *c)
{
struct controlBase *cb;
for (;;) {
if (isToplevel(c))
return c;
cb = controlBase(c);
if (cb->parent == NULL)
return NULL;
c = cb->parent;
}
}
void uiControlSetParent(uiControl *c, uiControl *parent)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-08-27 11:05:11 -05:00
if (isToplevel(c))
complain("cannot set a parent on a toplevel (uiWindow)");
2015-05-29 13:56:11 -05:00
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);
cb->parent = parent;
2015-05-29 13:56:11 -05:00
// for situations such as where the old parent was disabled but the new one is not, etc.
2015-08-27 11:05:11 -05:00
controlUpdateState(c);
}
2015-08-27 11:05:11 -05:00
static int controlContainerVisible(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
if (cb->hidden)
return 0;
if (cb->parent == NULL)
return 1;
2015-08-27 11:05:11 -05:00
return controlContainerVisible(cb->parent);
}
2015-08-27 11:05:11 -05:00
void uiControlShow(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
cb->hidden = 0;
2015-08-27 11:05:11 -05:00
controlUpdateState(c);
}
2015-08-27 11:05:11 -05:00
void uiControlHide(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
cb->hidden = 1;
2015-08-27 11:05:11 -05:00
controlUpdateState(c);
}
2015-08-27 11:05:11 -05:00
static int controlContainerEnabled(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
if (cb->disabled)
return 0;
if (cb->parent == NULL)
return 1;
2015-08-27 11:05:11 -05:00
return controlContainerEnabled(cb->parent);
}
2015-08-27 11:05:11 -05:00
void uiControlEnable(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
cb->disabled = 0;
2015-08-27 11:05:11 -05:00
controlUpdateState(c);
}
2015-08-27 11:05:11 -05:00
void uiControlDisable(uiControl *c)
{
2015-05-29 13:56:11 -05:00
struct controlBase *cb = controlBase(c);
2015-05-29 13:56:11 -05:00
cb->disabled = 1;
2015-08-27 11:05:11 -05:00
controlUpdateState(c);
}
2015-08-27 11:05:11 -05:00
void controlUpdateState(uiControl *c)
{
2015-08-27 11:05:11 -05:00
if (controlContainerVisible(c))
(*(c->CommitShow))(c);
2015-05-29 13:56:11 -05:00
else
2015-08-27 11:05:11 -05:00
(*(c->CommitHide))(c);
if (controlContainerEnabled(c))
osCommitEnable(c);
2015-05-29 13:56:11 -05:00
else
2015-08-27 11:05:11 -05:00
osCommitDisable(c);
(*(c->ContainerUpdateState))(c);
2015-05-30 12:40:05 -05:00
// and queue a resize, just in case we showed/hid something
2015-08-27 11:05:11 -05:00
//TODO uiControlQueueResize(c);
}
2015-05-29 13:56:11 -05:00
uiControl *uiNewControl(uintmax_t type)
{
2015-05-29 13:56:11 -05:00
uiControl *c;
2015-05-29 13:56:11 -05:00
c = uiControl(newTyped(type));
2015-08-27 11:05:11 -05:00
c->Internal = uiNew(struct controlBase);
return c;
}