cancel
Showing results for 
Search instead for 
Did you mean: 

How to create numeric keypad?

BParh.1
Senior III

I know TouchGFX provide a template for keyboard, but the layout is far from what I need. What I need is something like our typical numeric keypad in our standard PC keyboard ( the one on right hand side).

When I take a look the sample code, it seems not trivial, there are 3 cpp/hpp files that I can see. Can someone give me pointer how to proceed?

If there is a ready sample would be great, if not please advice me which files need to be modified. Or maybe I can break down my questions:

  1. Which files to modify to change the keyboard layout into numeric keypad?
  2. Which pad need to modify to change the keyboard text screen depending on which button triggering the keyboard?

I recommend ST make a sample demo for this as this is very typical usage and there would be many developers looking for it

10 REPLIES 10
BParh.1
Senior III

This is a sample I would like to achieve

BParh.1
Senior III

I have difficulty to modify existing keyboard sample in TouchGFX, it seems I have to change also class Keyboard which seems not possible for user as the code is in platform level and I dont think meant for user to change

BParh.1
Senior III

Hi @Martin KJELDSEN​ , I wonder if you could help me please, I have been stucked for days.

I tried to change what I can from the original TouchGFX keyboard template, but still cant achieve the layout that I want as posted above. I have modified these files but seem would allow me to achieve the layout I want:

  1. CustomKeyboard.hpp
  2. KeyboardMapping.hpp
  3. KeyboardLayout.hpp

Could you give me some pointers to achieve that layout please.

awiernie
Senior II

I made a custom container "CustomContainerInputFloatValue" which has similar layout but additional keys for decimal seperator, +/- and backspace and clear.

For each key, in interactions I defined a virtual function, e.g. goKey1.

This function checks, if it is allowed to add the new key and appends the key to a string.

The screen which uses the custom container retrieves the value with getValue().

I can also set the required range of value and the decimal point (point or comma).

Maybe you can use this as a base.

Here is the header file:

#ifndef CUSTOMCONTAINERINPUTFLOATVALUE_HPP

#define CUSTOMCONTAINERINPUTFLOATVALUE_HPP

#include <gui_generated/containers/CustomContainerInputFloatValueBase.hpp>

const int strFloatValueBufferSize = 20;

class CustomContainerInputFloatValue : public CustomContainerInputFloatValueBase

{

public:

  CustomContainerInputFloatValue();

  virtual ~CustomContainerInputFloatValue() {}

  virtual void initialize();

// functions called is a key is pressed:

virtual void goKey0();

virtual void goKey1();

virtual void goKey2();

virtual void goKey3();

virtual void goKey4();

virtual void goKey5();

virtual void goKey6();

virtual void goKey7();

virtual void goKey8();

virtual void goKey9();

virtual void goKeyDecimalPoint();

virtual void goKeyPlusMinus();

virtual void goKeyBackspace();

virtual void goKeyBackword();

virtual void setDefaultValue(float value);

virtual void setDecimalPoint(char decimalPt);

virtual void setMinValueAllowed(float f);

virtual void setMaxValueAllowed(float f);

// update text field

virtual void update();

// true, if new value is within allowed range

virtual bool isAddCharPossible(char ch);

virtual void addChar(char ch);

virtual bool isEqual(const char * string);

virtual void clear();

virtual float getValue();

char m_str[strFloatValueBufferSize];

char decimalPoint;

float minValueAllowed;

float maxValueAllowed;

protected:

};

#endif // CUSTOMCONTAINERINPUTFLOATVALUE_HPP

awiernie
Senior II

And here is the cpp file:

#include <gui/containers/CustomContainerInputFloatValue.hpp>

#include <cstring>

CustomContainerInputFloatValue::CustomContainerInputFloatValue()

{

decimalPoint = '.';

minValueAllowed = 0;

maxValueAllowed = 100;

}

void CustomContainerInputFloatValue::initialize()

