From b95cf18c924ac42277c894b65c7ad3d7c38432e1 Mon Sep 17 00:00:00 2001 From: Leonard Ritter Date: Sun, 21 Sep 2014 19:05:40 +0200 Subject: [PATCH] oui: use item identity for state keeping --- example.cpp | 5 +- oui.h | 158 ++++++++++++++-------------------------------------- 2 files changed, 43 insertions(+), 120 deletions(-) diff --git a/example.cpp b/example.cpp index 80c4664..217a46f 100644 --- a/example.cpp +++ b/example.cpp @@ -383,7 +383,7 @@ int column_append(int parent, int item) { // fill parent horizontally, anchor to previous item vertically uiSetLayout(item, UI_HFILL|UI_TOP); // if not the first item, add a margin of 1 - uiSetMargins(item, 0, (last < 0)?0:1, 0, 0); + uiSetMargins(item, 0, 1, 0, 0); return item; } @@ -399,8 +399,6 @@ int vgroup_append(int parent, int item) { uiSetBelow(item, last); // fill parent horizontally, anchor to previous item vertically uiSetLayout(item, UI_HFILL|UI_TOP); - // if not the first item, add a margin - uiSetMargins(item, 0, (last < 0)?0:-2, 0, 0); return item; } @@ -416,7 +414,6 @@ int hgroup_append(int parent, int item) { if (last > 0) uiSetLeftTo(last, item); uiSetLayout(item, UI_LEFT|UI_RIGHT); - uiSetMargins(item, (last < 0)?0:-1, 0, 0, 0); return item; } diff --git a/oui.h b/oui.h index 83f8bfe..1411517 100644 --- a/oui.h +++ b/oui.h @@ -421,10 +421,9 @@ OUI_EXPORT void uiUpdateHotItem(); 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(); +// a re-declaration of the UI changes the item indices, to avoid state +// related glitches because item identities have changed. +OUI_EXPORT void uiClearState(); // UI Declaration // -------------- @@ -532,10 +531,6 @@ OUI_EXPORT UIitemState uiGetState(int item); // 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(void *handle); - // return the item that is currently under the cursor or -1 for none OUI_EXPORT int uiGetHotItem(); @@ -771,14 +766,14 @@ struct UIcontext { // accumulated scroll wheel offsets UIvec2 scroll; - void *hot_handle; - void *active_handle; - void *focus_handle; - void *last_click_handle; + int hot_item; + int active_item; + int focus_item; + int last_click_item; + UIrect hot_rect; UIrect active_rect; UIstate state; - int hot_item; unsigned int active_key; unsigned int active_modifier; int event_item; @@ -792,7 +787,6 @@ struct UIcontext { UIitem items[UI_MAX_ITEMS]; unsigned char data[UI_MAX_BUFFERSIZE]; - UIhandleEntry handles[UI_MAX_ITEMS]; UIinputEvent events[UI_MAX_INPUT_EVENTS]; }; @@ -812,6 +806,7 @@ UIcontext *uiCreateContext() { UIcontext *oldctx = ui_context; uiMakeCurrent(ctx); uiClear(); + uiClearState(); uiMakeCurrent(oldctx); return ctx; } @@ -826,81 +821,6 @@ void uiDestroyContext(UIcontext *ctx) { free(ctx); } -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; - x += x>>5; - x ^= x<<2; - x += x>>15; - x ^= x<<10; - return x?x:1; // must not be zero -} - -UI_INLINE unsigned int uiHashProbeDistance(unsigned int key, unsigned int slot_index) { - unsigned int pos = key & (UI_MAX_ITEMS-1); - return (slot_index + UI_MAX_ITEMS - pos) & (UI_MAX_ITEMS-1); -} - -UI_INLINE UIhandleEntry *uiHashLookupHandle(unsigned int key) { - assert(ui_context); - int pos = key & (UI_MAX_ITEMS-1); - unsigned int dist = 0; - for (;;) { - UIhandleEntry *entry = ui_context->handles + pos; - unsigned int pos_key = entry->key; - if (!pos_key) return NULL; - else if (entry->key == key) - return entry; - else if (dist > uiHashProbeDistance(pos_key, pos)) - return NULL; - pos = (pos+1) & (UI_MAX_ITEMS-1); - ++dist; - } -} - -int uiGetItem(void *handle) { - unsigned int key = uiHashHandle(handle); - UIhandleEntry *e = uiHashLookupHandle(key); - return e?(e->item):-1; -} - -static void uiHashInsertHandle(void *handle, int item) { - unsigned int key = uiHashHandle(handle); - UIhandleEntry *e = uiHashLookupHandle(key); - if (e) { // update - e->item = item; - return; - } - - int pos = key & (UI_MAX_ITEMS-1); - unsigned int dist = 0; - for (unsigned int i = 0; i < UI_MAX_ITEMS; ++i) { - int index = (pos + i) & (UI_MAX_ITEMS-1); - unsigned int pos_key = ui_context->handles[index].key; - if (!pos_key) { - ui_context->handles[index].key = key; - ui_context->handles[index].item = item; - break; - } else { - unsigned int probe_distance = uiHashProbeDistance(pos_key, index); - if (dist > probe_distance) { - unsigned int oldkey = ui_context->handles[index].key; - unsigned int olditem = ui_context->handles[index].item; - ui_context->handles[index].key = key; - ui_context->handles[index].item = item; - key = oldkey; - item = olditem; - dist = probe_distance; - } - } - ++dist; - } -} - void uiSetButton(int button, int enabled) { assert(ui_context); unsigned long long mask = 1ull<= -1) && (item < ui_context->count)); - ui_context->focus_handle = (item < 0)?0:uiGetHandle(item); + ui_context->focus_item = item; +} + +static void uiValidateStateItems() { + assert(ui_context); + if (ui_context->hot_item >= ui_context->count) + ui_context->hot_item = -1; + if (ui_context->active_item >= ui_context->count) + ui_context->active_item = -1; + if (ui_context->focus_item >= ui_context->count) + ui_context->focus_item = -1; + if (ui_context->last_click_item >= ui_context->count) + ui_context->last_click_item = -1; } int uiGetFocusedItem() { assert(ui_context); - return ui_context->focus_handle?uiGetItem(ui_context->focus_handle):-1; + uiValidateStateItems(); + return ui_context->focus_item; } void uiClear() { @@ -1045,15 +978,14 @@ void uiClear() { ui_context->count = 0; ui_context->datasize = 0; ui_context->hot_item = -1; - memset(ui_context->handles, 0, sizeof(ui_context->handles)); } -void uiClearHandleState() { +void uiClearState() { assert(ui_context); - ui_context->hot_handle = NULL; - ui_context->active_handle = NULL; - ui_context->focus_handle = NULL; - ui_context->last_click_handle = NULL; + ui_context->hot_item = -1; + ui_context->active_item = -1; + ui_context->focus_item = -1; + ui_context->last_click_item = -1; } int uiItem() { @@ -1410,7 +1342,6 @@ void *uiAllocHandle(int item, int size) { pitem->handle = ui_context->data + ui_context->datasize; pitem->flags |= UI_ITEM_DATA; ui_context->datasize += size; - uiHashInsertHandle(pitem->handle, item); return pitem->handle; } @@ -1418,9 +1349,6 @@ void uiSetHandle(int item, void *handle) { UIitem *pitem = uiItemPtr(item); assert(pitem->handle == NULL); pitem->handle = handle; - if (handle) { - uiHashInsertHandle(handle, item); - } } void *uiGetHandle(int item) { @@ -1529,6 +1457,7 @@ void uiLayout() { uiItemPtr(0)->rect.y = uiItemPtr(0)->margins[1]; uiLayoutItem(0,1); + uiValidateStateItems(); // drawing routines may require this to be set already uiUpdateHotItem(); } @@ -1551,9 +1480,9 @@ void uiProcess(int timestamp) { return; } - int hot_item = uiGetItem(ui_context->hot_handle); - int active_item = uiGetItem(ui_context->active_handle); - int focus_item = uiGetItem(ui_context->focus_handle); + int hot_item = ui_context->hot_item; + int active_item = ui_context->active_item; + int focus_item = ui_context->focus_item; // send all keyboard events if (focus_item >= 0) { @@ -1564,7 +1493,7 @@ void uiProcess(int timestamp) { ui_context->events[i].event); } } else { - ui_context->focus_handle = 0; + ui_context->focus_item = -1; } if (ui_context->scroll.x || ui_context->scroll.y) { int scroll_item = uiFindItemForEvent(0, UI_SCROLL, NULL, @@ -1589,20 +1518,19 @@ void uiProcess(int timestamp) { if (active_item != focus_item) { focus_item = -1; - ui_context->focus_handle = 0; + ui_context->focus_item = -1; } if (active_item >= 0) { - void *active_handle = uiGetHandle(active_item); if ( ((timestamp - ui_context->last_click_timestamp) > UI_CLICK_THRESHOLD) - || (ui_context->last_click_handle != active_handle)) { + || (ui_context->last_click_item != active_item)) { ui_context->clicks = 0; } ui_context->clicks++; ui_context->last_click_timestamp = timestamp; - ui_context->last_click_handle = active_handle; + ui_context->last_click_item = active_item; uiNotifyItem(active_item, UI_BUTTON0_DOWN); } ui_context->state = UI_STATE_CAPTURE; @@ -1641,10 +1569,8 @@ void uiProcess(int timestamp) { } ui_context->last_cursor = ui_context->cursor; - ui_context->hot_handle = (hot_item>=0)? - uiGetHandle(hot_item):0; - ui_context->active_handle = (active_item>=0)? - uiGetHandle(active_item):0; + ui_context->hot_item = hot_item; + ui_context->active_item = active_item; ui_context->last_timestamp = timestamp; ui_context->last_buttons = ui_context->buttons; @@ -1652,17 +1578,17 @@ void uiProcess(int timestamp) { static int uiIsActive(int item) { assert(ui_context); - return (ui_context->active_handle)&&(uiGetHandle(item) == ui_context->active_handle); + return ui_context->active_item == item; } static int uiIsHot(int item) { assert(ui_context); - return (ui_context->hot_handle)&&(uiGetHandle(item) == ui_context->hot_handle); + return ui_context->hot_item == item; } static int uiIsFocused(int item) { assert(ui_context); - return (ui_context->focus_handle)&&(uiGetHandle(item) == ui_context->focus_handle); + return ui_context->focus_item == item; } UIitemState uiGetState(int item) {