Browse Source

- merged layout flags, event flags, frozen flag, visited flags into single item flagset

pull/1/head
Leonard Ritter 10 years ago
parent
commit
4243d5e845
3 changed files with 182 additions and 73 deletions
  1. +66
    -3
      blendish.h
  2. +21
    -14
      example.cpp
  3. +95
    -56
      oui.h

+ 66
- 3
blendish.h View File

@@ -934,7 +934,12 @@ BND_EXPORT void bndJoinAreaOverlay(NVGcontext *ctx, float x, float y, float w, f

// returns the ideal width for a label with given icon and text
BND_EXPORT float bndLabelWidth(NVGcontext *ctx, int iconid, const char *label);

// returns the height for a label with given icon, text and width; this
// function is primarily useful in conjunction with multiline labels and textboxes
BND_EXPORT float bndLabelHeight(NVGcontext *ctx, int iconid, const char *label,
float width);

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

// Low Level Functions
@@ -1866,6 +1871,24 @@ float bndLabelWidth(NVGcontext *ctx, int iconid, const char *label) {
return w;
}

float bndLabelHeight(NVGcontext *ctx, int iconid, const char *label, float width) {
int h = BND_WIDGET_HEIGHT;
width -= BND_TEXT_RADIUS*2;
if (iconid >= 0) {
width -= BND_ICON_SHEET_RES;
}
if (label && (bnd_font >= 0)) {
nvgFontFaceId(ctx, bnd_font);
nvgFontSize(ctx, BND_LABEL_FONT_SIZE);
float bounds[4];
nvgTextBoxBounds(ctx, 1, 1, width, label, NULL, bounds);
int bh = int(bounds[3] - bounds[1]) + BND_TEXT_PAD_DOWN;
if (bh > h)
h = bh;
}
return h;
}

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

void bndRoundedBox(NVGcontext *ctx, float x, float y, float w, float h,
@@ -2143,13 +2166,16 @@ void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h,
if (bnd_font < 0) return;
x+=pleft;
y+=h-BND_TEXT_PAD_DOWN;
y+=BND_WIDGET_HEIGHT-BND_TEXT_PAD_DOWN;

nvgFontFaceId(ctx, bnd_font);
nvgFontSize(ctx, fontsize);
nvgTextAlign(ctx, NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE);

w -= BND_TEXT_RADIUS+pleft;

if (cend >= cbegin) {
#if 1
float c0,c1;
const char *cb;const char *ce;
static NVGglyphPosition glyphs[BND_MAX_GLYPHS];
@@ -2176,11 +2202,48 @@ void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h,
nvgRect(ctx, c0-1, bounds[1], c1-c0+1, bounds[3]-bounds[1]);
}
nvgFill(ctx);
#else
float c0,c1;
const char *cb;
const char *ce;
const char *line;
int numlines;
cb = label+cbegin; ce = label+cend;
line = label;

NVGtextRow rows[2];
numlines = nvgTextBreakLines(ctx, line, NULL, w, rows, 2);

/*
int nglyphs = nvgTextGlyphPositions(
ctx, x, y, label, label+cend+1, glyphs, BND_MAX_GLYPHS);
c0=glyphs[0].x;
c1=glyphs[nglyphs-1].x;
// TODO: this is slow
for (int i=0; i < nglyphs; ++i) {
if (glyphs[i].str == cb)
c0 = glyphs[i].x;
if (glyphs[i].str == ce)
c1 = glyphs[i].x;
}

nvgTextBounds(ctx,x,y,label,NULL, bounds);
nvgBeginPath(ctx);
if (cbegin == cend) {
nvgFillColor(ctx, nvgRGBf(0.337,0.502,0.761));
nvgRect(ctx, c0-1, bounds[1], 2, bounds[3]-bounds[1]);
} else {
nvgFillColor(ctx, caretcolor);
nvgRect(ctx, c0-1, bounds[1], c1-c0+1, bounds[3]-bounds[1]);
}
nvgFill(ctx);
*/
#endif
}
nvgBeginPath(ctx);
nvgFillColor(ctx, color);
nvgTextBox(ctx,x,y,w-BND_TEXT_RADIUS-pleft,label, NULL);
nvgTextBox(ctx,x,y,w,label, NULL);
}

