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 {
int size;
int subtype;
int iconid;
const char *label;
} 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,
data->iconid,data->label);
} 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: {
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;
default: break;
}
@@ -282,26 +293,28 @@ void draw(NVGcontext *vg, float w, float h) {
uiSetRect(0,600,10,250,400);
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);
data.label = "Item 2";
uiItem(col, 2, UI_BUTTON, 0, BND_WIDGET_HEIGHT, &data);
{ // nested row
{
int row = uiRow(col,-1);
data.subtype = ST_RADIO;
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.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.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.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 coll = uiColumn(row,-2);
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.
*/

// item states as returned by uiGetState()

// the item is inactive
#define UI_COLD 0x0000
// the item is inactive, but the cursor is hovering over this item
#define UI_HOT 0x0001
// the item is toggled or activated (depends on item kind)
#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
// 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
// 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

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

// maximum number of items that may be added
#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
// maximum size in bytes of a single data buffer passed to uiItem().
#define UI_MAX_DATASIZE 4096
// maximum depth of nested containers
#define UI_MAX_DEPTH 64

// opaque UI context
typedef struct UIcontext UIcontext;

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

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

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

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

// 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);

// 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);

// 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);

// 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);

// sets the current cursor position (usually belonging to a mouse) to the
// screen coordinates at (x,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);

// 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();

// 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 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);

// 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);

// 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();

// 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);

// 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 uiNextSibling(int item);

// returns an items parent container item.
// if item is 0, -1 will be returned.
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);

// returns the current spacing value assigned to item by uiSetSpacing()
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);

// 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);

// 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);

// 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 *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);

// return the current state of the item.
// The returned value is one of UI_COLD, UI_HOT, UI_ACTIVE.
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_

#define UI_IMPLEMENTATION
#ifdef UI_IMPLEMENTATION

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

typedef struct UIitem {
UIhandle handle;
int parent;
// container structure
// number of kids
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
int kidid;
// index of next sibling with same parent
int nextitem;
// attributes
// declaration independent unique handle (for persistence)
UIhandle handle;
// layout rectangle
UIrect rect;
// absolute position
int absx,absy;
// widget type
int kind;
// index of data or -1 for none
int data;
// layouting containers: spacing between items
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;

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

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

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

@@ -208,7 +363,7 @@ void uiClear() {
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(parent >= 0);
int idx = ui_context->count++;
@@ -240,7 +395,7 @@ int uiAllocItem(int parent, UIhandle handle, int kind, void *data) {
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);
UIitem *item = uiItemPtr(idx);
item->rect.w = w;
@@ -308,7 +463,7 @@ int uiGetKind(int item) {
return uiItemPtr(item)->kind;
}

void *uiGetData(int item) {
const void *uiGetData(int item) {
UIitem *pitem = uiItemPtr(item);
if (pitem->data < 0) return NULL;
return ui_context->data + pitem->data;
@@ -318,6 +473,10 @@ int uiGetHandle(int item) {
return uiItemPtr(item)->handle;
}

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

int uiGetChildId(int item) {
return uiItemPtr(item)->kidid;
}
@@ -326,19 +485,17 @@ int uiGetChildCount(int item) {
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);
while (kid > 0) {
uiLayoutItem(kid, x, y);
uiLayoutItem(kid);
kid = uiNextSibling(kid);
}
}

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

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

void uiLayout() {
uiLayoutItem(0, 0, 0);
uiLayoutItem(0);
uiUpdateItemState(0, 0, 0);
if (!uiGetButton(0)) {
ui_context->active = 0;


Loading…
Cancel
Save