Browse Source

added text field support

pull/1/head
Leonard Ritter 10 years ago
parent
commit
26c8227bfa
2 changed files with 180 additions and 13 deletions
  1. +164
    -13
      blendish.h
  2. +16
    -0
      example.cpp

+ 164
- 13
blendish.h View File

@@ -80,6 +80,7 @@ before including blendish.h, otherwise the file will be in header-only mode.
#ifndef BLENDISH_NO_NVG_TYPEDEFS
typedef struct NVGcontext NVGcontext;
typedef struct NVGcolor NVGcolor;
typedef struct NVGglyphPosition NVGglyphPosition;
#endif

// describes the theme used to draw a single widget or widget box;
@@ -114,6 +115,8 @@ typedef struct BNDtheme {
BNDwidgetTheme toolTheme;
// theme for radio buttons
BNDwidgetTheme radioTheme;
// theme for text fields
BNDwidgetTheme textFieldTheme;
// theme for option buttons (checkboxes)
BNDwidgetTheme optionTheme;
// theme for choice buttons (comboboxes)
@@ -125,7 +128,9 @@ typedef struct BNDtheme {
BNDwidgetTheme sliderTheme;
// theme for scrollbars
BNDwidgetTheme scrollBarTheme;
// theme for menu backgrounds and tooltips
// theme for tooltips
BNDwidgetTheme tooltipTheme;
// theme for menu backgrounds
BNDwidgetTheme menuTheme;
// theme for menu items
BNDwidgetTheme menuItemTheme;
@@ -242,6 +247,19 @@ void bndRadioButton(NVGcontext *ctx,
float x, float y, float w, float h, int flags, BNDwidgetState state,
int iconid, const char *label);
// Draw a text field with its lower left origin at (x,y) and size of (w,h),
// where flags is one or multiple flags from BNDcornerFlags and state denotes
// the widgets current UI state.
// if iconid >= 0, an icon will be added to the widget
// if text is not NULL, text will be printed to the widget
// cbegin must be >= 0 and <= strlen(text) and denotes the beginning of the caret
// cend must be >= cbegin and <= strlen(text) and denotes the end of the caret
// if cend < cbegin, then no caret will be drawn
// widget looks best when height is BND_WIDGET_HEIGHT
void bndTextField(NVGcontext *ctx,
float x, float y, float w, float h, int flags, BNDwidgetState state,
int iconid, const char *text, int cbegin, int cend);
// Draw an option button with its lower left origin at (x,y) and size of (w,h),
// where flags is one or multiple flags from BNDcornerFlags and state denotes
// the widgets current UI state.
@@ -314,7 +332,10 @@ void bndMenuLabel(NVGcontext *ctx,
void bndMenuItem(NVGcontext *ctx,
float x, float y, float w, float h, BNDwidgetState state,
int iconid, const char *label);

// Draw a tooltip background with its lower left origin at (x,y) and size of (w,h)
void bndTooltipBackground(NVGcontext *ctx, float x, float y, float w, float h);
////////////////////////////////////////////////////////////////////////////////

// Low Level Functions
@@ -398,10 +419,23 @@ void bndOutlineBox(NVGcontext *ctx, float x, float y, float w, float h,
// and color.
// if value is not NULL, label and value will be drawn with a ":" separator
// inbetween.
void bndIconLabel(NVGcontext *ctx, float x, float y, float w, float h,
void bndIconLabelValue(NVGcontext *ctx, float x, float y, float w, float h,
int iconid, NVGcolor color, int align, float fontsize, const char *label,
const char *value);

// Draw an optional icon specified by <iconid>, an optional label and
// a caret with given fontsize and color within a widget box.
// if iconid is >= 0, an icon will be drawn and the labels remaining space
// will be adjusted.
// if label is not NULL, it will be drawn with the specified alignment, fontsize
// and color.
// cbegin must be >= 0 and <= strlen(text) and denotes the beginning of the caret
// cend must be >= cbegin and <= strlen(text) and denotes the end of the caret
// if cend < cbegin, then no caret will be drawn
void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h,
int iconid, NVGcolor color, float fontsize, const char *label,
NVGcolor caretcolor, int cbegin, int cend);
// Draw a checkmark for an option box with the given upper left coordinates
// (ox,oy) with the specified color.
void bndCheck(NVGcontext *ctx, float ox, float oy, NVGcolor color);
@@ -490,6 +524,9 @@ void bndUpDownArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color);
// height of option button checkbox
#define BND_OPTION_HEIGHT 15

// radius of text field
#define BND_TEXT_RADIUS 4

// radius of number button
#define BND_NUMBER_RADIUS 10

@@ -505,6 +542,9 @@ void bndUpDownArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color);
// shade intensity of active scrollbar
#define BND_SCROLLBAR_ACTIVE_SHADE 15

// max glyphs for position testing
#define BND_MAX_GLYPHS 1024

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

BND_INLINE float bnd_clamp(float v, float mn, float mx) {
@@ -550,6 +590,17 @@ static BNDtheme bnd_theme = {
15, // shade_top
-15, // shade_down
},
// textFieldTheme
{
{{{ 0.098,0.098,0.098,1 }}}, // color_outline
{{{ 0.353, 0.353, 0.353,1 }}}, // color_item
{{{ 0.6, 0.6, 0.6,1 }}}, // color_inner
{{{ 0.6, 0.6, 0.6,1 }}}, // color_inner_selected
BND_COLOR_TEXT, // color_text
BND_COLOR_TEXT_SELECTED, // color_text_selected
0, // shade_top
25, // shade_down
},
// optionTheme
{
{{{ 0,0,0,1 }}}, // color_outline
@@ -605,6 +656,17 @@ static BNDtheme bnd_theme = {
5, // shade_top
-5, // shade_down
},
// tooltipTheme
{
{{{ 0,0,0,1 }}}, // color_outline
{{{ 0.392,0.392,0.392,1 }}}, // color_item
{{{ 0.098, 0.098, 0.098, 0.902 }}}, // color_inner
{{{ 0.176, 0.176, 0.176, 0.902 }}}, // color_inner_selected
{{{ 0.627, 0.627, 0.627, 1 }}}, // color_text
BND_COLOR_TEXT_SELECTED, // color_text_selected
0, // shade_top
0, // shade_down
},
// menuTheme
{
{{{ 0,0,0,1 }}}, // color_outline
@@ -657,7 +719,7 @@ void bndSetFont(int font) {

void bndLabel(NVGcontext *ctx,
float x, float y, float w, float h, int iconid, const char *label) {
bndIconLabel(ctx,x,y,w,h,iconid,
bndIconLabelValue(ctx,x,y,w,h,iconid,
bnd_theme.regularTheme.textColor, BND_LEFT,
BND_LABEL_FONT_SIZE, label, NULL);
}
@@ -674,7 +736,7 @@ void bndToolButton(NVGcontext *ctx,
bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
bndTransparent(bnd_theme.toolTheme.outlineColor));
bndIconLabel(ctx,x,y,w,h,iconid,
bndIconLabelValue(ctx,x,y,w,h,iconid,
bndTextColor(&bnd_theme.toolTheme, state), BND_CENTER,
BND_LABEL_FONT_SIZE, label, NULL);
}
@@ -691,11 +753,31 @@ void bndRadioButton(NVGcontext *ctx,
bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
bndTransparent(bnd_theme.radioTheme.outlineColor));
bndIconLabel(ctx,x,y,w,h,iconid,
bndIconLabelValue(ctx,x,y,w,h,iconid,
bndTextColor(&bnd_theme.radioTheme, state), BND_CENTER,
BND_LABEL_FONT_SIZE, label, NULL);
}

void bndTextField(NVGcontext *ctx,
float x, float y, float w, float h, int flags, BNDwidgetState state,
int iconid, const char *text, int cbegin, int cend) {
float cr[4];
NVGcolor shade_top, shade_down;
bndSelectCorners(cr, BND_TEXT_RADIUS, flags);
bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]);
bndInnerColors(&shade_top, &shade_down, &bnd_theme.textFieldTheme, state, 0);
bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
bndTransparent(bnd_theme.textFieldTheme.outlineColor));
if (state != BND_ACTIVE) {
cend = -1;
}
bndIconLabelCaret(ctx,x,y,w,h,iconid,
bndTextColor(&bnd_theme.textFieldTheme, state), BND_LABEL_FONT_SIZE,
text, bnd_theme.textFieldTheme.itemColor, cbegin, cend);
}

void bndOptionButton(NVGcontext *ctx,
float x, float y, float w, float h, BNDwidgetState state,
const char *label) {
@@ -720,7 +802,7 @@ void bndOptionButton(NVGcontext *ctx,
if (state == BND_ACTIVE) {
bndCheck(ctx,ox,oy, bndTransparent(bnd_theme.optionTheme.itemColor));
}
bndIconLabel(ctx,x+12,y,w-12,h,-1,
bndIconLabelValue(ctx,x+12,y,w-12,h,-1,
bndTextColor(&bnd_theme.optionTheme, state), BND_LEFT,
BND_LABEL_FONT_SIZE, label, NULL);
}
@@ -737,7 +819,7 @@ void bndChoiceButton(NVGcontext *ctx,
bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
bndTransparent(bnd_theme.choiceTheme.outlineColor));
bndIconLabel(ctx,x,y,w,h,iconid,
bndIconLabelValue(ctx,x,y,w,h,iconid,
bndTextColor(&bnd_theme.choiceTheme, state), BND_LEFT,
BND_LABEL_FONT_SIZE, label, NULL);
bndUpDownArrow(ctx,x+w-10,y+10,5,
@@ -756,7 +838,7 @@ void bndNumberField(NVGcontext *ctx,
bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down);
bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
bndTransparent(bnd_theme.numberFieldTheme.outlineColor));
bndIconLabel(ctx,x,y,w,h,-1,
bndIconLabelValue(ctx,x,y,w,h,-1,
bndTextColor(&bnd_theme.numberFieldTheme, state), BND_CENTER,
BND_LABEL_FONT_SIZE, label, value);
bndArrow(ctx,x+8,y+10,-BND_NUMBER_ARROW_SIZE,
@@ -793,7 +875,7 @@ void bndSlider(NVGcontext *ctx,
bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3],
bndTransparent(bnd_theme.sliderTheme.outlineColor));
bndIconLabel(ctx,x,y,w,h,-1,
bndIconLabelValue(ctx,x,y,w,h,-1,
bndTextColor(&bnd_theme.sliderTheme, state), BND_CENTER,
BND_LABEL_FONT_SIZE, label, value);
}
@@ -850,9 +932,24 @@ void bndMenuBackground(NVGcontext *ctx,
BND_SHADOW_FEATHER,BND_SHADOW_ALPHA);
}

void bndTooltipBackground(NVGcontext *ctx, float x, float y, float w, float h) {
NVGcolor shade_top, shade_down;
bndInnerColors(&shade_top, &shade_down, &bnd_theme.tooltipTheme,
BND_DEFAULT, 0);
bndInnerBox(ctx,x,y,w,h+1,
BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,
shade_top, shade_down);
bndOutlineBox(ctx,x,y,w,h+1,
BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,
bndTransparent(bnd_theme.tooltipTheme.outlineColor));
bndDropShadow(ctx,x,y,w,h,BND_MENU_RADIUS,
BND_SHADOW_FEATHER,BND_SHADOW_ALPHA);
}

void bndMenuLabel(NVGcontext *ctx,
float x, float y, float w, float h, int iconid, const char *label) {
bndIconLabel(ctx,x,y,w,h,iconid,
bndIconLabelValue(ctx,x,y,w,h,iconid,
bnd_theme.menuTheme.textColor, BND_LEFT,
BND_LABEL_FONT_SIZE, label, NULL);
}
@@ -868,7 +965,7 @@ void bndMenuItem(NVGcontext *ctx,
bnd_theme.menuItemTheme.shadeDown));
state = BND_ACTIVE;
}
bndIconLabel(ctx,x,y,w,h,iconid,
bndIconLabelValue(ctx,x,y,w,h,iconid,
bndTextColor(&bnd_theme.menuItemTheme, state), BND_LEFT,
BND_LABEL_FONT_SIZE, label, NULL);
}
@@ -1044,7 +1141,7 @@ NVGcolor bndTextColor(const BNDwidgetTheme *theme, BNDwidgetState state) {
return (state == BND_ACTIVE)?theme->textSelectedColor:theme->textColor;
}

void bndIconLabel(NVGcontext *ctx, float x, float y, float w, float h,
void bndIconLabelValue(NVGcontext *ctx, float x, float y, float w, float h,
int iconid, NVGcolor color, int align, float fontsize, const char *label,
const char *value) {
float pleft = BND_PAD_LEFT;
@@ -1088,6 +1185,60 @@ void bndIconLabel(NVGcontext *ctx, float x, float y, float w, float h,
}
}

void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h,
int iconid, NVGcolor color, float fontsize, const char *label,
NVGcolor caretcolor, int cbegin, int cend) {
float bounds[4];
float pleft = BND_TEXT_RADIUS;
if (!label) return;
if (iconid >= 0) {
bndIcon(ctx,x+4,y+2,iconid);
pleft += BND_ICON_SHEET_RES;
}
if (bnd_font < 0) return;
x+=pleft;
y+=h-6;

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

if (cend >= cbegin) {
float c0,c1;
const char *cb;const char *ce;
static NVGglyphPosition glyphs[BND_MAX_GLYPHS];
int nglyphs = nvgTextGlyphPositions(
ctx, x, y, label, label+cend+1, glyphs, BND_MAX_GLYPHS);
c0=glyphs[0].x;
c1=glyphs[nglyphs-1].x;
cb = label+cbegin; ce = label+cend;
// 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);
}
nvgBeginPath(ctx);
nvgFillColor(ctx, color);
nvgTextBox(ctx,x,y,w-BND_TEXT_RADIUS-pleft,label, NULL);
}

void bndCheck(NVGcontext *ctx, float ox, float oy, NVGcolor color) {
nvgBeginPath(ctx);
nvgStrokeWidth(ctx,2);


+ 16
- 0
example.cpp View File

@@ -147,6 +147,22 @@ void draw(NVGcontext *vg, float w, float h) {
ry += 20;
bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_ACTIVE,s_offset,s_size);
const char edit_text[] = "The quick brown fox";
int textlen = strlen(edit_text)+1;
int t = int(glfwGetTime()*2);
int idx1 = (t/textlen)%textlen;
int idx2 = idx1 + (t%(textlen-idx1));
ry += 25;
bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT,
-1, edit_text, idx1, idx2);
ry += 25;
bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER,
-1, edit_text, idx1, idx2);
ry += 25;
bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE,
-1, edit_text, idx1, idx2);
rx += rw + 20;
ry = 10;
bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_DEFAULT,s_offset,s_size);


Loading…
Cancel
Save