aboutsummaryrefslogtreecommitdiffstats
path: root/src/gwin/gwin_textedit.c
diff options
context:
space:
mode:
authorJoel Bodenmann <joel@seriouslyembedded.com>2015-08-14 18:33:16 +0200
committerJoel Bodenmann <joel@seriouslyembedded.com>2015-08-14 18:33:16 +0200
commitfcaa42972964e002474e6f79364f3af1a616d25c (patch)
tree9a8d054e76ded077e5fc8e6df3937f0deacfa98d /src/gwin/gwin_textedit.c
parent51633811777a0424d9bfe77143384a20f832c565 (diff)
downloaduGFX-fcaa42972964e002474e6f79364f3af1a616d25c.tar.gz
uGFX-fcaa42972964e002474e6f79364f3af1a616d25c.tar.bz2
uGFX-fcaa42972964e002474e6f79364f3af1a616d25c.zip
First working Version of TextEdit widget
Diffstat (limited to 'src/gwin/gwin_textedit.c')
-rw-r--r--src/gwin/gwin_textedit.c141
1 files changed, 122 insertions, 19 deletions
diff --git a/src/gwin/gwin_textedit.c b/src/gwin/gwin_textedit.c
index 6e90b3ac..9c7990eb 100644
--- a/src/gwin/gwin_textedit.c
+++ b/src/gwin/gwin_textedit.c
@@ -15,36 +15,103 @@
#if GFX_USE_GWIN && GWIN_NEED_TEXTEDIT
#include "gwin_class.h"
+#include <string.h>
+#include <stdio.h>
-// Text padding (between edge and text) in pixels
-const int TEXT_PADDING = 3;
+// Some settings
+ const int CURSOR_EXTRA_HEIGHT = 1;
+
+// Macros to assist in data type conversions
+#define gh2obj ((GTexteditObject *)gh)
+#define gw2obj ((GTexteditObject *)gw)
+
+// cursorPos is the position of the next character
+// textBuffer[cursorPos++] = readKey();
+
+// ToDo: Optimize by using strncpy() instead
+static void _shiftTextLeft(char* buffer, size_t bufferSize, size_t index)
+{
+ // Find the end of the string
+ size_t indexTerminator = index;
+ while (buffer[indexTerminator] != '\0' && indexTerminator < bufferSize-1) {
+ indexTerminator++;
+ }
+
+ // Shift
+ size_t i = 0;
+ for (i = index; i < indexTerminator+1; i++) {
+ buffer[i-1] = buffer[i];
+ }
+ buffer[indexTerminator] = '\0';
+}
+
+// ToDo: Optimize by using strncpy() instead
+static void _shiftTextRight(char* buffer, size_t bufferSize, size_t index, char fillChar)
+{
+ // Find the end of the string
+ size_t indexTerminator = index;
+ while (buffer[indexTerminator] != '\0' && indexTerminator < bufferSize-1) {
+ indexTerminator++;
+ }
+
+ // Shift
+ size_t i = 0;
+ for (i = indexTerminator+1; i > index; i--) {
+ if (i > bufferSize-1) {
+ break;
+ }
+
+ buffer[i] = buffer[i-1];
+ }
+
+ // Fill the gap
+ buffer[index] = fillChar;
+}
-// macros to assist in data type conversions
-#define gh2obj ((GTexteditObject *)gh)
-#define gw2obj ((GTexteditObject *)gw)
#if GINPUT_NEED_KEYBOARD
static void _keyboardEvent(GWidgetObject* gw, GEventKeyboard* pke)
{
- // Create a temporary buffer containing the current size
- unsigned bufSize = strlen(gwinGetText((GHandle)gw))+1;
- char buf[bufSize];
- strncpy(buf, gwinGetText((GHandle)gw), bufSize);
+ // Is it a special key?
+ if (pke->keystate & GKEYSTATE_SPECIAL) {
+ // Arrow keys to move the cursor
+ switch ((uint8_t)pke->c[0]) {
+ case GKEY_LEFT:
+ if (gw2obj->cursorPos > 0) {
+ gw2obj->cursorPos--;
+ }
+ break;
+
+ case GKEY_RIGHT:
+ if (gw2obj->cursorPos < strlen(gw2obj->textBuffer)) {
+ gw2obj->cursorPos++;
+ }
+ break;
+
+
+ default:
+ break;
+ }
+ }
// Parse the key press
- if (pke->bytecount == 1) {
+ else if (pke->bytecount >= 1) {
// Check backspace
if (pke->c[0] == GKEY_BACKSPACE) {
- buf[strlen(buf)-1] = '\0';
+ if (gw2obj->cursorPos == 0) {
+ return;
+ }
+ _shiftTextLeft(gw2obj->textBuffer, gw2obj->bufferSize, gw2obj->cursorPos--);
}
- // Append new character
+ // Add a new character
else {
- strncat(buf, &(pke->c[0]), 1);
+ // Shift everything right from the cursor by one character. This includes the '\0'. Then inser the new character.
+ _shiftTextRight(gw2obj->textBuffer, gw2obj->bufferSize, gw2obj->cursorPos++, pke->c[0]);
}
// Set the new text
- gwinSetText((GHandle)gw, buf, TRUE);
+ gwinSetText((GHandle)gw, gw2obj->textBuffer, FALSE);
}
_gwinUpdate((GHandle)gw);
@@ -93,15 +160,30 @@ static const gwidgetVMT texteditVMT = {
#endif
};
-GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* widget, GWidgetInit* pInit)
+GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* widget, GWidgetInit* pInit, size_t bufSize)
{
uint16_t flags = 0;
+ // Create the underlying widget
if (!(widget = (GTexteditObject*)_gwidgetCreate(g, &widget->w, pInit, &texteditVMT))) {
return 0;
}
- widget->w.g.flags |= flags;
+ // Allocate the text buffer
+ widget->bufferSize = bufSize;
+ widget->textBuffer = gfxAlloc(widget->bufferSize);
+ if (widget->textBuffer == 0) {
+ return 0;
+ }
+
+ // Initialize the text buffer
+ size_t i = 0;
+ for (i = 0; i < bufSize; i++) {
+ widget->textBuffer[i] = '\0';
+ }
+
+ widget->cursorPos = 0;
+ widget->w.g.flags |= flags;
gwinSetVisible(&widget->w.g, pInit->g.show);
return (GHandle)widget;
@@ -109,17 +191,38 @@ GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* widget, GWidgetInit* p
static void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param)
{
- color_t textColor;
- (void) param;
+ (void)param;
// Is it a valid handle?
if (gw->g.vmt != (gwinVMT*)&texteditVMT) {
return;
}
- textColor = (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text;
+ // Retrieve colors
+ color_t textColor = (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text;
+ color_t cursorColor = (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge;
+ // Render background and string
gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font, textColor, gw->pstyle->background, justifyLeft);
+
+ // Render cursor (if focused)
+ if (gwinGetFocus() == (GHandle)gw || TRUE) {
+ // Calculate cursor stuff
+ char textBeforeCursor[gw2obj->bufferSize];
+ strncpy(textBeforeCursor, gw->text, gw2obj->cursorPos+1);
+ textBeforeCursor[gw2obj->cursorPos] = '\0';
+ coord_t textWidth = gdispGetStringWidth(textBeforeCursor, gw->g.font);
+ coord_t cursorHeight = gdispGetFontMetric(gw->g.font, fontHeight);
+ coord_t cursorSpacingTop = (gw->g.height - cursorHeight)/2 - CURSOR_EXTRA_HEIGHT;
+ coord_t cursorSpacingBottom = (gw->g.height - cursorHeight)/2 - CURSOR_EXTRA_HEIGHT;
+
+ // Draw cursor
+ coord_t lineX0 = gw->g.x + textWidth - 2;
+ coord_t lineX1 = gw->g.x + textWidth - 2;
+ coord_t lineY0 = gw->g.y + cursorSpacingTop;
+ coord_t lineY1 = gw->g.y + gw->g.height - cursorSpacingBottom;
+ gdispGDrawLine(gw->g.display, lineX0, lineY0, lineX1, lineY1, cursorColor);
+ }
}
#undef gh2obj