DVX_GUI/dvx/widgets/widgetTextInput.c

129 lines
3.8 KiB
C

// widgetTextInput.c — TextInput and TextArea widgets
#include "widgetInternal.h"
// ============================================================
// wgtTextArea
// ============================================================
WidgetT *wgtTextArea(WidgetT *parent, int32_t maxLen) {
WidgetT *w = widgetAlloc(parent, WidgetTextAreaE);
if (w) {
int32_t bufSize = maxLen > 0 ? maxLen + 1 : 256;
w->as.textArea.buf = (char *)malloc(bufSize);
w->as.textArea.bufSize = bufSize;
if (w->as.textArea.buf) {
w->as.textArea.buf[0] = '\0';
}
}
return w;
}
// ============================================================
// wgtTextInput
// ============================================================
WidgetT *wgtTextInput(WidgetT *parent, int32_t maxLen) {
WidgetT *w = widgetAlloc(parent, WidgetTextInputE);
if (w) {
int32_t bufSize = maxLen > 0 ? maxLen + 1 : 256;
w->as.textInput.buf = (char *)malloc(bufSize);
w->as.textInput.bufSize = bufSize;
if (w->as.textInput.buf) {
w->as.textInput.buf[0] = '\0';
}
w->weight = 100; // text inputs stretch by default
}
return w;
}
// ============================================================
// widgetTextInputCalcMinSize
// ============================================================
void widgetTextInputCalcMinSize(WidgetT *w, const BitmapFontT *font) {
w->calcMinW = font->charWidth * 8 + TEXT_INPUT_PAD * 2;
w->calcMinH = font->charHeight + TEXT_INPUT_PAD * 2;
}
// ============================================================
// widgetTextInputOnMouse
// ============================================================
void widgetTextInputOnMouse(WidgetT *hit, WidgetT *root, int32_t vx) {
hit->focused = true;
// Place cursor at click position
AppContextT *ctx = (AppContextT *)root->userData;
const BitmapFontT *font = &ctx->font;
int32_t relX = vx - hit->x - TEXT_INPUT_PAD;
int32_t charPos = relX / font->charWidth + hit->as.textInput.scrollOff;
if (charPos < 0) {
charPos = 0;
}
if (charPos > hit->as.textInput.len) {
charPos = hit->as.textInput.len;
}
hit->as.textInput.cursorPos = charPos;
}
// ============================================================
// widgetTextInputPaint
// ============================================================
void widgetTextInputPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors) {
uint32_t fg = w->fgColor ? w->fgColor : colors->contentFg;
uint32_t bg = w->bgColor ? w->bgColor : colors->contentBg;
// Sunken border
BevelStyleT bevel;
bevel.highlight = colors->windowShadow;
bevel.shadow = colors->windowHighlight;
bevel.face = bg;
bevel.width = 2;
drawBevel(d, ops, w->x, w->y, w->w, w->h, &bevel);
// Draw text
if (w->as.textInput.buf) {
int32_t textX = w->x + TEXT_INPUT_PAD;
int32_t textY = w->y + (w->h - font->charHeight) / 2;
int32_t maxChars = (w->w - TEXT_INPUT_PAD * 2) / font->charWidth;
int32_t off = w->as.textInput.scrollOff;
int32_t len = w->as.textInput.len - off;
if (len > maxChars) {
len = maxChars;
}
for (int32_t i = 0; i < len; i++) {
drawChar(d, ops, font, textX + i * font->charWidth, textY,
w->as.textInput.buf[off + i],
fg, bg, true);
}
// Draw cursor
if (w->focused) {
int32_t cursorX = textX + (w->as.textInput.cursorPos - off) * font->charWidth;
if (cursorX >= w->x + TEXT_INPUT_PAD &&
cursorX < w->x + w->w - TEXT_INPUT_PAD) {
drawVLine(d, ops, cursorX, textY, font->charHeight, fg);
}
}
}
}