2015-05-29 13:56:11 -05:00
|
|
|
// 26 may 2015
|
2015-10-16 17:31:14 -05:00
|
|
|
#include "../ui.h"
|
2015-05-18 21:32:22 -05:00
|
|
|
#include "uipriv.h"
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase {
|
2015-05-18 21:02:37 -05:00
|
|
|
uiControl *parent;
|
2015-05-29 13:56:11 -05:00
|
|
|
int hidden;
|
|
|
|
int disabled;
|
2015-05-18 21:02:37 -05:00
|
|
|
};
|
|
|
|
|
2015-05-29 13:56:11 -05:00
|
|
|
#define controlBase(c) ((struct controlBase *) (c->Internal))
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
void uiControlDestroy(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
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-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
uintptr_t uiControlHandle(uiControl *c)
|
|
|
|
{
|
|
|
|
return (*(c->Handle))(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
uiControl *uiControlParent(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2015-05-29 13:56:11 -05:00
|
|
|
return cb->parent;
|
2015-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2016-04-24 17:23:00 -05:00
|
|
|
// TODO ask the control instead
|
2015-08-27 11:05:11 -05:00
|
|
|
int isToplevel(uiControl *c)
|
|
|
|
{
|
2016-04-24 15:14:19 -05:00
|
|
|
return c->TypeSignature == uiWindowSignature;
|
2015-08-27 11:05:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void uiControlSetParent(uiControl *c, uiControl *parent)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
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);
|
2015-06-30 09:52:38 -05:00
|
|
|
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-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-09-01 15:44:09 -05:00
|
|
|
// only to be called by the immediate parent of a control
|
|
|
|
int controlSelfVisible(uiControl *c)
|
|
|
|
{
|
|
|
|
struct controlBase *cb = controlBase(c);
|
|
|
|
|
|
|
|
return !cb->hidden;
|
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
static int controlContainerVisible(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
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-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
void uiControlShow(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2015-05-29 13:56:11 -05:00
|
|
|
cb->hidden = 0;
|
2015-08-27 11:05:11 -05:00
|
|
|
controlUpdateState(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
void uiControlHide(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2015-05-29 13:56:11 -05:00
|
|
|
cb->hidden = 1;
|
2015-08-27 11:05:11 -05:00
|
|
|
controlUpdateState(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
static int controlContainerEnabled(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
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-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
void uiControlEnable(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2015-05-29 13:56:11 -05:00
|
|
|
cb->disabled = 0;
|
2015-08-27 11:05:11 -05:00
|
|
|
controlUpdateState(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
void uiControlDisable(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
struct controlBase *cb = controlBase(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2015-05-29 13:56:11 -05:00
|
|
|
cb->disabled = 1;
|
2015-08-27 11:05:11 -05:00
|
|
|
controlUpdateState(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2015-08-27 11:05:11 -05:00
|
|
|
void controlUpdateState(uiControl *c)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
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-09-01 15:44:09 -05:00
|
|
|
// for instance, on Windows uiBox, if we don't do this, hiding a control will show empty space until the window is resized
|
2015-08-27 11:05:11 -05:00
|
|
|
//TODO uiControlQueueResize(c);
|
2015-05-18 21:02:37 -05:00
|
|
|
}
|
|
|
|
|
2016-04-24 14:15:36 -05:00
|
|
|
#define uiControlSignature 0x7569436F
|
|
|
|
|
2016-04-24 15:14:19 -05:00
|
|
|
// TODO should this be public?
|
2016-04-24 16:38:48 -05:00
|
|
|
uiControl *newControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr)
|
2015-05-18 21:02:37 -05:00
|
|
|
{
|
2015-05-29 13:56:11 -05:00
|
|
|
uiControl *c;
|
2015-05-18 21:02:37 -05:00
|
|
|
|
2016-04-24 16:38:48 -05:00
|
|
|
c = (uiControl *) uiAlloc(size, typenamestr);
|
2016-04-24 14:15:36 -05:00
|
|
|
c->Signature = uiControlSignature;
|
|
|
|
c->OSSignature = OSsig;
|
|
|
|
c->TypeSignature = typesig;
|
2015-08-27 11:05:11 -05:00
|
|
|
c->Internal = uiNew(struct controlBase);
|
|
|
|
return c;
|
2015-05-18 21:02:37 -05:00
|
|
|
}
|