Browse Source

oui: use item identity for state keeping

pull/1/head
Leonard Ritter 10 years ago
parent
commit
b95cf18c92
2 changed files with 43 additions and 120 deletions
  1. +1
    -4
      example.cpp
  2. +42
    -116
      oui.h

+ 1
- 4
example.cpp View File

@@ -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;
}



+ 42
- 116
oui.h View File

@@ -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<<button;
@@ -1032,12 +952,25 @@ int uiGetHotItem() {

void uiFocus(int item) {
assert(ui_context && (item >= -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) {


Loading…
Cancel
Save