void bndCheck(NVGcontext *ctx, float ox, float oy, NVGcolor color) {


+ 21
- 14
example.cpp View File

@@ -79,6 +79,8 @@ typedef struct {

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

static struct NVGcontext* _vg = NULL;

void init(NVGcontext *vg) {
bndSetFont(nvgCreateFont(vg, "system", "../DejaVuSans.ttf"));
bndSetIconImage(nvgCreateImage(vg, "../blender_icons16.png", 0));
@@ -334,6 +336,11 @@ void textboxhandler(int item, UIevent event) {
if (size >= (data->maxsize-1)) return;
data->text[size] = (char)key;
} break;
case UI_ADJUST_HEIGHT: {
UIrect rc = uiGetRect(item);
rc.h = bndLabelHeight(_vg, -1, data->text, (float)rc.w);
uiSetSize(item, uiGetWidth(item), rc.h);
} break;
}
}

@@ -342,7 +349,7 @@ int textbox(UIhandle handle, char *text, int maxsize) {
uiSetHandle(item, handle);
uiSetSize(item, 0, BND_WIDGET_HEIGHT);
uiSetHandler(item, textboxhandler,
UI_BUTTON0_DOWN | UI_KEY_DOWN | UI_CHAR);
UI_BUTTON0_DOWN | UI_KEY_DOWN | UI_CHAR | UI_ADJUST_HEIGHT);
// store some custom data with the button that we use for styling
// and logic, e.g. the pointer to the data we want to alter.
UITextData *data = (UITextData *)uiAllocData(item, sizeof(UITextData));
@@ -729,15 +736,14 @@ void draw(NVGcontext *vg, float w, float h) {
}
column_append(col, button(11, BND_ICONID(6,3), "Item 5", NULL));

static char textbuffer[1024] = "This textbox adjusts its height to its content when the text is overflowing the widgets width.";
column_append(col, textbox((UIhandle)textbuffer, textbuffer, 1024));

column_append(col, check(12, "Frozen", &option1));
column_append(col, check(13, "Item 7", &option2));
column_append(col, check(14, "Item 8", &option3));
static char textbuffer[32] = "click and edit";
column_append(col, textbox((UIhandle)textbuffer, textbuffer, 32));
uiLayout();
drawUI(vg, 0, 0, 0);
@@ -797,7 +803,6 @@ static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
int main()
{
GLFWwindow* window;
struct NVGcontext* vg = NULL;
UIcontext *uictx;
uictx = uiCreateContext();
@@ -840,13 +845,15 @@ int main()
glGetError();
#endif

vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
if (vg == NULL) {
_vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
if (_vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
init(vg);
init(_vg);

printf("%lu %lu\n", sizeof(UIitem), sizeof(UIitem2));

glfwSwapInterval(0);

@@ -870,11 +877,11 @@ int main()
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
nvgBeginFrame(_vg, winWidth, winHeight, pxRatio);

draw(vg, winWidth, winHeight);
draw(_vg, winWidth, winHeight);

nvgEndFrame(vg);
nvgEndFrame(_vg);

glfwSwapBuffers(window);
glfwPollEvents();
@@ -882,7 +889,7 @@ int main()

uiDestroyContext(uictx);

nvgDeleteGL3(vg);
nvgDeleteGL3(_vg);

glfwTerminate();
return 0;


+ 95
- 56
oui.h View File

@@ -234,67 +234,67 @@ typedef enum UIitemState {
// layout flags
typedef enum UIlayoutFlags {
// anchor to left item or left side of parent
UI_LEFT = 0x01,
UI_LEFT = 0x1,
// anchor to top item or top side of parent
UI_TOP = 0x02,
UI_TOP = 0x2,
// anchor to right item or right side of parent
UI_RIGHT = 0x04,
UI_RIGHT = 0x4,
// anchor to bottom item or bottom side of parent
UI_DOWN = 0x08,
UI_DOWN = 0x8,
// anchor to both left and right item or parent borders
UI_HFILL = 0x05,
UI_HFILL = 0x5,
// anchor to both top and bottom item or parent borders
UI_VFILL = 0x0A,
UI_VFILL = 0xA,
// center horizontally, with left margin as offset
UI_HCENTER = 0x00,
UI_HCENTER = 0x0,
// center vertically, with top margin as offset
UI_VCENTER = 0x00,
UI_VCENTER = 0x0,
// center in both directions, with left/top margin as offset
UI_CENTER = 0x00,
UI_CENTER = 0x0,
// anchor to all four directions
UI_FILL = 0x0F,
UI_FILL = 0xF,
} UIlayoutFlags;

// event flags
typedef enum UIevent {
// on button 0 down
UI_BUTTON0_DOWN = 0x0001,
UI_BUTTON0_DOWN = 0x0010,
// on button 0 up
// when this event has a handler, uiGetState() will return UI_ACTIVE as
// long as button 0 is down.
UI_BUTTON0_UP = 0x0002,
UI_BUTTON0_UP = 0x0020,
// on button 0 up while item is hovered
// when this event has a handler, uiGetState() will return UI_ACTIVE
// when the cursor is hovering the items rectangle; this is the
// behavior expected for buttons.
UI_BUTTON0_HOT_UP = 0x0004,
UI_BUTTON0_HOT_UP = 0x0040,
// item is being captured (button 0 constantly pressed);
// when this event has a handler, uiGetState() will return UI_ACTIVE as
// long as button 0 is down.
UI_BUTTON0_CAPTURE = 0x0008,
UI_BUTTON0_CAPTURE = 0x0080,
// on button 2 down (right mouse button, usually triggers context menu)
UI_BUTTON2_DOWN = 0x0010,
UI_BUTTON2_DOWN = 0x0100,
// item has received a scrollwheel event
// the accumulated wheel offset can be queried with uiGetScroll()
UI_SCROLL = 0x0020,
UI_SCROLL = 0x0200,
// item is focused and has received a key-down event
// the respective key can be queried using uiGetKey() and uiGetModifier()
UI_KEY_DOWN = 0x0040,
UI_KEY_DOWN = 0x0400,
// item is focused and has received a key-up event
// the respective key can be queried using uiGetKey() and uiGetModifier()
UI_KEY_UP = 0x0080,
UI_KEY_UP = 0x0800,
// item is focused and has received a character event
// the respective character can be queried using uiGetKey()
UI_CHAR = 0x0100,
UI_CHAR = 0x1000,
// if this flag is set, all events will propagate to the parent;
// the original item firing this event can be retrieved using
// uiGetEventItem()
UI_PROPAGATE = 0x0200,
// after computing the horizontal size of the element, the vertical
UI_PROPAGATE = 0x2000,
// used if, after computing the horizontal size of the element, the vertical
// size needs adjustment.
// the handler is called after the horizontal layout step, and can make
// modifications to the items height using uiSetSize()
UI_ADJUST_HEIGHT = 0x0400,
UI_ADJUST_HEIGHT = 0x4000,
} UIevent;

// handler callback; event is one of UI_EVENT_*
@@ -660,6 +660,21 @@ OUI_EXPORT int uiGetAbove(int item);
#define UI_ANY_INPUT (UI_ANY_MOUSE_INPUT \
|UI_ANY_KEY_INPUT)

#define UI_ITEM_VISITED_XY_FLAG(X) (1<<(UI_ITEM_VISITED_BITOFS+(X)))
#define UI_ITEM_VISITED_WH_FLAG(X) (4<<(UI_ITEM_VISITED_BITOFS+(X)))

// extra item flags
enum {
UI_ITEM_LAYOUT_MASK = 0x000F,
UI_ITEM_EVENT_MASK = 0xFFF0,
UI_ITEM_FROZEN = 0x10000,
UI_ITEM_VISITED_BITOFS = 17, // 0x20000, 0x40000, 0x80000, 0x100000
UI_ITEM_VISITED_MASK = (UI_ITEM_VISITED_XY_FLAG(0)
| UI_ITEM_VISITED_XY_FLAG(1)
| UI_ITEM_VISITED_WH_FLAG(0)
| UI_ITEM_VISITED_WH_FLAG(1)),
};

typedef struct UIitem {
// declaration independent unique handle (for persistence)
UIhandle handle;
@@ -667,6 +682,7 @@ typedef struct UIitem {
UIhandler handler;
// container structure
unsigned int flags;
// number of kids
int numkids;
@@ -686,12 +702,8 @@ typedef struct UIitem {
// index of previous sibling with same parent
int previtem;
// one or multiple of UIlayoutFlags
int layout_flags;
// size
UIvec2 size;
// visited flags for layouting
int visited;
// margin offsets, interpretation depends on flags
int margins[4];
// neighbors to position borders to
@@ -704,15 +716,36 @@ typedef struct UIitem {
// attributes
int frozen;
// index of data or -1 for none
int data;
// size of data
int datasize;
// a combination of UIevents
int event_flags;
} UIitem;

// 40 bytes
typedef struct UIitem2 {
// declaration independent unique handle (for persistence)
UIhandle handle;
// handler
UIhandler handler;

// flags: unifies: 4 layout bits, 11 event bits, 1 frozen bit, 2 visited bits
// 2 new layout bits: rect w/h is fixed
int flags;

// container structure

// index of first kid
int firstkid;
// index of next sibling with same parent
int nextitem;

// margin offsets, orientation/interpretation depends on layout flags
short margins[2];
// relative / absolute offset
short offset[2];
// measured / fixed size
short size[2];
} UIitem2;

typedef enum UIstate {
UI_STATE_IDLE = 0,
UI_STATE_CAPTURE,
@@ -1039,9 +1072,10 @@ int uiItem() {

void uiNotifyAllItems(UIevent event) {
assert(ui_context);
assert((event & UI_ITEM_EVENT_MASK) == event);
for (int i = 0; i < ui_context->count; ++i) {
UIitem *pitem = ui_context->items + i;
if (pitem->handler && (pitem->event_flags & event)) {
if (pitem->handler && (pitem->flags & event)) {
pitem->handler(i, event);
}
}
@@ -1049,13 +1083,14 @@ void uiNotifyAllItems(UIevent event) {

void uiNotifyItem(int item, UIevent event) {
assert(ui_context);
assert((event & UI_ITEM_EVENT_MASK) == event);
ui_context->event_item = item;
while (item >= 0) {
UIitem *pitem = uiItemPtr(item);
if (pitem->handler && (pitem->event_flags & event)) {
if (pitem->handler && (pitem->flags & event)) {
pitem->handler(item, event);
}
if (!(pitem->event_flags & UI_PROPAGATE))
if (!(pitem->flags & UI_PROPAGATE))
break;
item = uiParent(item);
}
@@ -1081,7 +1116,10 @@ int uiAppend(int item, int child) {

void uiSetFrozen(int item, int enable) {
UIitem *pitem = uiItemPtr(item);
pitem->frozen = enable;
if (enable)
pitem->flags |= UI_ITEM_FROZEN;
else
pitem->flags &= ~UI_ITEM_FROZEN;
}

void uiSetSize(int item, int w, int h) {
@@ -1099,11 +1137,11 @@ int uiGetHeight(int item) {
}

void uiSetLayout(int item, int flags) {
uiItemPtr(item)->layout_flags = flags;
uiItemPtr(item)->flags |= flags & UI_ITEM_LAYOUT_MASK;
}

int uiGetLayout(int item) {
return uiItemPtr(item)->layout_flags;
return uiItemPtr(item)->flags & UI_ITEM_LAYOUT_MASK;
}

void uiSetMargins(int item, int l, int t, int r, int b) {
@@ -1171,12 +1209,12 @@ UI_INLINE void uiComputeChainSize(UIitem *pkid,
*hard_size = pitem->size.v[dim]?size:0;
int it = 0;
pitem->visited |= 1<<dim;
pitem->flags |= UI_ITEM_VISITED_XY_FLAG(dim);
// traverse along left neighbors
while ((pitem->layout_flags>>dim) & UI_LEFT) {
while (((pitem->flags&UI_ITEM_LAYOUT_MASK)>>dim) & UI_LEFT) {
if (pitem->relto[dim] < 0) break;
pitem = uiItemPtr(pitem->relto[dim]);
pitem->visited |= 1<<dim;
pitem->flags |= UI_ITEM_VISITED_XY_FLAG(dim);
size = pitem->rect.v[wdim] + pitem->margins[dim] + pitem->margins[wdim];
*need_size = (*need_size) + size;
*hard_size = (*hard_size) + (pitem->size.v[dim]?size:0);
@@ -1186,10 +1224,10 @@ UI_INLINE void uiComputeChainSize(UIitem *pkid,
// traverse along right neighbors
pitem = pkid;
it = 0;
while ((pitem->layout_flags>>dim) & UI_RIGHT) {
while (((pitem->flags&UI_ITEM_LAYOUT_MASK)>>dim) & UI_RIGHT) {
if (pitem->relto[wdim] < 0) break;
pitem = uiItemPtr(pitem->relto[wdim]);
pitem->visited |= 1<<dim;
pitem->flags |= UI_ITEM_VISITED_XY_FLAG(dim);
size = pitem->rect.v[wdim] + pitem->margins[dim] + pitem->margins[wdim];
*need_size = (*need_size) + size;
*hard_size = (*hard_size) + (pitem->size.v[dim]?size:0);
@@ -1205,7 +1243,7 @@ UI_INLINE void uiComputeSizeDim(UIitem *pitem, int dim) {
int kid = pitem->firstkid;
while (kid >= 0) {
UIitem *pkid = uiItemPtr(kid);
if (!(pkid->visited & (1<<dim))) {
if (!(pkid->flags & UI_ITEM_VISITED_XY_FLAG(dim))) {
int ns,hs;
uiComputeChainSize(pkid, &ns, &hs, dim);
need_size = ui_max(need_size, ns);
@@ -1224,7 +1262,7 @@ UI_INLINE void uiComputeSizeDim(UIitem *pitem, int dim) {

static void uiComputeBestSize(int item, int dim) {
UIitem *pitem = uiItemPtr(item);
pitem->visited = 0;
pitem->flags &= ~UI_ITEM_VISITED_MASK;
// children expand the size
int kid = uiFirstChild(item);
while (kid >= 0) {
@@ -1237,15 +1275,15 @@ static void uiComputeBestSize(int item, int dim) {

static void uiLayoutChildItem(UIitem *pparent, UIitem *pitem,
int *dyncount, int *consumed_space, int dim) {
if (pitem->visited & (4<<dim)) return;
pitem->visited |= (4<<dim);
if (pitem->flags & UI_ITEM_VISITED_WH_FLAG(dim)) return;
pitem->flags |= UI_ITEM_VISITED_WH_FLAG(dim);
int wdim = dim+2;
int x = 0;
int s = pparent->rect.v[wdim];
int flags = pitem->layout_flags>>dim;
int flags = (pitem->flags & UI_ITEM_LAYOUT_MASK) >> dim;
int hasl = (flags & UI_LEFT) && (pitem->relto[dim] >= 0);
int hasr = (flags & UI_RIGHT) && (pitem->relto[wdim] >= 0);
@@ -1310,7 +1348,7 @@ static void uiLayoutChildItem(UIitem *pparent, UIitem *pitem,
}

UI_INLINE void uiLayoutItemDim(UIitem *pitem, int dim) {
int wdim = dim+2;
//int wdim = dim+2;
int kid = pitem->firstkid;
int consumed_space = 0;
int dyncount = 0;
@@ -1398,7 +1436,8 @@ UIhandle uiGetHandle(int item) {
void uiSetHandler(int item, UIhandler handler, int flags) {
UIitem *pitem = uiItemPtr(item);
pitem->handler = handler;
pitem->event_flags = flags;
pitem->flags &= ~UI_ITEM_EVENT_MASK;
pitem->flags |= flags;
}

UIhandler uiGetHandler(int item) {
@@ -1406,7 +1445,7 @@ UIhandler uiGetHandler(int item) {
}

int uiGetHandlerFlags(int item) {
return uiItemPtr(item)->event_flags;
return uiItemPtr(item)->flags & UI_ITEM_EVENT_MASK;
}

int uiGetChildId(int item) {
@@ -1443,7 +1482,7 @@ int uiFindItemForEvent(int item, UIevent event,
UIrect *hot_rect,
int x, int y, int ox, int oy) {
UIitem *pitem = uiItemPtr(item);
if (pitem->frozen) return -1;
if (pitem->flags & UI_ITEM_FROZEN) return -1;
UIrect rect = pitem->rect;
x -= rect.x;
y -= rect.y;
@@ -1461,7 +1500,7 @@ int uiFindItemForEvent(int item, UIevent event,
kid = uiPrevSibling(kid);
}
// click-through if the item has no handler for this event
if (pitem->event_flags & event) {
if (pitem->flags & event) {
rect.x = ox;
rect.y = oy;
if (hot_rect)
@@ -1634,13 +1673,13 @@ static int uiIsFocused(int item) {

UIitemState uiGetState(int item) {
UIitem *pitem = uiItemPtr(item);
if (pitem->frozen) return UI_FROZEN;
if (pitem->flags & UI_ITEM_FROZEN) return UI_FROZEN;
if (uiIsFocused(item)) {
if (pitem->event_flags & (UI_KEY_DOWN|UI_CHAR|UI_KEY_UP)) return UI_ACTIVE;
if (pitem->flags & (UI_KEY_DOWN|UI_CHAR|UI_KEY_UP)) return UI_ACTIVE;
}
if (uiIsActive(item)) {
if (pitem->event_flags & (UI_BUTTON0_CAPTURE|UI_BUTTON0_UP)) return UI_ACTIVE;
if ((pitem->event_flags & UI_BUTTON0_HOT_UP)
if (pitem->flags & (UI_BUTTON0_CAPTURE|UI_BUTTON0_UP)) return UI_ACTIVE;
if ((pitem->flags & UI_BUTTON0_HOT_UP)
&& uiIsHot(item)) return UI_ACTIVE;
return UI_COLD;
} else if (uiIsHot(item)) {


Loading…
Cancel
Save