{

CustomContainerInputFloatValueBase::initialize();

}

void CustomContainerInputFloatValue::goKey0()

{

if (! isEqual("0"))

{

if (isAddCharPossible('0'))

{

addChar('0');

}

update();

}

}

void CustomContainerInputFloatValue::goKey1()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('1'))

{

addChar('1');

}

update();

}

void CustomContainerInputFloatValue::goKey2()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('2'))

{

addChar('2');

}

update();

}

void CustomContainerInputFloatValue::goKey3()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('3'))

{

addChar('3');

}

update();

}

void CustomContainerInputFloatValue::goKey4()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('4'))

{

addChar('4');

}

update();

}

void CustomContainerInputFloatValue::goKey5()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('5'))

{

addChar('5');

}

update();

}

void CustomContainerInputFloatValue::goKey6()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('6'))

{

addChar('6');

}

update();

}

void CustomContainerInputFloatValue::goKey7()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('7'))

{

addChar('7');

}

update();

}

void CustomContainerInputFloatValue::goKey8()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('8'))

{

addChar('8');

}

update();

}

void CustomContainerInputFloatValue::goKey9()

{

if (isEqual("0"))

{

clear();

}

if (isAddCharPossible('9'))

{

addChar('9');

}

update();

}

void CustomContainerInputFloatValue::goKeyDecimalPoint()

{

if (strlen(m_str) == 0)

{

addChar('0');

}

if (strchr(m_str, decimalPoint) == 0)

{

addChar(decimalPoint);

}

update();

}

void CustomContainerInputFloatValue::goKeyBackspace()

{

size_t l = strlen(m_str);

if (l > 0 && l <= strFloatValueBufferSize)

{

m_str [l-1] = 0;

update();

}

}

void CustomContainerInputFloatValue::goKeyBackword()

{

clear();

update();

}

void CustomContainerInputFloatValue::goKeyPlusMinus()

{

size_t l = strlen(m_str);

if (isEqual("0"))

{

clear();

addChar('-');

}

else if ((l > 1) && (m_str[0] == '-'))

{

if (l < strFloatValueBufferSize)

{

// remove first character

for (size_t n = 1; n < strFloatValueBufferSize; n++)

{

m_str[n-1] = m_str[n];

}

m_str[l-1] = 0;

}

}

else if (l >= 1)

{

// insert -

if (l < strFloatValueBufferSize)

{

for (size_t n = l; n; n--)

{

m_str[n] = m_str[n-1];

}

m_str[0] = '-';

m_str[strFloatValueBufferSize - 1] = 0;

}

}

update();

}

void CustomContainerInputFloatValue::update()

{

(void) Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, m_str);

textArea1.invalidate();

if (minValueAllowed < 0)

{

buttonKeyPlusMinus.setVisible(true);

}

else

{

buttonKeyPlusMinus.setVisible(false);

}

buttonKeyPlusMinus.invalidate();

}

void CustomContainerInputFloatValue::addChar(char ch)

{

size_t l = strlen(m_str);

if (l < (strFloatValueBufferSize-1))

{

m_str[l] = ch;

m_str[l+1] = 0;

}

}

bool CustomContainerInputFloatValue::isAddCharPossible(char ch)

{

bool b = false;

char str[strFloatValueBufferSize];

(void) strncpy(str, m_str, strFloatValueBufferSize);

size_t l = strlen(str);

if (l < (strFloatValueBufferSize-1))

{

str[l] = ch;

str[l+1] = 0;

float f = awiStrUtil::getFloat(str, strFloatValueBufferSize, decimalPoint);

if (f <= maxValueAllowed)

{

b = true;

}

}

return b;

}

void CustomContainerInputFloatValue::clear()

{

m_str[0] = 0;

}

bool CustomContainerInputFloatValue::isEqual(const char * string)

