Browse Source

documented oui.h

pull/1/head
Leonard Ritter 10 years ago
parent
commit
c78fb2df9c
2 changed files with 215 additions and 45 deletions
  1. +29
    -16
      example.cpp
  2. +186
    -29
      oui.h

+ 29
- 16
example.cpp View File

@@ -21,8 +21,16 @@


//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////


typedef enum {
// default
ST_DEFAULT = 0,
// radio button
ST_RADIO = 1,
} SubType;

typedef struct { typedef struct {
int size; int size;
int subtype;
int iconid; int iconid;
const char *label; const char *label;
} UIData; } UIData;
@@ -69,17 +77,20 @@ void drawUI(NVGcontext *vg, int item, int x, int y) {
bndLabel(vg,rect.x,rect.y,rect.w,rect.h, bndLabel(vg,rect.x,rect.y,rect.w,rect.h,
data->iconid,data->label); data->iconid,data->label);
} break; } break;
case UI_RADIO: {
assert(data);
bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h,
cornerFlags(item),(BNDwidgetState)uiGetState(item),
data->iconid,data->label);
} break;
case UI_BUTTON: { case UI_BUTTON: {
assert(data); assert(data);
bndToolButton(vg,rect.x,rect.y,rect.w,rect.h,
cornerFlags(item),(BNDwidgetState)uiGetState(item),
data->iconid,data->label);
switch(data->subtype) {
default: {
bndToolButton(vg,rect.x,rect.y,rect.w,rect.h,
cornerFlags(item),(BNDwidgetState)uiGetState(item),
data->iconid,data->label);
} break;
case ST_RADIO:{
bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h,
cornerFlags(item),(BNDwidgetState)uiGetState(item),
data->iconid,data->label);
} break;
}
} break; } break;
default: break; default: break;
} }
@@ -282,26 +293,28 @@ void draw(NVGcontext *vg, float w, float h) {
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), BND_ICONID(6,3), "Item 1" };
UIData data = { sizeof(UIData), ST_DEFAULT, BND_ICONID(6,3), "Item 1" };
uiItem(col, 1, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data); uiItem(col, 1, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.label = "Item 2"; data.label = "Item 2";
uiItem(col, 2, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data); uiItem(col, 2, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
{ // nested row
{
int row = uiRow(col,-1); int row = uiRow(col,-1);
data.subtype = ST_RADIO;
data.label = "Item 3.0"; data.label = "Item 3.0";
uiItem(row, 3, UI_RADIO, 0, BND_WIDGET_HEIGHT, &data);
uiItem(row, 3, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.label = NULL; data.label = NULL;
data.iconid = BND_ICONID(0,10); data.iconid = BND_ICONID(0,10);
uiItem(row, 4, UI_RADIO, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, &data);
uiItem(row, 4, UI_BUTTON, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, &data);
data.label = NULL; data.label = NULL;
data.iconid = BND_ICONID(1,10); data.iconid = BND_ICONID(1,10);
uiItem(row, 5, UI_RADIO, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, &data);
uiItem(row, 5, UI_BUTTON, BND_TOOL_WIDTH, BND_WIDGET_HEIGHT, &data);
data.iconid = BND_ICONID(6,3); data.iconid = BND_ICONID(6,3);
data.label = "Item 3.3"; data.label = "Item 3.3";
uiItem(row, 6, UI_RADIO, 0, BND_WIDGET_HEIGHT, &data);
uiItem(row, 6, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
data.subtype = ST_DEFAULT;
} }
{ // two columns
{
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.label = "Items 4.0:";


+ 186
- 29
oui.h View File

@@ -35,76 +35,211 @@ user interfaces; the intended use is for bootstrap situations where only basic
UI services are needed. UI services are needed.
*/ */


// item states as returned by uiGetState()

// the item is inactive
#define UI_COLD 0x0000 #define UI_COLD 0x0000
// the item is inactive, but the cursor is hovering over this item
#define UI_HOT 0x0001 #define UI_HOT 0x0001
// the item is toggled or activated (depends on item kind)
#define UI_ACTIVE 0x0002 #define UI_ACTIVE 0x0002
// the item is unresponsive
#define UI_FROZEN 0x0003
// item kinds
// containers
// this is a reserved kind and only used by the root item 0
#define UI_ROOT 0x0100 #define UI_ROOT 0x0100
// Column container. Arranges child items vertically and adjusts their width to
// the width of the column. Items of fixed width will only be truncated, but not
// expanded.
#define UI_COLUMN 0x0101 #define UI_COLUMN 0x0101
// Row container. Arranges items horizontally and distributes their width to
// match the width of the row. Items of fixed width will only be truncated, but
// not expanded. The remaining space will be equally distributed among all items
// of dynamic width.
#define UI_ROW 0x0102 #define UI_ROW 0x0102


// controls
// Label control. The control is non-interactive and will not call any handlers.
#define UI_LABEL 0x0203 #define UI_LABEL 0x0203
// Button control. Will call the buttons handler when activated.
#define UI_BUTTON 0x0204 #define UI_BUTTON 0x0204
#define UI_RADIO 0x0205


// maximum number of items that may be added
#define UI_MAX_ITEMS 4096 #define UI_MAX_ITEMS 4096
// maximum size in bytes reserved for storage of application dependent data
// as passed to uiItem().
#define UI_MAX_BUFFERSIZE 1048576 #define UI_MAX_BUFFERSIZE 1048576
// maximum size in bytes of a single data buffer passed to uiItem().
#define UI_MAX_DATASIZE 4096 #define UI_MAX_DATASIZE 4096
// maximum depth of nested containers
#define UI_MAX_DEPTH 64 #define UI_MAX_DEPTH 64


// opaque UI context
typedef struct UIcontext UIcontext; typedef struct UIcontext UIcontext;

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


// handler callback
typedef void (*UIhandler)(int item);

// layout rectangle
typedef struct UIrect { typedef struct UIrect {
int x, y, w, h; int x, y, w, h;
} UIrect; } UIrect;


// exemplary buffer of variable size to pass to the data argument of uiItem();
// see uiItem() for more information.
typedef struct UIdata { typedef struct UIdata {
int size; int size;
unsigned char content[1]; unsigned char content[1];
} UIdata; } UIdata;


// unless declared otherwise, all operations have the complexity O(1).

// create a new UI context; call uiMakeCurrent() to make this context the
// current context.
UIcontext *uiCreateContext(); UIcontext *uiCreateContext();

// select an UI context as the current context; a context must always be
// selected before using any of the other UI functions
void uiMakeCurrent(UIcontext *ctx); void uiMakeCurrent(UIcontext *ctx);

// release the memory of an UI context created with uiCreateContext(); if the
// context is the current context, the current context will be set to NULL
void uiDestroyContext(UIcontext *ctx); void uiDestroyContext(UIcontext *ctx);


// sets a mouse or gamepad button as pressed/released
// button is in the range 0..63 and maps to an application defined input
// source.
// enabled is 1 for pressed, 0 for released
void uiSetButton(int button, int enabled); void uiSetButton(int button, int enabled);

// returns the current state of an application dependent input button
// as set by uiSetButton().
// the function returns 1 if the button has been set to pressed, 0 for released.
int uiGetButton(int button); int uiGetButton(int button);


// sets the current cursor position (usually belonging to a mouse) to the
// screen coordinates at (x,y)
void uiSetCursor(int x, int y); void uiSetCursor(int x, int y);

// returns the current cursor position in screen coordinates as set by
// uiSetCursor()
void uiGetCursor(int *x, int *y); void uiGetCursor(int *x, int *y);


// clear the item buffer; uiClear() should be called before each UI declaration
// to avoid concatenation of the same UI multiple times.
// After the call, all previously declared item IDs are invalid, and all
// application dependent context data has been freed.
void uiClear(); void uiClear();


// add a new UI item with size (w,h) and return the new items ID.
// parent is the item ID of the containing item; an item ID of 0 refers to the
// root item.
// handle is an application defined 64-bit handle. If handle is 0, the item
// will not be interactive.
// kind is one of UI_COLUMN, UI_ROW, UI_LABEL, UI_BUTTON and influences the
// items behavior in layouting and input handling.
// If w or h are 0, the dimension is marked as dynamic and will be rescaled
// accordingly by the containing element.
// if data is not NULL, it points to an application defined buffer conforming
// to the declaration of UIdata; The first element must always be a 32-bit
// integer denoting the size of the structure in bytes. The contents of data
// will be copied and can be read back later using uiGetData(). The data
// pointer passed to uiItem() is allowed to become invalid right after the call.
int uiItem(int parent, UIhandle handle, int kind, int uiItem(int parent, UIhandle handle, int kind,
int w, int h, void *data);
int w, int h, const void *data);

// add a new UI item of type UI_COLUMN.
// this is a shorthand of the equivalent call
// int id = uiItem(parent,0,UI_COLUMN,0,0,NULL); uiSetSpacing(id, spacing);
int uiColumn(int parent, int spacing); int uiColumn(int parent, int spacing);

// this is a shorthand of the equivalent call
// int id = uiItem(parent,0,UI_ROW,0,0,NULL); uiSetSpacing(id, spacing);
int uiRow(int parent, int spacing); int uiRow(int parent, int spacing);


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


// 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.
// if item is 0, the child item count of the root item will be returned.
int uiGetChildCount(int item);

// returns the first child item of a container item. If the item is not
// a container or does not contain any items, -1 is returned.
// if item is 0, the first child item of the root item will be returned.
int uiFirstChild(int item); int uiFirstChild(int item);

// returns the last child item of a container item. If the item is not
// a container or does not contain any items, -1 is returned.
// if item is 0, the last child item of the root item will be returned.
int uiLastChild(int item); int uiLastChild(int item);
int uiNextSibling(int item);

// returns an items parent container item.
// if item is 0, -1 will be returned.
int uiParent(int item); int uiParent(int item);


// returns an items child index relative to its parent. If the item is the
// first item, the return value is 0; If the item is the last item, the return
// value is equivalent to uiGetChildCount(uiParent(item))-1.
// if item is 0, 0 will be returned.
int uiGetChildId(int item);

// returns an items next sibling in the list of the parent containers children.
// if item is 0 or the item is the last child item, -1 will be returned.
int uiNextSibling(int item);

// assign a spacing value by which child items of a container items will be
// separated. If item is not a container type, the call has no effect.
void uiSetSpacing(int item, int spacing); void uiSetSpacing(int item, int spacing);

// returns the current spacing value assigned to item by uiSetSpacing()
int uiGetSpacing(int item); int uiGetSpacing(int item);


// returns the kind of the item as passed to uiItem().
// The returned value is one of UI_COLUMN, UI_ROW, UI_LABEL, UI_BUTTON.
int uiGetKind(int item); int uiGetKind(int item);

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

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

// explicitly assign a layout rectangle to an item; If uiSetRect() is called
// after uiLayout(), behavior is undefined.
// 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);
void *uiGetData(int item);
int uiGetChildId(int item);
int uiGetChildCount(int item);

// return the application-dependent context data for an item as passed to
// uiItem(). The memory of the pointer is managed by the UI context.
const void *uiGetData(int item);

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

// return the current state of the item.
// The returned value is one of UI_COLD, UI_HOT, UI_ACTIVE.
int uiGetState(int item); int uiGetState(int item);


// set the handler callback for an interactive item. The meaning of the
// callback is dependent on the item kind.
void uiSetHandler(int item, UIhandler handler);

#endif // _UI_H_ #endif // _UI_H_


#define UI_IMPLEMENTATION
#ifdef UI_IMPLEMENTATION #ifdef UI_IMPLEMENTATION


#include <assert.h> #include <assert.h>
@@ -112,23 +247,40 @@ int uiGetState(int item);
#define UI_MAX_KIND 16 #define UI_MAX_KIND 16


typedef struct UIitem { typedef struct UIitem {
UIhandle handle;
int parent;
// container structure
// number of kids // number of kids
int numkids; int numkids;
// index of first kid
int firstkid;
// index of last kid
int lastkid;
// child structure
// parent item
int parent;
// index of kid relative to parent // index of kid relative to parent
int kidid; int kidid;
// index of next sibling with same parent
int nextitem;
// attributes
// declaration independent unique handle (for persistence)
UIhandle handle;
// layout rectangle
UIrect rect; UIrect rect;
// absolute position
int absx,absy; int absx,absy;
// widget type
int kind; int kind;
// index of data or -1 for none
int data; int data;
// layouting containers: spacing between items
int spacing; int spacing;
// index of first kid
int firstkid;
// index of last kid
int lastkid;
// index of next sibling with same parent
int nextitem;
// handler
UIhandler handler;
} UIitem; } UIitem;


struct UIcontext { struct UIcontext {
@@ -154,10 +306,13 @@ UIcontext *uiCreateContext() {


void uiMakeCurrent(UIcontext *ctx) { void uiMakeCurrent(UIcontext *ctx) {
ui_context = ctx; ui_context = ctx;
uiClear();
if (ui_context)
uiClear();
} }


void uiDestroyContext(UIcontext *ctx) { void uiDestroyContext(UIcontext *ctx) {
if (ui_context == ctx)
uiMakeCurrent(NULL);
free(ctx); free(ctx);
} }


@@ -208,7 +363,7 @@ void uiClear() {
item->data = -1; item->data = -1;
} }


int uiAllocItem(int parent, UIhandle handle, int kind, void *data) {
int uiAllocItem(int parent, UIhandle handle, int kind, const void *data) {
assert(ui_context && (ui_context->count < UI_MAX_ITEMS)); assert(ui_context && (ui_context->count < UI_MAX_ITEMS));
assert(parent >= 0); assert(parent >= 0);
int idx = ui_context->count++; int idx = ui_context->count++;
@@ -240,7 +395,7 @@ int uiAllocItem(int parent, UIhandle handle, int kind, void *data) {
return idx; return idx;
} }


int uiItem(int parent, UIhandle handle, int kind, int w, int h, void *data) {
int uiItem(int parent, UIhandle handle, int kind, int w, int h, const void *data) {
int idx = uiAllocItem(parent, handle, kind, data); int idx = uiAllocItem(parent, handle, kind, data);
UIitem *item = uiItemPtr(idx); UIitem *item = uiItemPtr(idx);
item->rect.w = w; item->rect.w = w;
@@ -308,7 +463,7 @@ int uiGetKind(int item) {
return uiItemPtr(item)->kind; return uiItemPtr(item)->kind;
} }


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;
@@ -318,6 +473,10 @@ int uiGetHandle(int item) {
return uiItemPtr(item)->handle; return uiItemPtr(item)->handle;
} }


void uiSetHandler(int item, UIhandler handler) {
uiItemPtr(item)->handler = handler;
}

int uiGetChildId(int item) { int uiGetChildId(int item) {
return uiItemPtr(item)->kidid; return uiItemPtr(item)->kidid;
} }
@@ -326,19 +485,17 @@ int uiGetChildCount(int item) {
return uiItemPtr(item)->numkids; return uiItemPtr(item)->numkids;
} }


void uiLayoutItem(int item, int x, int y);
void uiLayoutChildren(int item, int x, int y) {
void uiLayoutItem(int item);
void uiLayoutChildren(int item) {
int kid = uiFirstChild(item); int kid = uiFirstChild(item);
while (kid > 0) { while (kid > 0) {
uiLayoutItem(kid, x, y);
uiLayoutItem(kid);
kid = uiNextSibling(kid); kid = uiNextSibling(kid);
} }
} }


void uiLayoutItem(int item, int x, int y) {
void uiLayoutItem(int item) {
UIrect rect = uiGetRect(item); UIrect rect = uiGetRect(item);
rect.x += x;
rect.y += y;
switch(uiGetKind(item)) { switch(uiGetKind(item)) {
case UI_COLUMN: case UI_COLUMN:
@@ -352,7 +509,7 @@ void uiLayoutItem(int item, int x, int y) {
kid = uiNextSibling(kid); kid = uiNextSibling(kid);
} }
uiLayoutChildren(item, rect.x, rect.y);
uiLayoutChildren(item);
int spacing = uiItemPtr(item)->spacing; int spacing = uiItemPtr(item)->spacing;
int h = -spacing; int h = -spacing;
@@ -415,7 +572,7 @@ void uiLayoutItem(int item, int x, int y) {
kid = uiNextSibling(kid); kid = uiNextSibling(kid);
} }
uiLayoutChildren(item, rect.x, rect.y);
uiLayoutChildren(item);


// adjust row height to tallest child // adjust row height to tallest child
kid = uiFirstChild(item); kid = uiFirstChild(item);
@@ -460,7 +617,7 @@ void uiUpdateItemState(int item, int x, int y) {
} }


void uiLayout() { void uiLayout() {
uiLayoutItem(0, 0, 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;


Loading…
Cancel
Save