diff --git a/docs/releases.txt b/docs/releases.txt index 9f7c16be..07c97bb2 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -10,6 +10,9 @@ FEATURE: New board STM32F746G-Discovery FEATURE: New gdisp driver STM32LTDC FEATURE: Better support for Raw32 platforms FEATURE: Implementing widget focusing. See gwinSetFocus() and gwinGetFocus() +FEATURE: Adding more font metrics (BaselineX and BaselineY) +FEATURE: Adding gdispGetStringWidthCount() +FEATURE: Adding TextEdit widget *** Release 2.3 *** diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 43b470b2..6e431441 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -3324,12 +3324,26 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co return mf_character_width(font, c); } - coord_t gdispGetStringWidth(const char* str, font_t font) { - if (!str) + coord_t gdispGetStringWidthCount(const char* str, font_t font, uint16_t count) { + if (!str) { return 0; + } - /* No mutex required as we only read static data */ - return mf_get_string_width(font, str, 0, 0); + // No mutex required as we only read static data + #if GDISP_NEED_TEXT_KERNING + return mf_get_string_width(font, str, count, TRUE); + #else + return mf_get_string_width(font, str, count, FALSE); + #endif + } + + coord_t gdispGetStringWidth(const char* str, font_t font) { + if (!str) { + return 0; + } + + // No mutex required as we only read static data + return gdispGetStringWidthCount(str, font, 0); } #endif diff --git a/src/gdisp/gdisp.h b/src/gdisp/gdisp.h index 298258cb..b096cb3d 100644 --- a/src/gdisp/gdisp.h +++ b/src/gdisp/gdisp.h @@ -978,7 +978,22 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co coord_t gdispGetCharWidth(char c, font_t font); /** - * @brief Get the pixel width of a string. + * @brief Get the pixel width of a string of a given length. + * @return The width of the string in pixels. + * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h + * + * @note Passing 0 to count has the same effect as calling gdispGetStringWidt() + * + * @param[in] str The string to measure + * @param[in] font The font to use + * @param[in] count The number of characters to take into account + * + * @api + */ + coord_t gdispGetStringWidthCount(const char* str, font_t font, uint16_t count); + + /** + * @brief Get the pixel width of an entire string. * @return The width of the string in pixels. * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h * diff --git a/src/gwin/gwin_textedit.c b/src/gwin/gwin_textedit.c index f90666ff..bb25c102 100644 --- a/src/gwin/gwin_textedit.c +++ b/src/gwin/gwin_textedit.c @@ -18,7 +18,9 @@ #include // Some settings - const int CURSOR_EXTRA_HEIGHT = 1; +const int TEXT_PADDING_LEFT = 4; +const int CURSOR_PADDING_LEFT = 0; +const int CURSOR_EXTRA_HEIGHT = 1; // Macros to assist in data type conversions #define gh2obj ((GTexteditObject *)gh) @@ -185,7 +187,10 @@ GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* widget, GWidgetInit* p widget->textBuffer[i] = '\0'; } - widget->cursorPos = 0; + // Set text and cursor position + strncpy(widget->textBuffer, gwinGetText((GHandle)widget), widget->bufferSize); // FixMe: pInit->text leads to a segfault + widget->cursorPos = strlen(widget->textBuffer); + widget->w.g.flags |= flags; gwinSetVisible(&widget->w.g, pInit->g.show); @@ -206,22 +211,20 @@ static void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param) color_t cursorColor = (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge; // Render background and string + //gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); 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) { + if (gwinGetFocus() == (GHandle)gw) { // 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 textWidth = gdispGetStringWidthCount(gw2obj->textBuffer, gw->g.font, gw2obj->cursorPos); 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 lineX0 = gw->g.x + textWidth + CURSOR_PADDING_LEFT + gdispGetFontMetric(gw->g.font, fontBaselineX)/2; + coord_t lineX1 = lineX0; 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); diff --git a/src/gwin/gwin_widget.c b/src/gwin/gwin_widget.c index 1d270a5f..9dc4d0d8 100644 --- a/src/gwin/gwin_widget.c +++ b/src/gwin/gwin_widget.c @@ -153,6 +153,7 @@ static void gwidgetEvent(void *param, GEvent *pe) { bool_t foundWidget = FALSE; bool_t endOfListDetected = FALSE; GHandle nextWidget = gwinGetFocus(); + GHandle prevWidget = gwinGetFocus(); do { nextWidget = gwinGetNextWindow(nextWidget); foundWidget = TRUE; @@ -189,6 +190,15 @@ static void gwidgetEvent(void *param, GEvent *pe) { } while (foundWidget == FALSE); gwinSetFocus(nextWidget); + // Redraw the new and the previous focused widget because they usually render differently when + // they are not focused anymore (eg. no blinking cursor) + if (prevWidget != 0) { + gwinRedraw(prevWidget); + } + if (nextWidget != 0) { + gwinRedraw(nextWidget); + } + break; }