Browse Source

more work on oui.h: simplifications, better support for radio buttons

pull/1/head
Leonard Ritter 10 years ago
parent
commit
ec0611d613
2 changed files with 147 additions and 51 deletions
  1. +56
    -39
      example.cpp
  2. +91
    -12
      oui.h

+ 56
- 39
example.cpp View File

@@ -66,7 +66,7 @@ int cornerFlags(int item) {
} }


void drawUI(NVGcontext *vg, int item, int x, int y) { void drawUI(NVGcontext *vg, int item, int x, int y) {
UIData *data = (UIData *)uiGetData(item);
const UIData *data = (const UIData *)uiGetData(item);
UIrect rect = uiGetRect(item); UIrect rect = uiGetRect(item);
rect.x += x; rect.x += x;
rect.y += y; rect.y += y;
@@ -86,8 +86,9 @@ void drawUI(NVGcontext *vg, int item, int x, int y) {
data->iconid,data->label); data->iconid,data->label);
} break; } break;
case ST_RADIO:{ case ST_RADIO:{
BNDwidgetState state = (BNDwidgetState)uiGetState(item);
bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h, bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h,
cornerFlags(item),(BNDwidgetState)uiGetState(item),
cornerFlags(item),state,
data->iconid,data->label); data->iconid,data->label);
} break; } break;
} }
@@ -102,6 +103,42 @@ void drawUI(NVGcontext *vg, int item, int x, int y) {
} }
} }


int label(int parent, int iconid, const char *label) {
UIData data = { sizeof(UIData), ST_DEFAULT, iconid, label };
return uiItem(parent, 0, UI_LABEL, 0, BND_WIDGET_HEIGHT, &data);
}

