Skip to main content
ilyus
Senior II
June 24, 2021
Solved

Creating TextArea Programmatically With Wildcard and Buffer

  • June 24, 2021
  • 4 replies
  • 11894 views

So far, I've been able to create a TextArea with a wildcard in TouchGFX and then edit its buffer via program code - that works. I just edit the array and invalidate. Done.

However, I fail miserably when I try to create Textarea using code only. I have created boxes, for example, and scrollable containers, put stuff inside each other and they work (and many of them in arrays that I loop through when drawing), but textareas are pretty wild and also weirdly (under)documented, and there are pretty much no examples in the internet, I googled my fingers to blood and left almost no links unclicked in google.

My logic was to look at TextAreas created by TouchGFX generator and reproduce the procedure - worked with other things, but doesn't work for TextArea. Here is a WORKING automatically generated by TouchGFX code from ViewBase:

textArea1.setXY(0, 51);
textArea1.setColor(touchgfx::Color::getColorFrom24BitRGB(0, 0, 0));
textArea1.setLinespacing(0);
Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%s", touchgfx::TypedText(T_SINGLEUSEID63).getText());
textArea1.setWildcard(textArea1Buffer);
textArea1.resizeToCurrentText();
textArea1.setTypedText(touchgfx::TypedText(T_SINGLEUSEID62));
scrollableContainerMeasurement.add(textArea1);
scrollableContainerMeasurement.setScrollbarsPermanentlyVisible();

First of all, this function, Unicode::snprintf(), is weirdly documented and I have still no clue how to use it.

More specifically I have no idea what I have to put (when I create my own TextArea) instead of its parameter touchgfx::TypedText(T_SINGLEUSEID63).getText(). Documentation says it's TypedText type - what is it? How do I generate one? From what? What exactly is it? Documentation for it doesn't seem to have any functions that produce object of this obscure type.

Also, if I already do setWildcard(), why do I do setTypedText two lines lower? With some other Single Use ID, whatever that is. Seems like completely useless line of code. I don't understand what it does if I already have a Wildcardbuffer attached to TextArea.

