Improving keyboard widget default renderer (thanks to TriZet)

This commit is contained in:
Joel Bodenmann 2015-12-10 21:58:12 +01:00
parent a51e2b3511
commit b89ce7c7b3
2 changed files with 148 additions and 67 deletions

View File

@ -7,6 +7,7 @@ FEATURE: Added support for numerous compilers
FIX: Improving STM32LTDC driver FIX: Improving STM32LTDC driver
FEATURE: Added support for NIOS-II platform FEATURE: Added support for NIOS-II platform
FEATURE: Added Altera-MAX10-NEEK board support FEATURE: Added Altera-MAX10-NEEK board support
FIX: Vastly improving keyboard widget default rendering
*** Release 2.4 *** *** Release 2.4 ***

View File

@ -393,24 +393,27 @@ static const GColorSet *getDrawColors(GWidgetObject *gw) {
*/ */
void gwinKeyboardDraw_Normal(GWidgetObject *gw, void *param) { void gwinKeyboardDraw_Normal(GWidgetObject *gw, void *param) {
#define gk ((GKeyboardObject *)gw) #define gk ((GKeyboardObject *)gw)
char cap[5]; char cap[5];
const char *pcap; const char *pcap;
const utf8 *krow; const utf8 *krow;
coord_t x, y, cx, cy; coord_t x, y, cx, cy;
uint8_t rows, cols, row, col, kcols; uint8_t rows, cols, row, col, kcols;
ucode key; ucode key;
fixed fx, fy; fixed fx, fy;
const GColorSet *pcol; const GColorSet *pcol;
(void) param; (void) param;
if (gw->g.vmt != (gwinVMT *)&keyboardVMT) return; // Make sure that this is a keyboard widget object
if (gw->g.vmt != (gwinVMT *)&keyboardVMT)
return;
// Get the y parameters // Get the y parameters
rows = NumKeyRows(gk->keyset); rows = NumKeyRows(gk->keyset);
fy = FIXED(gk->w.g.height) / rows; fy = FIXED(gk->w.g.height) / rows;
for(row = 0; row < rows; row++) { for (row = 0; row < rows; row++) {
y = NONFIXED(fy * row + FIXED0_5); y = NONFIXED(fy * row + FIXED0_5);
cy = NONFIXED(fy * (row+1) + FIXED0_5) - y; cy = NONFIXED(fy * (row+1) + FIXED0_5) - y;
@ -420,82 +423,159 @@ void gwinKeyboardDraw_Normal(GWidgetObject *gw, void *param) {
// Get the x parameters // Get the x parameters
cols = UTF8StrLen(krow); cols = UTF8StrLen(krow);
fx = FIXED(gk->w.g.width) / cols; fx = FIXED(gk->w.g.width) / cols;
for(col = 0; col < cols; col=kcols) { for (col = 0; col < cols; col=kcols) {
// Choose the color // Get the correct color set
if (!(gk->w.g.flags & GWIN_FLG_SYSENABLED)) if (!(gk->w.g.flags & GWIN_FLG_SYSENABLED))
pcol = &gk->w.pstyle->disabled; pcol = &gk->w.pstyle->disabled;
else if (gk->keyrow == row && gk->keycol == col) else
pcol = &gk->w.pstyle->pressed;
else
pcol = &gk->w.pstyle->enabled; pcol = &gk->w.pstyle->enabled;
// Get the key // Get the key
key = UTF8CharAt(krow, col); key = UTF8CharAt(krow, col);
// Amalgamate identical keys into one big key // Fuse identical keys into one big key
kcols = col+1; kcols = col+1;
while(UTF8CharAt(krow, kcols) == key) while (UTF8CharAt(krow, kcols) == key)
kcols++; kcols++;
// If quick update needed and keyboard already drawn (if not use this flag, then bug when screen touched before keyboard was drawn)
if ( (gk->w.g.flags & GKEYBOARD_FLG_QUICKUPDATE) && !(gk->w.g.flags & GWIN_FLG_BGREDRAW) ) {
// If key pressed
if ( (gk->keyrow != GKEY_BAD_ROWCOL) && (gk->keycol != GKEY_BAD_ROWCOL) ) {
// And previous key have
if ( (gk->lastkeyrow != GKEY_BAD_ROWCOL) && (gk->lastkeycol != GKEY_BAD_ROWCOL) ) {
if (gk->lastkeyrow == row && gk->lastkeycol == col) {
// If keyboard has no "disabled" color
if (pcol != &gk->w.pstyle->disabled)
pcol = &gk->w.pstyle->enabled;
gk->lastkeyrow = gk->lastkeycol = GKEY_BAD_ROWCOL;
} else {
continue;
}
}
// If no previous key
else {
if (gk->keyrow == row && gk->keycol == col) {
if (pcol != &gk->w.pstyle->disabled)
pcol = &gk->w.pstyle->pressed;
gk->lastkeyrow = row;
gk->lastkeycol = col;
}
else if (gk->lastkeyrow == row && gk->lastkeycol == col)
{
if (pcol != &gk->w.pstyle->disabled) pcol = &gk->w.pstyle->enabled;
}
else continue;
}
}
// If key up, and need clear the previous key
else if ( (gk->lastkeyrow != GKEY_BAD_ROWCOL) && (gk->lastkeycol != GKEY_BAD_ROWCOL) )
{
if ( (gk->lastkeyrow == row) && (gk->lastkeycol == col) )
{
if (pcol != &gk->w.pstyle->disabled) pcol = &gk->w.pstyle->enabled;
}
else continue;
}
}
else
{
gk->lastkeyrow = gk->lastkeycol = GKEY_BAD_ROWCOL;
}
x = NONFIXED(fx * col + FIXED0_5); x = NONFIXED(fx * col + FIXED0_5);
cx = NONFIXED(fx * kcols + FIXED0_5) - x; cx = NONFIXED(fx * kcols + FIXED0_5) - x;
if (key < 0x20) { if (key < 0x20) {
pcap = gk->keytable->skeys[key-1].keycap; pcap = gk->keytable->skeys[key-1].keycap;
} else { } else {
cap[UCode2UTF8((utf8 *)cap, key)] = 0; cap[UCode2UTF8((utf8 *)cap, key)] = 0;
pcap = cap; pcap = cap;
} }
switch(*pcap) {
case '\001': // Shift (up arrow) switch(*pcap) {
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text); /* / \ */ case '\001': // Shift (up-arrow)
gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text); gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, pcol->text); /* _ _ */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* || */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* _ */
break;
case '\002': // Shift locked (up arrow - bold)
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text); /* / \ */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, pcol->text); /* _ _ */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* || */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* _ */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/5, gw->g.y+y+cy -cy/4, gw->g.x+x+cx/2+cx/5, gw->g.y+y+cy -cy/4, pcol->text); /* ___ */
break;
case '\t':
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+1, gw->g.x+x+cx-1, gw->g.y+y+cy/2, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+cy-1, gw->g.x+x+cx-1, gw->g.y+y+cy/2, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx-1, gw->g.y+y+1, gw->g.x+x+cx-1, gw->g.y+y+cy-1, pcol->text);
break;
case '\b': // Backspace
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/8, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/3, pcol->text); /* / */ gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text); /* / \ */
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/8, gw->g.y+y+cy/2, gw->g.x+x+cx-cx/8, gw->g.y+y+cy/2, pcol->text); /* -- */ gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/8, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y+cy -cy/3, pcol->text); /* \ */ gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, pcol->text); /* _ _ */
break; gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, pcol->text);
case '\r': // Enter gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* || */
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill); gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* _ */
gdispGDrawLine(gw->g.display, gw->g.x+x+(cx/3)*2, gw->g.y+y+cy/2, gw->g.x+x+(cx/3)*2, gw->g.y+y+cy/5, pcol->text); /* | */ break;
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/3, gw->g.y+y+cy/2, gw->g.x+x+cx/3 +cx/8, gw->g.y+y +cy/3, pcol->text); /* / */
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/3, gw->g.y+y+cy/2, gw->g.x+x+(cx/3)*2, gw->g.y+y+cy/2, pcol->text); /* -- */ case '\002': // Shift locked (underlined up-arrow)
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/3, gw->g.y+y+cy/2, gw->g.x+x+cx/3 +cx/8, gw->g.y+y+cy -cy/3, pcol->text); /* \ */ gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
break;
default: gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text); /* / \ */
gdispGFillStringBox(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcap, gw->g.font, pcol->text, pcol->fill, justifyCenter); gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/4, pcol->text);
} gdispGDrawLine(gw->g.display, gw->g.x+x +cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, pcol->text); /* _ _ */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx -cx/4, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, pcol->text);
gdispGDrawBox(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->text); // Frame gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* || */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy/2, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/6, gw->g.y+y+cy -cy/3, gw->g.x+x+cx/2+cx/6, gw->g.y+y+cy -cy/3, pcol->text); /* _ */
gdispGDrawLine(gw->g.display, gw->g.x+x+cx/2-cx/5, gw->g.y+y+cy -cy/4, gw->g.x+x+cx/2+cx/5, gw->g.y+y+cy -cy/4, pcol->text); /* ___ */
break;
case '\t': // Tabulator
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+1, gw->g.x+x+cx-1, gw->g.y+y+cy/2, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+1, gw->g.y+y+cy-1, gw->g.x+x+cx-1, gw->g.y+y+cy/2, pcol->text);
gdispGDrawLine(gw->g.display, gw->g.x+x+cx-1, gw->g.y+y+1, gw->g.x+x+cx-1, gw->g.y+y+cy-1, pcol->text);
break;
case '\b': // Backspace
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/8, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y +cy/3, pcol->text); /* / */
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/8, gw->g.y+y+cy/2, gw->g.x+x+cx-cx/8, gw->g.y+y+cy/2, pcol->text); /* -- */
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/8, gw->g.y+y+cy/2, gw->g.x+x+cx/2, gw->g.y+y+cy -cy/3, pcol->text); /* \ */
break;
case '\r': // Enter
gdispGFillArea(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->fill);
gdispGDrawLine(gw->g.display, gw->g.x+x+(cx/3)*2, gw->g.y+y+cy/2, gw->g.x+x+(cx/3)*2, gw->g.y+y+cy/5, pcol->text); /* | */
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/3, gw->g.y+y+cy/2, gw->g.x+x+cx/3 +cx/8, gw->g.y+y+cy/3, pcol->text); /* / */
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/3, gw->g.y+y+cy/2, gw->g.x+x+(cx/3)*2, gw->g.y+y+cy/2, pcol->text); /* -- */
gdispGDrawLine(gw->g.display, gw->g.x+x+ cx/3, gw->g.y+y+cy/2, gw->g.x+x+cx/3 +cx/8, gw->g.y+y+cy -cy/3, pcol->text); /* \ */
break;
default: // Regular character
gdispGFillStringBox(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcap, gw->g.font, pcol->text, pcol->fill, justifyCenter);
break;
}
// Draw the frame (border around the entire widget)
gdispGDrawBox(gw->g.display, gw->g.x+x, gw->g.y+y, cx, cy, pcol->edge);
// If key up and we already cleared the previous key
if ( (gk->keyrow == GKEY_BAD_ROWCOL) && (gk->keycol == GKEY_BAD_ROWCOL) && (gk->lastkeyrow == row) && (gk->lastkeycol == col) ) {
gk->lastkeyrow = gk->lastkeycol = GKEY_BAD_ROWCOL;
return;
}
// Just quit the cycle if we did all the work in order not to waste any CPU time
if ( (row >= gk->keyrow && col >= gk->keycol) && (row >= gk->lastkeyrow && col >= gk->lastkeycol) ) {
return;
}
} }
} }