Browse Source

merged data and handles; handles can either be set or allocated.

pull/1/head
Leonard Ritter 10 years ago
parent
commit
aa8e0ced01
2 changed files with 93 additions and 114 deletions
  1. +37
    -52
      example.cpp
  2. +56
    -62
      oui.h

+ 37
- 52
example.cpp View File

@@ -40,6 +40,8 @@ typedef enum {
ST_PANEL = 7,
// text
ST_TEXT = 8,
//
ST_IGNORE = 9,
} SubType;

typedef struct {
@@ -93,7 +95,7 @@ int cornerFlags(int item) {
int parent = uiParent(item);
int numkids = uiGetChildCount(parent);
if (numkids < 2) return BND_CORNER_NONE;
const UIData *head = (const UIData *)uiGetData(parent);
const UIData *head = (const UIData *)uiGetHandle(parent);
if (head) {
int numid = uiGetChildId(item);
switch(head->subtype) {
@@ -124,7 +126,7 @@ void testrect(NVGcontext *vg, UIrect rect) {
}

void drawUI(NVGcontext *vg, int item, int x, int y) {
const UIData *head = (const UIData *)uiGetData(item);
const UIData *head = (const UIData *)uiGetHandle(item);
UIrect rect = uiGetRect(item);
rect.x += x;
rect.y += y;
@@ -202,7 +204,7 @@ void drawUI(NVGcontext *vg, int item, int x, int y) {
int label(int iconid, const char *label) {
int item = uiItem();
uiSetSize(item, 0, BND_WIDGET_HEIGHT);
UIButtonData *data = (UIButtonData *)uiAllocData(item, sizeof(UIButtonData));
UIButtonData *data = (UIButtonData *)uiAllocHandle(item, sizeof(UIButtonData));
data->head.subtype = ST_LABEL;
data->iconid = iconid;
data->label = label;
@@ -210,23 +212,19 @@ int label(int iconid, const char *label) {
}

void demohandler(int item, UIevent event) {
const UIButtonData *data = (const UIButtonData *)uiGetData(item);
printf("clicked: %lld %s\n", uiGetHandle(item), data->label);
const UIButtonData *data = (const UIButtonData *)uiGetHandle(item);
printf("clicked: %p %s\n", uiGetHandle(item), data->label);
}

int button(UIhandle handle, int iconid, const char *label,
UIhandler handler) {
int button(int iconid, const char *label, UIhandler handler) {
// create new ui item
int item = uiItem();
// set persistent handle for item that is used
// to track activity over time
uiSetHandle(item, handle);
// set size of wiget; horizontal size is dynamic, vertical is fixed
uiSetSize(item, 0, BND_WIDGET_HEIGHT);
// attach event handler e.g. demohandler above
uiSetHandler(item, handler, UI_BUTTON0_HOT_UP);
// store some custom data with the button that we use for styling
UIButtonData *data = (UIButtonData *)uiAllocData(item, sizeof(UIButtonData));
UIButtonData *data = (UIButtonData *)uiAllocHandle(item, sizeof(UIButtonData));
data->head.subtype = ST_BUTTON;
data->iconid = iconid;
data->label = label;
@@ -234,22 +232,19 @@ int button(UIhandle handle, int iconid, const char *label,
}

void checkhandler(int item, UIevent event) {
const UICheckData *data = (const UICheckData *)uiGetData(item);
const UICheckData *data = (const UICheckData *)uiGetHandle(item);
*data->option = !(*data->option);
}

int check(UIhandle handle, const char *label, int *option) {
int check(const char *label, int *option) {
// create new ui item
int item = uiItem();
// set persistent handle for item that is used
// to track activity over time
uiSetHandle(item, handle);
// set size of wiget; horizontal size is dynamic, vertical is fixed
uiSetSize(item, 0, BND_WIDGET_HEIGHT);
// attach event handler e.g. demohandler above
uiSetHandler(item, checkhandler, UI_BUTTON0_DOWN);
// store some custom data with the button that we use for styling
UICheckData *data = (UICheckData *)uiAllocData(item, sizeof(UICheckData));
UICheckData *data = (UICheckData *)uiAllocHandle(item, sizeof(UICheckData));
data->head.subtype = ST_CHECK;
data->label = label;
data->option = option;
@@ -264,7 +259,7 @@ static float sliderstart = 0.0;
// event handler for slider (same handler for all sliders)
void sliderhandler(int item, UIevent event) {
// retrieve the custom data we saved with the slider
UISliderData *data = (UISliderData *)uiGetData(item);
UISliderData *data = (UISliderData *)uiGetHandle(item);
switch(event) {
default: break;
case UI_BUTTON0_DOWN: {
@@ -288,12 +283,9 @@ void sliderhandler(int item, UIevent event) {
}
}

int slider(UIhandle handle, const char *label, float *progress) {
int slider(const char *label, float *progress) {
// create new ui item
int item = uiItem();
// set persistent handle for item that is used
// to track activity over time
uiSetHandle(item, handle);
// set size of wiget; horizontal size is dynamic, vertical is fixed
uiSetSize(item, 0, BND_WIDGET_HEIGHT);
// attach our slider event handler and capture two classes of events
@@ -301,7 +293,7 @@ int slider(UIhandle handle, const char *label, float *progress) {
UI_BUTTON0_DOWN | UI_BUTTON0_CAPTURE);
// store some custom data with the button that we use for styling
// and logic, e.g. the pointer to the data we want to alter.
UISliderData *data = (UISliderData *)uiAllocData(item, sizeof(UISliderData));
UISliderData *data = (UISliderData *)uiAllocHandle(item, sizeof(UISliderData));
data->head.subtype = ST_SLIDER;
data->label = label;
data->progress = progress;
@@ -309,7 +301,7 @@ int slider(UIhandle handle, const char *label, float *progress) {
}

void textboxhandler(int item, UIevent event) {
UITextData *data = (UITextData *)uiGetData(item);
UITextData *data = (UITextData *)uiGetHandle(item);
switch(event) {
default: break;
case UI_BUTTON0_DOWN: {
@@ -344,15 +336,14 @@ void textboxhandler(int item, UIevent event) {
}
}

int textbox(UIhandle handle, char *text, int maxsize) {
int textbox(char *text, int maxsize) {
int item = uiItem();
uiSetHandle(item, handle);
uiSetSize(item, 0, BND_WIDGET_HEIGHT);
uiSetHandler(item, textboxhandler,
UI_BUTTON0_DOWN | UI_KEY_DOWN | UI_CHAR | UI_ADJUST_HEIGHT);
// store some custom data with the button that we use for styling
// and logic, e.g. the pointer to the data we want to alter.
UITextData *data = (UITextData *)uiAllocData(item, sizeof(UITextData));
UITextData *data = (UITextData *)uiAllocHandle(item, sizeof(UITextData));
data->head.subtype = ST_TEXT;
data->text = text;
data->maxsize = maxsize;
@@ -361,15 +352,14 @@ int textbox(UIhandle handle, char *text, int maxsize) {

// simple logic for a radio button
void radiohandler(int item, UIevent event) {
UIRadioData *data = (UIRadioData *)uiGetData(item);
UIRadioData *data = (UIRadioData *)uiGetHandle(item);
*data->value = uiGetChildId(item);
}

int radio(UIhandle handle, int iconid, const char *label, int *value) {
int radio(int iconid, const char *label, int *value) {
int item = uiItem();
uiSetHandle(item, handle);
uiSetSize(item, label?0:BND_TOOL_WIDTH, BND_WIDGET_HEIGHT);
UIRadioData *data = (UIRadioData *)uiAllocData(item, sizeof(UIRadioData));
UIRadioData *data = (UIRadioData *)uiAllocHandle(item, sizeof(UIRadioData));
data->head.subtype = ST_RADIO;
data->iconid = iconid;
data->label = label;
@@ -380,7 +370,7 @@ int radio(UIhandle handle, int iconid, const char *label, int *value) {

int panel() {
int item = uiItem();
UIData *data = (UIData *)uiAllocData(item, sizeof(UIData));
UIData *data = (UIData *)uiAllocHandle(item, sizeof(UIData));
data->subtype = ST_PANEL;
return item;
}
@@ -416,8 +406,6 @@ int vgroup_append(int parent, int item) {

int vgroup() {
int item = uiItem();
UIData *data = (UIData *)uiAllocData(item, sizeof(UIData));
data->subtype = ST_COLUMN;
return item;
}

@@ -434,8 +422,6 @@ int hgroup_append(int parent, int item) {

int hgroup() {
int item = uiItem();
UIData *data = (UIData *)uiAllocData(item, sizeof(UIData));
data->subtype = ST_ROW;
return item;
}

@@ -700,7 +686,6 @@ void draw(NVGcontext *vg, float w, float h) {
uiSetLayout(0,UI_LEFT|UI_TOP);
uiSetMargins(0,600,10,0,0);
uiSetSize(0,250,400);
uiSetSelfHandle(root);
uiSetHandler(root, roothandler, UI_SCROLL|UI_BUTTON0_DOWN);
int col = column();
@@ -709,15 +694,15 @@ void draw(NVGcontext *vg, float w, float h) {
uiSetLayout(col, UI_TOP|UI_HFILL);
column_append(col, button(1, BND_ICONID(6,3), "Item 1", demohandler));
column_append(col, button(2, BND_ICONID(6,3), "Item 2", demohandler));
column_append(col, button(BND_ICONID(6,3), "Item 1", demohandler));
column_append(col, button(BND_ICONID(6,3), "Item 2", demohandler));

{
int h = column_append(col, hgroup());
hgroup_append(h, radio(3, BND_ICONID(6,3), "Item 3.0", &enum1));
hgroup_append(h, radio(4, BND_ICONID(0,10), NULL, &enum1));
hgroup_append(h, radio(5, BND_ICONID(1,10), NULL, &enum1));
hgroup_append(h, radio(6, BND_ICONID(6,3), "Item 3.3", &enum1));
hgroup_append(h, radio(BND_ICONID(6,3), "Item 3.0", &enum1));
hgroup_append(h, radio(BND_ICONID(0,10), NULL, &enum1));
hgroup_append(h, radio(BND_ICONID(1,10), NULL, &enum1));
hgroup_append(h, radio(BND_ICONID(6,3), "Item 3.3", &enum1));
}
{
@@ -725,24 +710,24 @@ void draw(NVGcontext *vg, float w, float h) {
int coll = row_append(rows, vgroup());
vgroup_append(coll, label(-1, "Items 4.0:"));
coll = vgroup_append(coll, vgroup());
vgroup_append(coll, button(7, BND_ICONID(6,3), "Item 4.0.0", demohandler));
vgroup_append(coll, button(8, BND_ICONID(6,3), "Item 4.0.1", demohandler));
vgroup_append(coll, button(BND_ICONID(6,3), "Item 4.0.0", demohandler));
vgroup_append(coll, button(BND_ICONID(6,3), "Item 4.0.1", demohandler));
int colr = row_append(rows, vgroup());
uiSetFrozen(colr, option1);
vgroup_append(colr, label(-1, "Items 4.1:"));
colr = vgroup_append(colr, vgroup());
vgroup_append(colr, slider(9, "Item 4.1.0", &progress1));
vgroup_append(colr, slider(10, "Item 4.1.1", &progress2));
vgroup_append(colr, slider("Item 4.1.0", &progress1));
vgroup_append(colr, slider("Item 4.1.1", &progress2));
}
column_append(col, button(11, BND_ICONID(6,3), "Item 5", NULL));
column_append(col, button(BND_ICONID(6,3), "Item 5", NULL));

static char textbuffer[1024] = "This textbox adjusts its height to its content when the text is overflowing the widgets width.";
column_append(col, textbox((UIhandle)textbuffer, textbuffer, 1024));
column_append(col, textbox(textbuffer, 1024));

column_append(col, check(12, "Frozen", &option1));
column_append(col, check(13, "Item 7", &option2));
column_append(col, check(14, "Item 8", &option3));
column_append(col, check("Frozen", &option1));
column_append(col, check("Item 7", &option2));
column_append(col, check("Item 8", &option3));
uiLayout();
drawUI(vg, 0, 0, 0);


+ 56
- 62
oui.h View File

@@ -215,9 +215,6 @@ typedef unsigned int UIuint;
// opaque UI context
typedef struct UIcontext UIcontext;

// application defined context handle
typedef unsigned long long UIhandle;

// item states as returned by uiGetState()

typedef enum UIitemState {
@@ -423,6 +420,12 @@ OUI_EXPORT void uiUpdateHotItem();
// this is an O(N) operation for N = number of declared items.
OUI_EXPORT void uiProcess(int timestamp);

// reset the currently stored hot/active etc. handles; this should be called when
// a redeclaration of the UI changes the handle addresses, to avoid state
// related glitches because item identities have changed. If you're using
// uiAllocHandle() you should definitely make use of this.
OUI_EXPORT void uiClearHandleState();

// UI Declaration
// --------------

@@ -439,19 +442,15 @@ OUI_EXPORT int uiItem();
OUI_EXPORT void uiSetFrozen(int item, int enable);

// set the application-dependent handle of an item.
// handle is an application defined 64-bit handle. If handle is 0, the item
// handle is an application defined 64-bit handle. If handle is NULL, the item
// will not be interactive.
OUI_EXPORT void uiSetHandle(int item, UIhandle handle);

// assigns the items own address as handle; this may cause glitches
// when the order of items changes while theitem is captured
OUI_EXPORT void uiSetSelfHandle(int item);
OUI_EXPORT void uiSetHandle(int item, void *handle);

// allocate space for application-dependent context data and return the pointer
// if successful. If no data has been allocated, a new pointer is returned.
// Otherwise, an assertion is thrown.
// The memory of the pointer is managed by the UI context.
OUI_EXPORT void *uiAllocData(int item, int size);
// allocate space for application-dependent context data and assign it
// as the handle to the item.
// The memory of the pointer is managed by the UI context and released
// upon the next call to uiClear()
OUI_EXPORT void *uiAllocHandle(int item, int size);

// set the handler callback for an interactive item.
// flags is a combination of UI_EVENT_* and designates for which events the
@@ -529,12 +528,13 @@ OUI_EXPORT int uiGetItemCount();
// The returned value is one of UI_COLD, UI_HOT, UI_ACTIVE, UI_FROZEN.
OUI_EXPORT UIitemState uiGetState(int item);

// return the application-dependent handle of the item as passed to uiSetHandle().
OUI_EXPORT UIhandle uiGetHandle(int item);
// return the application-dependent handle of the item as passed to uiSetHandle()
// or uiAllocHandle().
OUI_EXPORT void *uiGetHandle(int item);

// return the item with the given application-dependent handle as assigned by
// uiSetHandle() or -1 if unsuccessful.
OUI_EXPORT int uiGetItem(UIhandle handle);
OUI_EXPORT int uiGetItem(void *handle);

// return the item that is currently under the cursor or -1 for none
OUI_EXPORT int uiGetHotItem();
@@ -542,11 +542,6 @@ OUI_EXPORT int uiGetHotItem();
// return the item that is currently focused or -1 for none
OUI_EXPORT int uiGetFocusedItem();

// return the application-dependent context data for an item as passed to
// uiAllocData(). The memory of the pointer is managed by the UI context
// and should not be altered.
OUI_EXPORT const void *uiGetData(int item);

// return the handler callback for an item as passed to uiSetHandler()
OUI_EXPORT UIhandler uiGetHandler(int item);
// return the handler flags for an item as passed to uiSetHandler()
@@ -667,8 +662,11 @@ OUI_EXPORT int uiGetAbove(int item);
enum {
UI_ITEM_LAYOUT_MASK = 0x000F,
UI_ITEM_EVENT_MASK = 0xFFF0,
// item is frozen
UI_ITEM_FROZEN = 0x10000,
UI_ITEM_VISITED_BITOFS = 17, // 0x20000, 0x40000, 0x80000, 0x100000
// item handle is pointer to data
UI_ITEM_DATA = 0x20000,
UI_ITEM_VISITED_BITOFS = 18, // 0x4 0000, 0x8 0000, 0x10 0000, 0x20 0000
UI_ITEM_VISITED_MASK = (UI_ITEM_VISITED_XY_FLAG(0)
| UI_ITEM_VISITED_XY_FLAG(1)
| UI_ITEM_VISITED_WH_FLAG(0)
@@ -677,12 +675,13 @@ enum {

typedef struct UIitem {
// declaration independent unique handle (for persistence)
UIhandle handle;
void *handle;
// handler
UIhandler handler;
// container structure

unsigned int flags;

// container structure
// number of kids
int numkids;
@@ -713,17 +712,12 @@ typedef struct UIitem {
UIvec2 computed_size;
// relative rect
UIrect rect;
// attributes
// index of data or -1 for none
int data;
} UIitem;

// 40 bytes
typedef struct UIitem2 {
// declaration independent unique handle (for persistence)
UIhandle handle;
void *handle;
// handler
UIhandler handler;

@@ -777,9 +771,10 @@ struct UIcontext {
// accumulated scroll wheel offsets
UIvec2 scroll;
UIhandle hot_handle;
UIhandle active_handle;
UIhandle focus_handle;
void *hot_handle;
void *active_handle;
void *focus_handle;
void *last_click_handle;
UIrect hot_rect;
UIrect active_rect;
UIstate state;
@@ -789,7 +784,6 @@ struct UIcontext {
int event_item;
int last_timestamp;
int last_click_timestamp;
UIhandle last_click_handle;
int clicks;
int count;
@@ -832,9 +826,10 @@ void uiDestroyContext(UIcontext *ctx) {
free(ctx);
}

UI_INLINE unsigned int uiHashHandle(UIhandle handle) {
handle = (handle+(handle>>32)) & 0xffffffff;
unsigned int x = (unsigned int)handle;
UI_INLINE unsigned int uiHashHandle(void *handle) {
unsigned long long uval = (unsigned long long)handle;
uval = (uval+(uval>>32)) & 0xffffffff;
unsigned int x = (unsigned int)uval;
x += (x>>6)+(x>>19);
x += x<<16;
x ^= x<<3;
@@ -867,13 +862,13 @@ UI_INLINE UIhandleEntry *uiHashLookupHandle(unsigned int key) {
}
}

int uiGetItem(UIhandle handle) {
int uiGetItem(void *handle) {
unsigned int key = uiHashHandle(handle);
UIhandleEntry *e = uiHashLookupHandle(key);
return e?(e->item):-1;
}

static void uiHashInsertHandle(UIhandle handle, int item) {
static void uiHashInsertHandle(void *handle, int item) {
unsigned int key = uiHashHandle(handle);
UIhandleEntry *e = uiHashLookupHandle(key);
if (e) { // update
@@ -1053,6 +1048,14 @@ void uiClear() {
memset(ui_context->handles, 0, sizeof(ui_context->handles));
}

void uiClearHandleState() {
assert(ui_context);
ui_context->hot_handle = NULL;
ui_context->active_handle = NULL;
ui_context->focus_handle = NULL;
ui_context->last_click_handle = NULL;
}

int uiItem() {
assert(ui_context);
assert(ui_context->count < UI_MAX_ITEMS);
@@ -1064,7 +1067,6 @@ int uiItem() {
item->lastkid = -1;
item->nextitem = -1;
item->previtem = -1;
item->data = -1;
for (int i = 0; i < 4; ++i)
item->relto[i] = -1;
return idx;
@@ -1400,36 +1402,28 @@ int uiParent(int item) {
return uiItemPtr(item)->parent;
}

const void *uiGetData(int item) {
UIitem *pitem = uiItemPtr(item);
if (pitem->data < 0) return NULL;
return ui_context->data + pitem->data;
}

void *uiAllocData(int item, int size) {
void *uiAllocHandle(int item, int size) {
assert((size > 0) && (size < UI_MAX_DATASIZE));
UIitem *pitem = uiItemPtr(item);
assert(pitem->data < 0);
assert(pitem->handle == NULL);
assert((ui_context->datasize+size) <= UI_MAX_BUFFERSIZE);
pitem->data = ui_context->datasize;
pitem->handle = ui_context->data + ui_context->datasize;
pitem->flags |= UI_ITEM_DATA;
ui_context->datasize += size;
return ui_context->data + pitem->data;
uiHashInsertHandle(pitem->handle, item);
return pitem->handle;
}

void uiSetHandle(int item, UIhandle handle) {
uiItemPtr(item)->handle = handle;
void uiSetHandle(int item, void *handle) {
UIitem *pitem = uiItemPtr(item);
assert(pitem->handle == NULL);
pitem->handle = handle;
if (handle) {
uiHashInsertHandle(handle, item);
}
}

void uiSetSelfHandle(int item) {
UIitem *pitem = uiItemPtr(item);
pitem->handle = (UIhandle)pitem;
uiHashInsertHandle((UIhandle)pitem, item);
}

UIhandle uiGetHandle(int item) {
void *uiGetHandle(int item) {
return uiItemPtr(item)->handle;
}

@@ -1599,7 +1593,7 @@ void uiProcess(int timestamp) {
}
if (active_item >= 0) {
UIhandle active_handle = uiGetHandle(active_item);
void *active_handle = uiGetHandle(active_item);
if (
((timestamp - ui_context->last_click_timestamp) > UI_CLICK_THRESHOLD)
|| (ui_context->last_click_handle != active_handle)) {


Loading…
Cancel
Save