2019-12-19 02:57 AM
I am implementing a Custom keyboard to enter text.
Now I want to have
I achieved to display a cursor, but the position has to be adapted in relation to the text length which depends on the font width of the characters in the text (I have Calibri, which is not monotype).
How can I get the font width of a single character?
And how can I insert text at the current position instead of cutting the text after that insert-position?
Thank you for any suggestions!
2019-12-19 05:53 AM
Ok: Text width solution works:
For any one interested, here my solution to calculate the Cursor position for the current buffer position:
int CustomKeyboard::calcCursorPosition()
{
int n=0, nPos, nCursorPos=0;
// get font from assets
Font* font = FontManager::getFont(Typography::CALIBRIMEDIUM);
nPos = keyboard.getBufferPosition();
for (n = 0; n < nPos; n++)
{
nCursorPos+= font->getCharWidth(buffer[n]);
}
return nCursorPos;
}
2019-12-20 05:36 AM
Ok, and now I got the insert functionality working with following steps:
1)
Save Text of keyboard buffer to a copy buffer at startup and every time a character is inserted:
Unicode::strncpy(bufSav, buffer, BUFFER_SIZE);
2)
Adapt keyPressedhandler:
void CustomKeyboard::keyPressedhandler(Unicode::UnicodeChar keyChar)
{
uint16_t pos = keyboard.getBufferPosition();
int n, nSize,nSizeOld;
nSize = Unicode::strlen(buffer);
nSizeOld = Unicode::strlen(bufSav);
if ((nSizeOld >= nSize) && (nSizeOld > 0))
{
if (bClickedSpecialKey != true) // not Backspace/Mode/Shift?
{
// Restore remaining text from copy
for (n = pos; n < BUFFER_SIZE; n++)
{
buffer[n] = bufSav[n-1];
}
}
}
bClickedSpecialKey = false;
// Save current buffer for Insert-Handling
Unicode::strncpy(bufSav, buffer, BUFFER_SIZE);
// After the first keypress, the keyboard will shift to lowercase.
if (firstCharacterEntry && keyChar != 0)
{
firstCharacterEntry = false;
uppercaseKeys = false;
setKeyMappingList();
}
setCaret(); // Cursor at current position
}
2019-12-20 10:26 PM
This is very helpful. I'm also going to need a full keyboard for my project. I was going to write my own as I want to be able to allow users to edit better. Only allowing them to BS over the last character will not cut it for my project.
I was going to just write my own keyboard from scratch, but it looks like you have enhanced the current custom keyboard object.
Thanks for posting this.
2019-12-23 05:24 AM
Hi Jim,
just in case you need the cursor implementation, please see how it is done in the following link. I did take this feature from there:
https://touchgfx.zendesk.com/hc/en-us/community/posts/115002704212-Keyboard-Cursor
In my user interface I have included two buttons which process to move the cursor 1 position to the left and right so this allows to set the cursor to any character position in the edit field.
I am still working on the direct touch handling to set the cursor anywhere in the text area.
Have a Merry Christmas and a Happy New Year!
2019-12-30 08:08 AM
Ok, finally I have the time to provide the last step for setting the cursor to any place within the string by clicking in the text area:
1) Forward the handleClickEvent to the CustomKeyboard form the view.
2) Handle Click Event in the CustomKeyboard:
void CustomKeyboard::handleClickEvent(const ClickEvent& evt)
{
unsigned int x = evt.getX();
unsigned int y = evt.getY();
// in case clicked into text field area:
if ((x >= TEXT_POS_X) && (x <= (TEXT_POS_X + TEXT_POS_WIDTH)) &&
(y >= TEXT_POS_Y) && (y <= (TEXT_POS_Y + TEXT_POS_HEIGHT)))
{
x -= TEXT_POS_X;
// find closest Position of click event
m_position = findPosition(x);
//This find the end of buffer so that the caret will not appear at a weird place
if (m_position > BUFFER_SIZE)
{
m_position = BUFFER_SIZE;
}
keyboard.setBufferPosition(m_position);
setCaret();
}
}
uint16_t CustomKeyboard::findPosition(int x)
{
int nSize, i, nTextPos=0;
nSize = Unicode::strlen(buffer);
for (nTextPos = 0; nTextPos <= nSize; nTextPos++)
{
i = calcCursorPosition(nTextPos);
if (i >= x) // Beyond clicked Position
{
// Cursor would be set after the character which is on the right side of the click position
if (nTextPos > 0)
nTextPos--; // Therefore: set to one position on the left
return (uint16_t)nTextPos;
}
return (uint16_t)nTextPos;
}