int button(int parent, UIhandle handle, int iconid, const char *label,
UIhandler handler) {
UIData data = { sizeof(UIData), ST_DEFAULT, iconid, label };
int item = uiItem(parent, handle, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
uiSetHandler(item, handler);
return item;
}

static UIhandle radio_handle = 0;

void radiohandler(int item) {
radio_handle = uiGetHandle(item);
uiSetActive(item, 1);
}

int radio(int parent, UIhandle handle, int iconid, const char *label) {
UIData data = { sizeof(UIData), ST_RADIO, iconid, label };
int w = (label)?0:BND_TOOL_WIDTH;
int item = uiItem(parent, handle, UI_BUTTON, w, BND_WIDGET_HEIGHT, &data);
uiSetHandler(item, radiohandler);
uiSetEarlyHandler(item, true);
if (radio_handle == handle)
uiSetActive(item, 1);
return item;
}

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

void draw(NVGcontext *vg, float w, float h) { void draw(NVGcontext *vg, float w, float h) {
bndBackground(vg, 0, 0, w, h); bndBackground(vg, 0, 0, w, h);
@@ -288,60 +325,40 @@ void draw(NVGcontext *vg, float w, float h) {
bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT, bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,
BND_DEFAULT,BND_ICONID(5,11),NULL); BND_DEFAULT,BND_ICONID(5,11),NULL);
// some OUI stuff
uiClear(); uiClear();
uiSetRect(0,600,10,250,400); uiSetRect(0,600,10,250,400);
int col = uiColumn(0,1); int col = uiColumn(0,1);
UIData data = { sizeof(UIData), ST_DEFAULT, BND_ICONID(6,3), "Item 1" };
uiItem(col, 1, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.label = "Item 2";
uiItem(col, 2, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
button(col, 1, BND_ICONID(6,3), "Item 1", demohandler);
button(col, 2, BND_ICONID(6,3), "Item 2", demohandler);
{ {
int row = uiRow(col,-1); int row = uiRow(col,-1);
data.subtype = ST_RADIO;
data.label = "Item 3.0";
uiItem(row, 3, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.label = NULL;
data.iconid = BND_ICONID(0,10);
uiItem(row, 4, UI_BUTTON, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, &data);
data.label = NULL;
data.iconid = BND_ICONID(1,10);
uiItem(row, 5, UI_BUTTON, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, &data);
data.iconid = BND_ICONID(6,3);
data.label = "Item 3.3";
uiItem(row, 6, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.subtype = ST_DEFAULT;
radio(row, 3, BND_ICONID(6,3), "Item 3.0");
radio(row, 4, BND_ICONID(0,10), NULL);
radio(row, 5, BND_ICONID(1,10), NULL);
radio(row, 6, BND_ICONID(6,3), "Item 3.3");
} }
{ {
int row = uiRow(col,8); int row = uiRow(col,8);
int coll = uiColumn(row,-2); int coll = uiColumn(row,-2);
data.label = "Items 4.0:";
data.iconid = -1;
uiItem(coll, 0, UI_LABEL, 0, BND_WIDGET_HEIGHT, &data);
label(coll, -1, "Items 4.0:");
coll = uiColumn(coll,-2); coll = uiColumn(coll,-2);
data.label = "Item 4.0.0";
data.iconid = BND_ICONID(6,3);
uiItem(coll, 7, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.label = "Item 4.0.1";
uiItem(coll, 8, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
button(coll, 7, BND_ICONID(6,3), "Item 4.0.0", demohandler);
button(coll, 8, BND_ICONID(6,3), "Item 4.0.1", demohandler);
int colr = uiColumn(row,-2); int colr = uiColumn(row,-2);
data.label = "Items 4.1:";
data.iconid = -1;
uiItem(colr, 0, UI_LABEL, 0, BND_WIDGET_HEIGHT, &data);
label(colr, -1, "Items 4.1:");
colr = uiColumn(colr,-2); colr = uiColumn(colr,-2);
data.label = "Item 4.1.0";
data.iconid = BND_ICONID(6,3);
uiItem(colr, 9, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.label = "Item 4.1.1";
uiItem(colr,10, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
button(colr, 9, BND_ICONID(6,3), "Item 4.1.0", demohandler);
button(colr,10, BND_ICONID(6,3), "Item 4.1.1", demohandler);
} }
data.label = "Item 5";
uiItem(col,11, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
button(col, 11, BND_ICONID(6,3), "Item 5", NULL);
uiLayout();
uiProcess();
drawUI(vg, 0, 0, 0); drawUI(vg, 0, 0, 0);


+ 91
- 12
oui.h View File

@@ -163,9 +163,9 @@ int uiRow(int parent, int spacing);


// layout all added items and update the internal state according to the // layout all added items and update the internal state according to the
// current cursor position and button states. // current cursor position and button states.
// It is safe to immediately draw the items after a call to uiLayout().
// It is safe to immediately draw the items after a call to uiProcess().
// this is an O(N) operation for N = number of declared items. // this is an O(N) operation for N = number of declared items.
void uiLayout();
void uiProcess();


// returns the number of child items a container item contains. If the item // returns the number of child items a container item contains. If the item
// is not a container or does not contain any items, 0 is returned. // is not a container or does not contain any items, 0 is returned.
@@ -208,17 +208,17 @@ int uiGetSpacing(int item);
int uiGetKind(int item); int uiGetKind(int item);


// returns the items layout rectangle relative to its parent. If uiGetRect() // returns the items layout rectangle relative to its parent. If uiGetRect()
// is called before uiLayout(), the values of the returned rectangle are
// is called before uiProcess(), the values of the returned rectangle are
// undefined. // undefined.
UIrect uiGetRect(int item); UIrect uiGetRect(int item);


// returns the items layout rectangle in absolute coordinates. If // returns the items layout rectangle in absolute coordinates. If
// uiGetAbsoluteRect() is called before uiLayout(), the values of the returned
// uiGetAbsoluteRect() is called before uiProcess(), the values of the returned
// rectangle are undefined. // rectangle are undefined.
UIrect uiGetScreenRect(int item); UIrect uiGetScreenRect(int item);


// explicitly assign a layout rectangle to an item; If uiSetRect() is called // explicitly assign a layout rectangle to an item; If uiSetRect() is called
// after uiLayout(), behavior is undefined.
// after uiProcess(), behavior is undefined.
// This function is primarily used to position the root element. // This function is primarily used to position the root element.
void uiSetRect(int item, int x, int y, int w, int h); void uiSetRect(int item, int x, int y, int w, int h);


@@ -227,7 +227,7 @@ void uiSetRect(int item, int x, int y, int w, int h);
const void *uiGetData(int item); const void *uiGetData(int item);


// return the application-dependent handle of the item as passed to uiItem(). // return the application-dependent handle of the item as passed to uiItem().
int uiGetHandle(int item);
UIhandle uiGetHandle(int item);


// return the current state of the item. // return the current state of the item.
// The returned value is one of UI_COLD, UI_HOT, UI_ACTIVE. // The returned value is one of UI_COLD, UI_HOT, UI_ACTIVE.
@@ -237,6 +237,27 @@ int uiGetState(int item);
// callback is dependent on the item kind. // callback is dependent on the item kind.
void uiSetHandler(int item, UIhandler handler); void uiSetHandler(int item, UIhandler handler);


// return the handler callback for an item as passed to uiSetHandler()
UIhandler uiGetHandler(int item);

// set the state of a toggleable item to active. If set, uiGetState() will
// always return UI_ACTIVE.
// enabled is 1 for active, 0 for default behavior
void uiSetActive(int item, int enabled);

// returns the active state of a toggleable item;
// the function returns 1 if the item is always active, 0 for default behavior.
int uiGetActive(int item);

// set an interactive item to activate on button-down. The default behavior
// is to call the handler callback when the button is released; if set,
// the handler will already be called if the button is pressed.
void uiSetEarlyHandler(int item, int enabled);

// returns the setting passed to uiSetEarlyHandler();
// the function returns 1 if the setting is active, 0 for default behavior.
int uiGetEarlyHandler(int item);

#endif // _UI_H_ #endif // _UI_H_


#define UI_IMPLEMENTATION #define UI_IMPLEMENTATION
@@ -246,7 +267,19 @@ void uiSetHandler(int item, UIhandler handler);


#define UI_MAX_KIND 16 #define UI_MAX_KIND 16


typedef enum UIflags {
// if true, item is always active
UI_FLAG_ALWAYS_ACTIVE = (1<<0),
// if true, activate on mousedown, not mouseup
UI_FLAG_EARLY_HANDLER = (1<<1),
} UIflags;

typedef struct UIitem { typedef struct UIitem {
// declaration independent unique handle (for persistence)
UIhandle handle;
// handler
UIhandler handler;
// container structure // container structure
// number of kids // number of kids
@@ -267,8 +300,6 @@ typedef struct UIitem {
// attributes // attributes
// declaration independent unique handle (for persistence)
UIhandle handle;
// layout rectangle // layout rectangle
UIrect rect; UIrect rect;
// absolute position // absolute position
@@ -279,8 +310,8 @@ typedef struct UIitem {
int data; int data;
// layouting containers: spacing between items // layouting containers: spacing between items
int spacing; int spacing;
// handler
UIhandler handler;
// a combination of UIflags
int flags;
} UIitem; } UIitem;


struct UIcontext { struct UIcontext {
@@ -289,6 +320,7 @@ struct UIcontext {
UIhandle hot; UIhandle hot;
UIhandle active; UIhandle active;
int handle_item;
int count; int count;
UIitem items[UI_MAX_ITEMS]; UIitem items[UI_MAX_ITEMS];
@@ -463,13 +495,40 @@ int uiGetKind(int item) {
return uiItemPtr(item)->kind; return uiItemPtr(item)->kind;
} }


static void uiSetFlag(int item, int flag, int enabled) {
if (enabled)
uiItemPtr(item)->flags |= flag;
else
uiItemPtr(item)->flags &= ~flag;
}

static int uiGetFlag(int item, int flag) {
return (uiItemPtr(item)->flags & flag)?1:0;
}

void uiSetActive(int item, int enabled) {
uiSetFlag(item, UI_FLAG_ALWAYS_ACTIVE, enabled);
}

int uiGetActive(int item) {
return uiGetFlag(item, UI_FLAG_ALWAYS_ACTIVE);
}

void uiSetEarlyHandler(int item, int enabled) {
uiSetFlag(item, UI_FLAG_EARLY_HANDLER, enabled);
}

int uiGetEarlyHandler(int item) {
return uiGetFlag(item, UI_FLAG_EARLY_HANDLER);
}

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


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


@@ -477,6 +536,10 @@ void uiSetHandler(int item, UIhandler handler) {
uiItemPtr(item)->handler = handler; uiItemPtr(item)->handler = handler;
} }


UIhandler uiGetHandler(int item) {
return uiItemPtr(item)->handler;
}

int uiGetChildId(int item) { int uiGetChildId(int item) {
return uiItemPtr(item)->kidid; return uiItemPtr(item)->kidid;
} }
@@ -602,8 +665,15 @@ void uiUpdateItemState(int item, int x, int y) {
&& (cy<pitem->rect.h)) { && (cy<pitem->rect.h)) {
ui_context->hot = pitem->handle; ui_context->hot = pitem->handle;
// button down, no widget activated
if (!ui_context->active && uiGetButton(0)) { if (!ui_context->active && uiGetButton(0)) {
ui_context->active = pitem->handle; ui_context->active = pitem->handle;
if (pitem->flags & UI_FLAG_EARLY_HANDLER) {
ui_context->handle_item = item;
}
} else if ( // button up, this widget is active
(ui_context->active == pitem->handle) && !uiGetButton(0)) {
ui_context->handle_item = item;
} }
} }
} }
@@ -616,12 +686,19 @@ void uiUpdateItemState(int item, int x, int y) {


} }


void uiLayout() {
void uiProcess() {
ui_context->handle_item = -1;
uiLayoutItem(0); uiLayoutItem(0);
uiUpdateItemState(0, 0, 0); uiUpdateItemState(0, 0, 0);
if (!uiGetButton(0)) { if (!uiGetButton(0)) {
ui_context->active = 0; ui_context->active = 0;
} }
if (ui_context->handle_item >= 0) {
UIhandler handler = uiGetHandler(ui_context->handle_item);
if (handler) {
handler(ui_context->handle_item);
}
}
} }


int uiIsActive(int item) { int uiIsActive(int item) {
@@ -635,6 +712,8 @@ int uiIsHot(int item) {
} }


int uiGetState(int item) { int uiGetState(int item) {
UIitem *pitem = uiItemPtr(item);
if (pitem->flags & UI_FLAG_ALWAYS_ACTIVE) return UI_ACTIVE;
return (!uiIsHot(item))?UI_COLD:(uiIsActive(item))?UI_ACTIVE:UI_HOT; return (!uiIsHot(item))?UI_COLD:(uiIsActive(item))?UI_ACTIVE:UI_HOT;


} }


Loading…
Cancel
Save