cancel
Showing results for 
Search instead for 
Did you mean: 

How on EARTH do you change the text in the "textarea" programatically?????

LoyalServant
Associate II

As the subject says. searches over many hours have resulted in several different ways to do this, none of which work.

The CLOSEST ive gotten to a reaction out of a textbox outsode of some event is to break the rules, and *** with the autogenerated code. All that resulted in was getting the box to change to "??" which as crazy as it sounds, progress, because I have yet to figure out what methods to call to do this seemingly simple thing.

From the documentation:

 

touchgfx::Unicode::strncpy(textArea1Buffer, "string", TEXTAREA1_SIZE);
textArea1.resizeToCurrentText(); // optional, will resize the box to fit the text if it is too small
textArea1.invalidate();

 

This does absolutely nothing.

 

Again, from the documentation: 

 

// With int/double/UnicodeChar*
touchgfx::Unicode::snprintf(textArea1Buffer,TEXTAREA1_SIZE,"My numbers %i %i", my_var_1, my_var_2 );
// With float
touchgfx::Unicode::snprintfFloat(textArea1Buffer,TEXTAREA1_SIZE,"My float %f", my_var_float );
textArea1.invalidate();

 

 This does absolutely nothing.

 

And, again, from the documentation:

 

const uint8_t* Mystring = (const uint8_t*)"봉쥬르";
Unicode::fromUTF8(Mystring, textArea1Buffer, TEXTAREA1_SIZE);
textArea1.invalidate();

 

This does absolutely nothing.

 

What DOES SOMETHING outside of trying to change it in a 'tick' event is breaking the rules and changing the generated code but results in "??" being displayed:

 

testTextArea.setPosition(9, 47, 803, 124);
    testTextArea.setColor(touchgfx::Color::getColorFromRGB(255, 255, 255));
    testTextArea.setLinespacing(0);
    Unicode::snprintf(testTextAreaBuffer, TESTTEXTAREA_SIZE, "%s", "because i should not do this\0");//touchgfx::TypedText(T___SINGLEUSE_OYIT).getText());
    testTextArea.setWildcard(testTextAreaBuffer);
    testTextArea.setTypedText(touchgfx::TypedText(T___SINGLEUSE_ZPMF));
    add(testTextArea);

 

 

What *SORT OF WORKS* but it's as hoaky as all getout.

 

"...View.cpp":
void ServiceView::handleTickEvent()
{
	touchgfx::Unicode::strncpy(testTextAreaBuffer, TestTextBuffer, TESTTEXTAREA_SIZE);
	testTextArea.resizeToCurrentText();
	testTextArea.invalidate();
}

"...View.hpp":
Public:
virtual void handleTickEvent();
Unicode::UnicodeChar TestTextBuffer[50];

In some other place, like fired from main.c wrapped up in a function declared extern "C" in "...View.hpp/cpp":

Unicode::strncpy(TestTextBuffer, "This is a test", sizeof(TestTextBuffer) / sizeof(Unicode::UnicodeChar));

 

But this results in "T?is is a test", for example.

Or depending on the string I enter in there, some characters having a question mark in them.

Which leads me to some troubling observations that I can't see being correct...

1. All updates seem to have to happen in this tick event? That can't be.
2. Because of the above, which I can't believe is true.... I have to maintain some flag for each text item to make sure that it's not firing off a change *every single time* this tick is fired at whatever frequency it is fired.

How on earth is this supposed to be done? Do we REALLY have to change stuff in a "tick" event?? And why am i getting the seemingly random question marks? I need to change this from C... from events that occur based on either a hardware state change or something coming in via a data bus, etc.

What's the secret? Thanks all.

 

8 REPLIES 8
LouisB
ST Employee

Hello @LoyalServant,

 

touchgfx::Unicode::strncpy(textArea1Buffer, "string", TEXTAREA1_SIZE);
textArea1.resizeToCurrentText(); // optional, will resize the box to fit the text if it is too small
textArea1.invalidate();


Should work, have you setup your wildcards and the wildcard buffer in designer ?

BR,

Louis BOUDO
ST Software Developer | TouchGFX

Hi Louis,

What I have found out this weekend via studying or experimentation is that if I do ALL changes in handleTickEvent() then the world is good.

Let's say for the sake of argument that I have an rtos task and I have some C function that updates a textbox as you give an example of. Except it's got to determine what screen it is first so there is some logic first like....