{

bool b = false;

if (string)

{

if (strcmp(string, m_str) == 0)

{

b = true;

}

}

return b;

}

void CustomContainerInputFloatValue::setDefaultValue(float value)

{

awiStrUtil::printFloat(value, -1, m_str, strFloatValueBufferSize, decimalPoint);

update();

}

void CustomContainerInputFloatValue::setDecimalPoint(char decimalPt)

{

decimalPoint = decimalPt;

}

float CustomContainerInputFloatValue::getValue()

{

return awiStrUtil::getFloat(m_str, strFloatValueBufferSize, decimalPoint);

}

void CustomContainerInputFloatValue::setMaxValueAllowed(float f)

{

maxValueAllowed = f;

}

void CustomContainerInputFloatValue::setMinValueAllowed(float f)

{

minValueAllowed = f;

}

awiernie
Senior II

to be complete, if float is needed and the decimal point could also be a comma:

namespace awiStrUtil {

float getFloat(char * valbuf, size_t valbufSize, char decimalPoint)

{

const int bufSize = 20;

char buf[bufSize];

for (size_t i = 0; (i < valbufSize) && (i < bufSize); i++)

{

buf[i] = valbuf[i];

if (buf[i] == decimalPoint && decimalPoint != '.')

{

buf[i] = '.';

}

}

buf[valbufSize - 1] = 0;

return atof(buf);

}

void printFloat(float value, int precision, char * valbuf, size_t valbufSize, char decimalPoint)

{

// would give an error with simulator: "-Werror=format-nonliteral"

// snprintf(valbuf, valbufSize, getFloatFormatString(precision), value);

switch (precision)

{

case -1:

{

(void) snprintf(valbuf, valbufSize, "%f", value);

// remove trailing 0 (after decimal point)

int l = strlen(valbuf);

bool decimalFound = false;

for (int i = 0; i < l; i++)

{

if (valbuf[i] == '.')

{

decimalFound = true;

break;

}

}

if (decimalFound)

{

for (int i = l; i; i--)

{

if (valbuf[i-1] == '0')

{

valbuf[i-1] = 0;

}

else

{

if (valbuf[i-1] == '.')

{

valbuf[i-1] = 0;

}

break;

}

}

}

}

break;

case 0: (void) snprintf(valbuf, valbufSize, "%.0f", value); break;

case 1: (void) snprintf(valbuf, valbufSize, "%.1f", value); break;

case 2: (void) snprintf(valbuf, valbufSize, "%.2f", value); break;

case 3: (void) snprintf(valbuf, valbufSize, "%.3f", value); break;

case 4: (void) snprintf(valbuf, valbufSize, "%.4f", value); break;

case 5: (void) snprintf(valbuf, valbufSize, "%.5f", value); break;

case 6: (void) snprintf(valbuf, valbufSize, "%.6f", value); break;

case 7: (void) snprintf(valbuf, valbufSize, "%.7f", value); break;

default:

(void) snprintf(valbuf, valbufSize, "***"); break;

break;

}

//#pragma GCC diagnostic pop

// replace . by ,

if (decimalPoint != '.')

{

for (size_t i = 0; i < valbufSize; i++)

{

if (valbuf[i] == 0)

{

break;

}

else if (valbuf[i] == '.')

{

valbuf[i] = decimalPoint;

}

}

}

}

}

BParh.1
Senior III

thank you @awiernie​ , I can leverage some of ideas, but for my usage, I decide to code keyboard behavior by myself instead of using TouchGFX sample as base.

awiernie
Senior II

> but for my usage, I decide to code keyboard behavior by myself instead of using TouchGFX sample as base

My solution does not use TouchGFX sample as base.

Xzhiy.1
Associate II

From my opinion, it is easy to modify CustomKeyboard demo to meet your challenge, you need to modify KeyboardKeyMapping.hpp and KeyboardLayout.hpp, and modify CustomKeyboard.cpp accordingly(delete unused callbacks).