Oshel Posted August 14, 2017 Report Posted August 14, 2017 Hay, I am roaming with the uGFX library and I found no such thing as input text box for keyboard. I know there are string box but I guess they are not proper for the solution. So I managed to build my own widget for this and it works neat- with a cursor etc. I based on the custom widget example: typedef struct { GWidgetObject widget; char text[50]; uint8_t textLength; uint8_t toggleCursor; font_t font; } tInpuTextBox; GHandle ghInputTextBox; tInpuTextBox inputTextBoxObject; // Functions for VMT void inputTextBoxDraw ( GWidgetObject* gw, void* param); static void mousePressDownInputTextBox( GWidgetObject* gw, coord_t x, coord_t y); static void keyboardPressDownInputTextBox( GWidgetObject *gw, GEventKeyboard *pke); // End of Functions for VMT static void mousePressDownInputTextBox( GWidgetObject* gw, coord_t x, coord_t y) { } void keyboardPressDownInputTextBox( GWidgetObject *gw, GEventKeyboard *pke) { if (pke->bytecount) { uint8_t i; for (i = 0; i < pke->bytecount; i++) { switch (pke->c[i]) { case GKEY_BACKSPACE: // Prevent from going below o (to 0xFF exactly) if (((tInpuTextBox *)gw)->textLength != 0) { ((tInpuTextBox *)gw)->textLength--; } break; default: // Prevent from going out of the table if (((tInpuTextBox *)gw)->textLength != sizeof(((tInpuTextBox *)gw)->text) - 2) // 1 for '\0' and 1 for cursor { ((tInpuTextBox *)gw)->text[((tInpuTextBox *)gw)->textLength] = pke->c[i]; ((tInpuTextBox *)gw)->textLength++; } break; } } // Finish with ending mark ((tInpuTextBox *)gw)->text[((tInpuTextBox *)gw)->textLength] = '\0'; // Add the cursor if (((tInpuTextBox *)gw)->toggleCursor) { ((tInpuTextBox*)ghInputTextBox)->text[((tInpuTextBox*)ghInputTextBox)->textLength + 1] = '\0'; ((tInpuTextBox*)ghInputTextBox)->text[((tInpuTextBox*)ghInputTextBox)->textLength] = '|'; } // Redraw the box _gwinUpdate(ghInputTextBox); } } void inputTextBoxDraw ( GWidgetObject* gw, void* param) { gdispGFillArea( gw->g.display, gw->g.x + 1, gw->g.y + 1, gw->g.width - 2, gw->g.height - 2, White); gdispGDrawBox( gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, Black); // Get the string length uint16_t stringLength = gdispGetStringWidth( ((tInpuTextBox *)gw)->text, ((tInpuTextBox *)gw)->font); uint8_t i = 0; if (stringLength > (gw->g.width - 4)) { // Find the string which actually fit into the box while (stringLength > (gw->g.width - 4)) { i++; stringLength = gdispGetStringWidth( (((tInpuTextBox *)gw)->text) + i, ((tInpuTextBox *)gw)->font); } } gdispGDrawString( gw->g.display, gw->g.x + 2, gw->g.y + (gw->g.height / 2) - 6, // 6 because of the fixed font height (dunno how to make is versatile (((tInpuTextBox *)gw)->text) + i, ((tInpuTextBox *)gw)->font, Black); } void guiToggleCursor ( uint8_t toggle) { if (gwinGetEnabled(ghInputTextBox)) { ((tInpuTextBox*)ghInputTextBox)->toggleCursor = toggle; if (toggle) { ((tInpuTextBox*)ghInputTextBox)->text[((tInpuTextBox*)ghInputTextBox)->textLength + 1] = '\0'; ((tInpuTextBox*)ghInputTextBox)->text[((tInpuTextBox*)ghInputTextBox)->textLength] = '|'; } else { ((tInpuTextBox*)ghInputTextBox)->text[((tInpuTextBox*)ghInputTextBox)->textLength] = '\0'; } _gwinUpdate(ghInputTextBox); } } static const gwidgetVMT inputTextBoxVMT = { { "inpuTextBox", // The classname sizeof(inputTextBoxObject), // The object size _gwidgetDestroy, // The destroy routine _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, inputTextBoxDraw, // The default drawing routine #if GINPUT_NEED_MOUSE { mousePressDownInputTextBox, // Process mouse down events 0, // Process mouse up events 0, // Process mouse move events }, #endif #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD { keyboardPressDownInputTextBox // Process keyboard events }, #endif #if GINPUT_NEED_TOGGLE { 0, // Toggle role 0, // Assign Toggles 0, // Get Toggles 0, // Process toggle off events 0, // Process toggle on events }, #endif #if GINPUT_NEED_DIAL { 0, // No dial roles 0, // Assign Dials 0, // Get Dials 0, // Process dial move events }, #endif }; void inputTextBoxCreate ( void) { // Create input text box gwinWidgetClearInit(&widget); widget.text = "Input text box"; widget.g.parent = ghFrame; widget.g.width = widget.g.parent->width - 15; widget.g.height = 30; widget.g.x = 5; widget.g.y = 10; widget.g.show = TRUE; tInpuTextBox* pointer; pointer = (tInpuTextBox*) _gwidgetCreate( GDISP, &inputTextBoxObject.widget, &widget, &inputTextBoxVMT); if (!pointer) { while(1); } pointer->textLength = 0; pointer->text[0] = '\0'; pointer->font = gdispOpenFont("GDISP_INCLUDE_FONT_DEJAVUSANS12_AA"); gwinSetVisible((GHandle) pointer, widget.g.show); ghInputTextBox = (GHandle) pointer; } The toggle handle is triggered from a timer (1 sec toggle). I'd like also to add cursor moving with a mouse (touchscreen). Btw- is it proper way to write such a thing? Would you make anything in a diffrent way?
inmarket Posted August 15, 2017 Report Posted August 15, 2017 Great work on creating your own widget! There are a couple of errors in your allocation of the text buffer. There is already a text edit in the gwin module. See demos/modules/textedit and demos/modules/gwin/virtual_keyboard If you compare the source for the gwin textedit to yours you will see the similarities and the differences.
Oshel Posted August 16, 2017 Author Report Posted August 16, 2017 Oh, I see! I thought that this kind of widget is so obvious that there must be such kind of thing already implemented. Thank you. By the way- is there any way to create own keyboard template? I mean I would like to change how buttons look like.
Joel Bodenmann Posted August 16, 2017 Report Posted August 16, 2017 Yes, you can completely customize the keyboard layout. Have a look at the existing layout that you can find under /src/gwin/gwin_keyboard_layout.c. It's really just a matter of filling in a struct. You can use gwinKeyboardSetLayout() to set your own layout.
Oshel Posted August 16, 2017 Author Report Posted August 16, 2017 (edited) Hay Joel, Bu as I can see you can not in a simple way change how the keyboard looks lke. You can manipulate with which buttons are active, how they are arranged, what colors will they be when pressed etc but you can not use, let's say, a bitmap as a background of button (single one- I know it only makes sense for fixed keyboard sizes etc, it's just hypothetical). Or make color blending between buttons. I mean create custom redraw routine. P.S. I am just trying to make a copy of existing GUI which is currently made on Linux to make an impress that your library can replace expensive GUIs on Linux. Edited August 16, 2017 by Oshel
Joel Bodenmann Posted August 16, 2017 Report Posted August 16, 2017 As you mentioned yourself what you're after is a custom rendering routine. Every GWIN widget supports that: https://wiki.ugfx.io/index.php/Creating_a_custom_rendering_routine I'd recommend you to simply copy the existing one to your project and modify from there.
Oshel Posted August 16, 2017 Author Report Posted August 16, 2017 What you are saying is that I should define new customDraw routine for the keyboard widget, copy the content of gwinKeyboardDraw_Normal and change it as I want, yes?
Joel Bodenmann Posted August 16, 2017 Report Posted August 16, 2017 Exactly. Of course you could start from scratch but that probably won't be as efficient as all the button placement code will be the same.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now