Browse Source

- recover item ids in hierarchies where possible

- added uiRecoverItem, uiRemapItem
pull/1/head
Leonard Ritter 10 years ago
parent
commit
b04311e064
2 changed files with 138 additions and 14 deletions
  1. +17
    -4
      example.cpp
  2. +121
    -10
      oui.h

+ 17
- 4
example.cpp View File

@@ -780,7 +780,7 @@ void draw_demostuff(NVGcontext *vg, int x, int y, float w, float h) {


void build_democontent(int parent) { void build_democontent(int parent) {
// some persistent variables for demonstration // some persistent variables for demonstration
static int enum1 = 0;
static int enum1 = -1;
static float progress1 = 0.25f; static float progress1 = 0.25f;
static float progress2 = 0.75f; static float progress2 = 0.75f;
static int option1 = 1; static int option1 = 1;
@@ -794,12 +794,14 @@ void build_democontent(int parent) {
column_append(col, button(BND_ICON_GHOST, "Item 1", demohandler)); column_append(col, button(BND_ICON_GHOST, "Item 1", demohandler));
column_append(col, button(BND_ICON_GHOST, "Item 2", demohandler));
if (option3)
column_append(col, button(BND_ICON_GHOST, "Item 2", demohandler));


{ {
int h = column_append(col, hbox()); int h = column_append(col, hbox());
hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.0", &enum1)); hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.0", &enum1));
uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_REC, NULL, &enum1)), -1,0,0,0);
if (option2)
uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_REC, NULL, &enum1)), -1,0,0,0);
uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_PLAY, NULL, &enum1)), -1,0,0,0); uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_PLAY, NULL, &enum1)), -1,0,0,0);
uiSetMargins(hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.3", &enum1)), -1,0,0,0); uiSetMargins(hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.3", &enum1)), -1,0,0,0);
} }
@@ -1101,6 +1103,17 @@ void draw(NVGcontext *vg, float w, float h) {
uiLayout(); uiLayout();
drawUI(vg, 0, BND_CORNER_NONE); drawUI(vg, 0, BND_CORNER_NONE);
for (int i = 0; i < uiGetLastItemCount(); ++i) {
if (uiRecoverItem(i) == -1) {
UIitem *pitem = uiLastItemPtr(i);
nvgBeginPath(vg);
nvgRect(vg,pitem->margins[0],pitem->margins[1],pitem->size[0],pitem->size[1]);
nvgStrokeWidth(vg, 2);
nvgStrokeColor(vg, nvgRGBAf(1.0f,0.0f,0.0f,0.5f));
nvgStroke(vg);
}
}

if (choice == opt_blendish_demo) { if (choice == opt_blendish_demo) {
UIvec2 cursor = uiGetCursor(); UIvec2 cursor = uiGetCursor();
cursor.x -= w/2; cursor.x -= w/2;
@@ -1261,7 +1274,7 @@ int main()
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();
} }
printf("Peak item count: %i (%u bytes)\nPeak allocated handles: %u bytes\n",
printf("Peak item count: %i (%lu bytes)\nPeak allocated handles: %u bytes\n",
peak_items, peak_items * sizeof(UIitem), peak_alloc); peak_items, peak_items * sizeof(UIitem), peak_alloc);


uiDestroyContext(uictx); uiDestroyContext(uictx);


+ 121
- 10
oui.h View File

@@ -447,6 +447,9 @@ OUI_EXPORT void uiMakeCurrent(UIcontext *ctx);
// context is the current context, the current context will be set to NULL // context is the current context, the current context will be set to NULL
OUI_EXPORT void uiDestroyContext(UIcontext *ctx); OUI_EXPORT void uiDestroyContext(UIcontext *ctx);


// returns the currently selected context or NULL
OUI_EXPORT UIcontext *uiGetContext();

// Input Control // Input Control
// ------------- // -------------


@@ -698,6 +701,24 @@ OUI_EXPORT short uiGetMarginRight(int item);
// return the bottom margin of the item as set with uiSetMargins() // return the bottom margin of the item as set with uiSetMargins()
OUI_EXPORT short uiGetMarginDown(int item); OUI_EXPORT short uiGetMarginDown(int item);


// when uiClear() is called, the most recently declared items are retained.
// when uiLayout() completes, it matches the old item hierarchy to the new one
// and attempts to map old items to new items as well as possible.
// when passed an item Id from the previous frame, uiRecoverItem() returns the
// items new assumed Id, or -1 if the item could not be mapped.
// it is valid to pass -1 as item.
OUI_EXPORT int uiRecoverItem(int olditem);

// in cases where it is important to recover old state over changes in
// the view, and the built-in remapping fails, the UI declaration can manually
// remap old items to new IDs in cases where e.g. the previous item ID has been
// temporarily saved; uiRemapItem() would then be called after creating the
// new item using uiItem().
OUI_EXPORT void uiRemapItem(int olditem, int newitem);

// returns the number if items that have been allocated in the last frame
OUI_EXPORT int uiGetLastItemCount();

#ifdef __cplusplus #ifdef __cplusplus
}; };
#endif #endif
@@ -758,6 +779,12 @@ enum {
UI_ITEM_DATA = 0x100000, UI_ITEM_DATA = 0x100000,
// item has been inserted (bit 21) // item has been inserted (bit 21)
UI_ITEM_INSERTED = 0x200000, UI_ITEM_INSERTED = 0x200000,

// which flag bits will be compared
UI_ITEM_COMPARE_MASK = UI_ITEM_BOX_MODEL_MASK
| (UI_ITEM_LAYOUT_MASK & ~UI_BREAK)
| UI_ITEM_EVENT_MASK
| UI_USERMASK,
}; };


