129 lines
3.8 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
}
|