Jump to content
Oshel

Input text box

Recommended Posts

Oshel   

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?

Share this post


Link to post
Share on other sites
inmarket   

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.

Share this post


Link to post
Share on other sites
Oshel   

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
Oshel   

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 by Oshel

Share this post


Link to post
Share on other sites
Oshel   

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?

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×