typedef struct UIitem { typedef struct UIitem {
@@ -768,6 +795,7 @@ typedef struct UIitem {
unsigned int flags; unsigned int flags;


// index of first kid // index of first kid
// if old item: index of equivalent new item
int firstkid; int firstkid;
// index of next sibling with same parent // index of next sibling with same parent
int nextitem; int nextitem;
@@ -825,17 +853,19 @@ struct UIcontext {
UIstate state; UIstate state;
unsigned int active_key; unsigned int active_key;
unsigned int active_modifier; unsigned int active_modifier;
int event_item;
int last_timestamp; int last_timestamp;
int last_click_timestamp; int last_click_timestamp;
int clicks; int clicks;


int count; int count;
int last_count;
int eventcount; int eventcount;
unsigned int datasize; unsigned int datasize;


UIitem *items; UIitem *items;
unsigned char *data; unsigned char *data;
UIitem *last_items;
int *item_map;
UIinputEvent events[UI_MAX_INPUT_EVENTS]; UIinputEvent events[UI_MAX_INPUT_EVENTS];
}; };


@@ -858,6 +888,8 @@ UIcontext *uiCreateContext(
ctx->item_capacity = item_capacity; ctx->item_capacity = item_capacity;
ctx->buffer_capacity = buffer_capacity; ctx->buffer_capacity = buffer_capacity;
ctx->items = (UIitem *)malloc(sizeof(UIitem) * item_capacity); ctx->items = (UIitem *)malloc(sizeof(UIitem) * item_capacity);
ctx->last_items = (UIitem *)malloc(sizeof(UIitem) * item_capacity);
ctx->item_map = (int *)malloc(sizeof(int) * item_capacity);
if (buffer_capacity) { if (buffer_capacity) {
ctx->data = (unsigned char *)malloc(buffer_capacity); ctx->data = (unsigned char *)malloc(buffer_capacity);
} }
@@ -878,10 +910,16 @@ void uiDestroyContext(UIcontext *ctx) {
if (ui_context == ctx) if (ui_context == ctx)
uiMakeCurrent(NULL); uiMakeCurrent(NULL);
free(ctx->items); free(ctx->items);
free(ctx->last_items);
free(ctx->item_map);
free(ctx->data); free(ctx->data);
free(ctx); free(ctx);
} }


OUI_EXPORT UIcontext *uiGetContext() {
return ui_context;
}

void uiSetButton(int button, int enabled) { void uiSetButton(int button, int enabled) {
assert(ui_context); assert(ui_context);
unsigned long long mask = 1ull<<button; unsigned long long mask = 1ull<<button;
@@ -996,6 +1034,11 @@ int uiGetItemCount() {
return ui_context->count; return ui_context->count;
} }


int uiGetLastItemCount() {
assert(ui_context);
return ui_context->last_count;
}

unsigned int uiGetAllocSize() { unsigned int uiGetAllocSize() {
assert(ui_context); assert(ui_context);
return ui_context->datasize; return ui_context->datasize;
@@ -1006,6 +1049,11 @@ UIitem *uiItemPtr(int item) {
return ui_context->items + item; return ui_context->items + item;
} }


UIitem *uiLastItemPtr(int item) {
assert(ui_context && (item >= 0) && (item < ui_context->last_count));
return ui_context->last_items + item;
}

int uiGetHotItem() { int uiGetHotItem() {
assert(ui_context); assert(ui_context);
return ui_context->hot_item; return ui_context->hot_item;
@@ -1018,14 +1066,10 @@ void uiFocus(int item) {


static void uiValidateStateItems() { static void uiValidateStateItems() {
assert(ui_context); assert(ui_context);
if (ui_context->last_hot_item >= ui_context->count)
ui_context->last_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;
ui_context->last_hot_item = uiRecoverItem(ui_context->last_hot_item);
ui_context->active_item = uiRecoverItem(ui_context->active_item);
ui_context->focus_item = uiRecoverItem(ui_context->focus_item);
ui_context->last_click_item = uiRecoverItem(ui_context->last_click_item);
} }


int uiGetFocusedItem() { int uiGetFocusedItem() {
@@ -1035,9 +1079,17 @@ int uiGetFocusedItem() {


void uiClear() { void uiClear() {
assert(ui_context); assert(ui_context);
ui_context->last_count = ui_context->count;
ui_context->count = 0; ui_context->count = 0;
ui_context->datasize = 0; ui_context->datasize = 0;
ui_context->hot_item = -1; ui_context->hot_item = -1;
// swap buffers
UIitem *items = ui_context->items;
ui_context->items = ui_context->last_items;
ui_context->last_items = items;
for (int i = 0; i < ui_context->last_count; ++i) {
ui_context->item_map[i] = -1;
}
} }


void uiClearState() { void uiClearState() {
@@ -1064,7 +1116,6 @@ void uiNotifyItem(int item, UIevent event) {
if (!ui_context->handler) if (!ui_context->handler)
return; return;
assert((event & UI_ITEM_EVENT_MASK) == event); assert((event & UI_ITEM_EVENT_MASK) == event);
ui_context->event_item = item;
UIitem *pitem = uiItemPtr(item); UIitem *pitem = uiItemPtr(item);
if (pitem->flags & event) { if (pitem->flags & event) {
ui_context->handler(item, event); ui_context->handler(item, event);
@@ -1476,6 +1527,61 @@ static void uiArrange(int item, int dim) {
} }
} }


UI_INLINE bool uiCompareItems(UIitem *item1, UIitem *item2) {
return ((item1->flags & UI_ITEM_COMPARE_MASK) == (item2->flags & UI_ITEM_COMPARE_MASK));

}

static bool uiMapItems(int item1, int item2) {
UIitem *pitem1 = uiLastItemPtr(item1);
if (item2 == -1) {
return false;
}

UIitem *pitem2 = uiItemPtr(item2);
if (!uiCompareItems(pitem1, pitem2)) {
return false;
}

int count = 0;
int failed = 0;
int kid1 = pitem1->firstkid;
int kid2 = pitem2->firstkid;
while (kid1 != -1) {
UIitem *pkid1 = uiLastItemPtr(kid1);
count++;
if (!uiMapItems(kid1, kid2)) {
failed = count;
break;
}
kid1 = pkid1->nextitem;
if (kid2 != -1) {
kid2 = uiItemPtr(kid2)->nextitem;
}
}

if (count && (failed == 1)) {
return false;
}

ui_context->item_map[item1] = item2;
return true;
}

int uiRecoverItem(int olditem) {
assert(ui_context);
assert((olditem >= -1) && (olditem < ui_context->last_count));
if (olditem == -1) return -1;
return ui_context->item_map[olditem];
}

void uiRemapItem(int olditem, int newitem) {
assert(ui_context);
assert((olditem >= 0) && (olditem < ui_context->last_count));
assert((newitem >= -1) && (newitem < ui_context->count));
ui_context->item_map[olditem] = newitem;
}

void uiLayout() { void uiLayout() {
assert(ui_context); assert(ui_context);
if (!ui_context->count) return; if (!ui_context->count) return;
@@ -1485,6 +1591,11 @@ void uiLayout() {
uiComputeSize(0,1); uiComputeSize(0,1);
uiArrange(0,1); uiArrange(0,1);


if (ui_context->last_count && ui_context->count) {
// map old item id to new item id
uiMapItems(0,0);
}

uiValidateStateItems(); uiValidateStateItems();
// drawing routines may require this to be set already // drawing routines may require this to be set already
uiUpdateHotItem(); uiUpdateHotItem();


Loading…
Cancel
Save