Whenever I manually change the TextArea wildcard with code, I just change the Buffer array and invalidate - I don't need any TypedText or anything. But whenever I just dropped those lines that I don't understand (it doesn't compile with unchanged lines with my own TextAreas - I need to change them somehow, I guess?) and tied wildcardbuffer to the Textarea, it simply didn't show anything on the screen - as if I didn't create anything.

Any hint would be appreciated, thank you!

This topic has been closed for replies.
Best answer by ilyus

FULL SOLUTION TO CREATING CUSTOM TEXTAREA WITH CODE

With the help of everyone participating in this post and some other people in other threads (and, of course, my own undeniable genius *chuckle*), here is a summary of how you can create a textArea purely (99%) with code. Step by step from zero:

Open TouchGFX Designer. In the upper tabs, go to "Texts"->Typographies. Make sure there is a font you are going to use (or add another one), you need to generate letter glyphs using TouchGFX Designer. In my case, I did this:0693W00000BcRuBQAV.pngI'm using Verdana 40px font; In "Wildcard ranges" I have written 0-9,A-Z,a-z; this will force TouchGFX to generate glyphs for all letters and numbers even if no TextAreas created natively in TouchGFX Designer use them. Otherwise, you can miss a few letters of that font (and will see "?"). If you need other characters, such as commas and stuff, there is "wildcard characters" section for it.

Next, go to "Resources" tab. "Resource" is a set of formatting rules that we associate with every TextArea. Font size, font direction, Alignment and content. Add new resource to use with the new TextAreas that we will create with the code. You can use one Resource with multiple TextAreas. It's just a formatting feature, not the text itself. I am going to use "ResourceId3" for my custom TextAreas. Set the Typography of the Resource to the one you used in 1.In Resource text, write "<>" (means "wildcard"), If you write some text in there except "<>", it will be visible in all TextAreas using that resource. Wildcards, however, are individual for every TextArea. Personally, I want all TextAreas to have completely different content, so I do the following:0693W00000BcS0JQAV.png 

Now we have forced TouchGFX to generate all characters' glyphs for the font we're going to use and we have created text formatting rules, also known as Resource (Rules are: use that font with glyphs, align left, text direction left to right, text is entirely wildcard). So we finally get to generating stuff with the code.

Create the screen where you want to create your custom TextAreas. The screen can be empty, we just need the files for the screen to be generated to put our stuff into them. "Generate the code".

Find the screen view file. It should be located in "/gui/" folder (exact location differs depending on whether you created project in Cube or TouchGFX first, but it's always in the folder named "gui/" or "gui/src/screenname_screen/", "gui/included/..." for its header file). Look for "gui" folder (not gui_generated!). My screen is called "NewScreen", and my project was first created in TouchGFX Designer and later imported into CubeIDE, where I'm working on it. If you 're curious about how to import it there, there is a video on "EE by Karl" youtube channel that does just that.

I open "NewScreenView.cpp" and "NewScreenView.hpp". In the header file, we need to include TouchGFX components that we're going to use. If you're not sure what to add, create a widget in TouchGFX designer, generate code and go to "NewScreenViewBase.cpp/hpp" in gui_generated. That hpp will include stuff necessary to generate those specific widgets. Copy those includes to your NewScreenView.hpp. My NewScreenView.hpp has these includes:

#include <touchgfx/widgets/Box.hpp>
#include <touchgfx/widgets/Button.hpp>
#include <touchgfx/containers/ScrollableContainer.hpp>
#include <touchgfx/widgets/TextAreaWithWildcard.hpp>
#include <touchgfx/Color.hpp>
#include <texts/TextKeysAndLanguages.hpp>

Color and TextKeysAndLanguages are a must - you will haveto set color and you will need to connect your font/resource to the TextArea, those do exactly that. Others - whatever you want to create with your own code, should be there. My "includes" allow me to create Boxes (color fills), buttons, scrollable containers and TextAreas with a wildcard.

Next, let's declare our new custom TextArea in the header file.

My entire header file looks like this:

#ifndef NEWSCREENVIEW_HPP
#define NEWSCREENVIEW_HPP
 
#include <gui_generated/newscreen_screen/NewScreenViewBase.hpp>
#include <gui/newscreen_screen/NewScreenPresenter.hpp>
#include <touchgfx/widgets/Box.hpp>
#include <touchgfx/widgets/Button.hpp>
#include <touchgfx/containers/ScrollableContainer.hpp>
#include <touchgfx/widgets/TextAreaWithWildcard.hpp>
#include <touchgfx/Color.hpp>
#include <texts/TextKeysAndLanguages.hpp>
 
 
class NewScreenView : public NewScreenViewBase
{
public:
 NewScreenView();
 virtual ~NewScreenView() {}
 virtual void setupScreen();
 virtual void tearDownScreen();
 touchgfx::TextAreaWithOneWildcard testTextArea;
 touchgfx::Unicode::UnicodeChar testTextAreaBuffer[10];
 touchgfx::TextAreaWithOneWildcard testTextArea2;
 touchgfx::Unicode::UnicodeChar testTextAreaBuffer2[10];
protected:
};
 
#endif // NEWSCREENVIEW_HPP

In "Public" section, I have created two textAreas and two buffer arrays for them so that they can hold different stuff. As far as I remember, buffers are maximum 10 places long (haven't tried longer to be honest, feel free to try, I expect it to trim the text which is too long), and one last character has to be reserved for end of line character when it's put into the TextArea. so if you need 4 places for your text, you'll need an array of length 5.

Nothing stops you from declaring an array of boxes or array of buttons or array of textAreas. I had no problem creating an array of boxes that way,

What's left is to actually add stuff to our NewScreen.cpp, which in my hands looks like this:

#include <gui/newscreen_screen/NewScreenView.hpp>
 
NewScreenView::NewScreenView()
{
 
}
 
void NewScreenView::setupScreen()
{
 NewScreenViewBase::setupScreen();
 
 //CREATING ONE TEXTAREA
 testTextArea.setXY(200, 400);
 testTextArea.setColor(touchgfx::Color::getColorFrom24BitRGB(255, 255, 0));
 testTextArea.setLinespacing(0);
 testTextArea.setWildcard(testTextAreaBuffer);
 testTextArea.setTypedText(touchgfx::TypedText(T_RESOURCEID3));
 Unicode::snprintf(testTextAreaBuffer, 10, "Meow meow");
 testTextArea.resizeToCurrentText();
 add(testTextArea);
 testTextArea.invalidate();
 
 //CREATING SECOND TEXTAREA with the same resource
 testTextArea2.setXY(500, 400);
 testTextArea2.setColor(touchgfx::Color::getColorFrom24BitRGB(255, 255, 0));
 testTextArea2.setLinespacing(0);
 testTextArea2.setWildcard(testTextAreaBuffer2);
 testTextArea2.setTypedText(touchgfx::TypedText(T_RESOURCEID3)); //Same resource as the first TextArea. EXPERIMENT!
 Unicode::snprintf(testTextAreaBuffer2, 10, "Woof woof");
 testTextArea2.resizeToCurrentText();
 add(testTextArea2);
 testTextArea2.invalidate();
}
 
void NewScreenView::tearDownScreen()
{
 NewScreenViewBase::tearDownScreen();
}

 CONTINUES IN REPLY!

4 replies

ktrofimo
Senior III
June 24, 2021

Hello!

You can threat Unicode::snprintf( str, N, format, variables) as regular snprintf - printf limited to N characters. It is used just to make sure not to overwrite bytes after end of the buffer. I found it difficult to use for non-Latin characters and finally using now Unicode::fromUTF8( text, str, N );

Also you need to add all characters you are going to use with this font to Texts / Typographies otherwise you will get string of "?" (fallback characters)

ilyus
ilyusAuthor
Senior II
June 24, 2021

Yeah, I figured this one (snprintf) out about now. I'm sitting here experimenting and stuff, ***** to be mere mortal; but hat's not the main source of the problem. What is the TypedText thing? The documentation has literally zero information on what exactly it is, what it does and what it exists for. It just says "TypedText is an object", and it doesn't describe anything nor does it list any function to create one - only read from TypedText, but not create one. There are functinos that require that thing as a parameter, and I can't do it, because there is no way to create object of this type - there is no function, no constructor. Only to get text back from it (and it even doesn't specify return data type, it simply says "returns text" - last time I checked there was no datatype "text", so I have actually no clue what it returns, how to use it and why do I need it at all). That's all I could get from the TouchGFX documentation.

I would still prefer if someone just wrote 10 lines of code that create a TextArea (given definitions in header) that I can control. I'm pretty sure I'll understand what's what if I just see some code of creating a TextArea from scratch

ktrofimo
Senior III
June 24, 2021

touchgfx::TypedText(T_SINGLEUSEID63).getText()... Look for T_SINGLEUSEID63. This is an ID of text string you typed in designer and this function simply returns actual text. Put your own string instead:

Unicode::snprintf(textArea1Buffer, sizeof(textArea1Buffer), "My string with value %d", intVal);

Since you do not use designer to make your strings, do not use TypedText​

Alexandre RENOUX
Visitor II
June 29, 2021

Hello @ilyus​ ,

Better documentation on Text should be available very soon.

In the meantime, I made a very simple example on how to create Text Areas with a wildcard by code.

It's important to know that you will need the Designer to create your text being used as wildcard.

Hope this simple example will help you understand.

/Alexandre

ilyus
ilyusAuthor
Senior II
June 30, 2021

Hi! Thanks for the example. It's working the way I want it to work. Wanna make sure I understand it correctly, so I have a few clarifying questions.

  1. First of all, what exactly is TypedText? Can multiple TextAreas use one TypedText? What's the point of having TypedText AND Buffer array (aren't they the same thing?)? Both seem to set text, so what's the point of two things setting text, this question has been lingering me for some time already.
  2. As a follow-up to question 1, I don't understand what function myTextArea.setTypedText(touchgfx::TypedText(T_WIDLCARDID)); does in principle, what is the purpose of that specific line of code. Does it set font/direction of text? If so, I guess it's a reusable thing then? Given all Buffer arrays will be individual for each TextArea of course. If it is just font and text direction etc, then I just need one resource for all my TextAreas (provided they have the same font/direction/whatever else this thing does)

If I have to create a Resouce for each TextArea I wanna create with code, it kinda defeats the whole purpose - I can't and don't want to create 100 Resources for 100 TextAreas - which is actually very realistic in my case, I expect to have no less than 80 TextAreas on a single screen (scrollable) purely code-generated that I will for-loop through to set their values or read values from them.

I appreciate your help and patience. Will try things on my own now, maybe will figure it out myself after some experimenting, but it's still a good idea to ask a knowledgeable person, I think.

If I discover anything worthy that answers my question in any way, I will add it here for the infos. Some day in 2025 someone will find this thread in google and thank all of us haha.

ilyus
ilyusAuthorBest answer
Senior II
June 30, 2021

FULL SOLUTION TO CREATING CUSTOM TEXTAREA WITH CODE

With the help of everyone participating in this post and some other people in other threads (and, of course, my own undeniable genius *chuckle*), here is a summary of how you can create a textArea purely (99%) with code. Step by step from zero:

Open TouchGFX Designer. In the upper tabs, go to "Texts"->Typographies. Make sure there is a font you are going to use (or add another one), you need to generate letter glyphs using TouchGFX Designer. In my case, I did this:0693W00000BcRuBQAV.pngI'm using Verdana 40px font; In "Wildcard ranges" I have written 0-9,A-Z,a-z; this will force TouchGFX to generate glyphs for all letters and numbers even if no TextAreas created natively in TouchGFX Designer use them. Otherwise, you can miss a few letters of that font (and will see "?"). If you need other characters, such as commas and stuff, there is "wildcard characters" section for it.

Next, go to "Resources" tab. "Resource" is a set of formatting rules that we associate with every TextArea. Font size, font direction, Alignment and content. Add new resource to use with the new TextAreas that we will create with the code. You can use one Resource with multiple TextAreas. It's just a formatting feature, not the text itself. I am going to use "ResourceId3" for my custom TextAreas. Set the Typography of the Resource to the one you used in 1.In Resource text, write "<>" (means "wildcard"), If you write some text in there except "<>", it will be visible in all TextAreas using that resource. Wildcards, however, are individual for every TextArea. Personally, I want all TextAreas to have completely different content, so I do the following:0693W00000BcS0JQAV.png 

Now we have forced TouchGFX to generate all characters' glyphs for the font we're going to use and we have created text formatting rules, also known as Resource (Rules are: use that font with glyphs, align left, text direction left to right, text is entirely wildcard). So we finally get to generating stuff with the code.

Create the screen where you want to create your custom TextAreas. The screen can be empty, we just need the files for the screen to be generated to put our stuff into them. "Generate the code".

Find the screen view file. It should be located in "/gui/" folder (exact location differs depending on whether you created project in Cube or TouchGFX first, but it's always in the folder named "gui/" or "gui/src/screenname_screen/", "gui/included/..." for its header file). Look for "gui" folder (not gui_generated!). My screen is called "NewScreen", and my project was first created in TouchGFX Designer and later imported into CubeIDE, where I'm working on it. If you 're curious about how to import it there, there is a video on "EE by Karl" youtube channel that does just that.

I open "NewScreenView.cpp" and "NewScreenView.hpp". In the header file, we need to include TouchGFX components that we're going to use. If you're not sure what to add, create a widget in TouchGFX designer, generate code and go to "NewScreenViewBase.cpp/hpp" in gui_generated. That hpp will include stuff necessary to generate those specific widgets. Copy those includes to your NewScreenView.hpp. My NewScreenView.hpp has these includes:

#include <touchgfx/widgets/Box.hpp>
#include <touchgfx/widgets/Button.hpp>
#include <touchgfx/containers/ScrollableContainer.hpp>
#include <touchgfx/widgets/TextAreaWithWildcard.hpp>
#include <touchgfx/Color.hpp>
#include <texts/TextKeysAndLanguages.hpp>

Color and TextKeysAndLanguages are a must - you will haveto set color and you will need to connect your font/resource to the TextArea, those do exactly that. Others - whatever you want to create with your own code, should be there. My "includes" allow me to create Boxes (color fills), buttons, scrollable containers and TextAreas with a wildcard.

Next, let's declare our new custom TextArea in the header file.

My entire header file looks like this:

#ifndef NEWSCREENVIEW_HPP
#define NEWSCREENVIEW_HPP
 
#include <gui_generated/newscreen_screen/NewScreenViewBase.hpp>
#include <gui/newscreen_screen/NewScreenPresenter.hpp>
#include <touchgfx/widgets/Box.hpp>
#include <touchgfx/widgets/Button.hpp>
#include <touchgfx/containers/ScrollableContainer.hpp>
#include <touchgfx/widgets/TextAreaWithWildcard.hpp>
#include <touchgfx/Color.hpp>
#include <texts/TextKeysAndLanguages.hpp>
 
 
class NewScreenView : public NewScreenViewBase
{
public:
 NewScreenView();
 virtual ~NewScreenView() {}
 virtual void setupScreen();
 virtual void tearDownScreen();
 touchgfx::TextAreaWithOneWildcard testTextArea;
 touchgfx::Unicode::UnicodeChar testTextAreaBuffer[10];
 touchgfx::TextAreaWithOneWildcard testTextArea2;
 touchgfx::Unicode::UnicodeChar testTextAreaBuffer2[10];
protected:
};
 
#endif // NEWSCREENVIEW_HPP

In "Public" section, I have created two textAreas and two buffer arrays for them so that they can hold different stuff. As far as I remember, buffers are maximum 10 places long (haven't tried longer to be honest, feel free to try, I expect it to trim the text which is too long), and one last character has to be reserved for end of line character when it's put into the TextArea. so if you need 4 places for your text, you'll need an array of length 5.

Nothing stops you from declaring an array of boxes or array of buttons or array of textAreas. I had no problem creating an array of boxes that way,

What's left is to actually add stuff to our NewScreen.cpp, which in my hands looks like this:

#include <gui/newscreen_screen/NewScreenView.hpp>
 
NewScreenView::NewScreenView()
{
 
}
 
void NewScreenView::setupScreen()
{
 NewScreenViewBase::setupScreen();
 
 //CREATING ONE TEXTAREA
 testTextArea.setXY(200, 400);
 testTextArea.setColor(touchgfx::Color::getColorFrom24BitRGB(255, 255, 0));
 testTextArea.setLinespacing(0);
 testTextArea.setWildcard(testTextAreaBuffer);
 testTextArea.setTypedText(touchgfx::TypedText(T_RESOURCEID3));
 Unicode::snprintf(testTextAreaBuffer, 10, "Meow meow");
 testTextArea.resizeToCurrentText();
 add(testTextArea);
 testTextArea.invalidate();
 
 //CREATING SECOND TEXTAREA with the same resource
 testTextArea2.setXY(500, 400);
 testTextArea2.setColor(touchgfx::Color::getColorFrom24BitRGB(255, 255, 0));
 testTextArea2.setLinespacing(0);
 testTextArea2.setWildcard(testTextAreaBuffer2);
 testTextArea2.setTypedText(touchgfx::TypedText(T_RESOURCEID3)); //Same resource as the first TextArea. EXPERIMENT!
 Unicode::snprintf(testTextAreaBuffer2, 10, "Woof woof");
 testTextArea2.resizeToCurrentText();
 add(testTextArea2);
 testTextArea2.invalidate();
}
 
void NewScreenView::tearDownScreen()
{
 NewScreenViewBase::tearDownScreen();
}

 CONTINUES IN REPLY!

ilyus
ilyusAuthor
Senior II
June 30, 2021

Now, I want the textareas to appear on the screen immediately. Nothing stops you from putting the generating code into some other function, of course. Such as after button press. But remember, that you can do "add" only once, otherwise it will crash. Keep it in mind.

I think, most of the code there is pretty easy to read.

Setting the coordinates, then setting color using TouchGFX color, then line spacing.

Then we do .setWildcard to associate a buffer array with the TextArea. It won't immediately produce text on the screen after this function tho, because we haven't hooked up the text formatting yet.

Next we do SetTypedText - the function that took me the longest to understand. This actually IS formatting. You need to add there the Resource ID of the formatting we created earlier - it was ID3. If you don't know what exactly to write there, open "TextKeysAndLanguages.hpp", there is a list of resource IDs, find the one with the number youi created. Notice they are all capitalized even if your resource has a name with small letters (confusing!).

So basically we said "Hey, create me a TextArea, use that array as wildcard's buffer and use that resource for defining font, alignment, direction, position of wildcard, etc.". Our wildcard takes 100% of that.

Next, we do the funny "Unicode::snprintf(testTextAreaBuffer, 10, "Meow meow");" This actually puts the string "Meow meow" into the buffer and adds termination character at the end so you don't have to worry about it. This function actually defines what TextArea shows. "10" is a buffer length. You can have a string of 1 character but have buffer length 10, the function will take care of it.

Then I decided to resize the TextArea, but you can set fixed width of course, it's all in TouchGFX documentation online. I just wanted to see all, since I'm doing proof of concept here.

Then I add textArea to the screen. It could very well be container1.add or something else.

And then invalidate() forces TouchGFX to redraw the widget to make it show up to date content of the buffer. If you want to change the content of TextArea, you do Unicode::snprintf(testTextAreaBuffer, 10, "New Text"); followed by invalidate().

The second TextArea does exactly the same; it has the same Resource but its own buffer array.

I have a semi-opaque background box on the screen, other than that, the result is the following:

0693W00000BcSTfQAN.png 

Congrats, that's it!

March 20, 2023

Beware that

Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%s", touchgfx::TypedText(T_SINGLEUSEID63).getText());

textArea1.setWildcard(textArea1Buffer);

should go strictly BEFORE both of functions

textArea1.resizeToCurrentText();

AND

textArea1.setTypedText(touchgfx::TypedText(T_SINGLEUSEID62));

This is because resizeToCurrentText will also calculate wildcard text's width - and if wildcard's buffer is not initialized with null-terminated string - it will calculate till the first zero somewhere in memory, and can hang or crash.

And setTypedText calls resizeToCurrentText internally with the same effect.