auto* frontendApp = static_cast<FrontendApplication* (touchgfx::Application::getInstance());
Screen* currentScreen = frontendApp->getCurrentScreen();

Now I have the screen... so I can cast it to the class that it should be and so on...

Side question: We don't have RTTI so we can't get runtime information to know which screen is active. Is there a way to know which screen it is?

Anyhow now we have the screen so we go ahead and update the buffers. Except that nothing happens. It doesn't crash. It just doesn't change anything. So what I have done is declare some variables in the 'view' class, set them in the task, and a flag so that the 'tick' event doesnt update the screen every tick, but only once, and then use those to update the ones tied to the widget. That works, and it's the only thing that has worked. 

Honestly I don't know what goes on down in the bowels, just that any updates from "outside" - like from the C side of things doesn't work for me and I don't know if that's intended.

 

Michael K
Senior III

The steps I would take are:

  1. Create a TextArea widget in the Designer.
  2. Add a wildcard to the TextArea by pressing the + icon underneath the "translation" entry in the properties pane.
  3. Enable the wildcard buffer and set the size
  4. Go to the Texts->Typographies tab (left pane of the Designer), select the font your TextArea uses, and enter 0x0-0x255 to the Wildcard Ranges box. This will force TouchGFX to generate the bitmap data for all the ascii characters of this font, otherwise you get question marks.
  5. In your code, call touchgfx::Unicode::strncpy(textArea1Buffer, "The text you want", TEXTAREA1_SIZE); and then textArea1.invalidate();

I made a video demonstrating this process if you are interested: TouchGFX Wildcards

You also mention RTOS tasks. Here's how I would handle that:

  • Create a virtual method with an empty implementation in ModelListener.hpp called, e.g.

 

virtual void onNewText(){}

 

  • Handle the RTOS queue in the Model::tick() function. If a message with a new string appears, store it in char buffer that is a member function of the model()

 

class Model{
...
public:
char backendBuffer[64];
...
}

 

  • then, in the r call:

 

modelListener->onNewText();

 

  •  On however many screens you need to react to the text, implement something like 

 

Screen1View::setText(char * string){
touchgfx::Unicode::strncpy(textArea1Buffer, string, TEXTAREA1_SIZE); 
textArea1.invalidate();
}

 

  •  On each screen's presenter, create the following function:

 

Screen1Presenter::onNewText(){
view.setText(model->backendBuffer);
}

 

 Note that onNewText is the same as the Model Listener function. When the model calls this function, any presenter that has overridden onNewText in this way will be called. No need to figure out what screen is active or use externs.

Embedded UI/UX Consulting: cadenza.design

Very impressive tutorial.

LoyalServant
Associate II

Thanks. Going to watch your video.
Let me give all of this a shot and see where it lands me.

 

 

LoyalServant
Associate II

Ok, so I see where we are going with this.

In my case none of the screens will share the same text in any way, so I need to know what screen is active and that eludes me. Besides me keeping track of it myself somehow... so this concept won't work in my case.

The wildcard bit makes sense tho so I appreciate that.

I still have to populate EVERYTHING in handletickevent() or it goes sideways and simply doesn't work. This is after taking a fresh look at this, and concluding this is the only way it works for me. No other methods work.

LoyalServant
Associate II

Ok, so I did some more fiddling and I realised that I shot myself in the foot.

Order of events obviously matters. I was changing screens and I was setting a text value in the model to "bubble up" to the screen, which was happening after setting the text value. Obviously it can't paint the text value, then the screen over it...

I think my fundamental misunderstanding here is how it works, so I am going to try to work at this incrementally and take a dive into the stuff in the 'generated' directory to see whats under the hood a little more.

Appreciate the information, and the linked video did help me understand the 'wildcard' stuff a bit more.

 

You're right, the Model can't know exactly which type of View and Presenter is active at a time, but it does have a pointer to a ModelListener interface and all Presenters inherit from the ModelListener. Under the hood, TouchGFX will swap the modelListener pointer to point to the active presenter whenever the screen changes.

If you have a message you'd like to send to a Presenter (for example when a button was pressed) you can add an empty implementation to the ModelListener header. Then, in any screen where it's relevant, you can override the implementation in the Presenter. In your Presenter implementation, you can gather data from the model, and then call methods from the View to take action. 

For all the screens it's not relevant, don't override the method, and the empty implementation will be called and nothing will happen.

I'll be releasing a video this weekend on communication from the Model to the Views.

Embedded UI/UX Consulting: cadenza.design