Somehow the problem was me calling resizeToCurrentText() function of TextArea.
Let me show you my whole Model.cpp
The line 59 is the line 52 here. Where I call something from debugWidgetPointer.
#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>
#include <gui/containers/Header.hpp>
#include <gui/containers/Debug.hpp>
#include <gui/common/FrontendApplication.hpp>
#include <ButtonEnum.hpp>
Model::Model() : modelListener(0) {
}
uint16_t Model::getButtonState(uint8_t buttonNum)
{
uint16_t buttonState = 0x0000;
HC165_CLK_GPIO_Port->ODR |= (HC165_CLK_Pin);
HC165_EN_GPIO_Port->ODR &= ~(HC165_EN_Pin);
HC165_EN_GPIO_Port->ODR |= (HC165_EN_Pin);
for(int i = 0; i < buttonNum; i++)
{
HC165_CLK_GPIO_Port->ODR &= ~(HC165_CLK_Pin);
if(HC165_MISO_GPIO_Port->IDR & (1<<5))
buttonState &= ~(1 << i);
else
buttonState |= (1 << i);
HC165_CLK_GPIO_Port->ODR |= (HC165_CLK_Pin);
}
return buttonState;
}
uint8_t Model::getBatteryLevel()
{
return rand() % 101; // Return random battery level between 0-100
}
void Model::tick()
{
tickCount++;
if (headerPointer != nullptr && tickCount % 10 == 0)
{
uint8_t batteryLevel = getBatteryLevel();
debugWidgetPointer->setText(batteryLevel);
headerPointer->setBatteryLevel(batteryLevel);
}
uint16_t buttonState = getButtonState(16);
if (buttonState != previousButtonState)
{
if (modelListener != 0)
{
modelListener->onButtonStateChange(buttonState);
}
if (debugWidgetPointer != nullptr)
{
debugWidgetPointer->onButtonStateChange(buttonState);
}
if (static_cast<ButtonEnum>(buttonState) == ButtonEnum::MENU)
{
static_cast<FrontendApplication*>(Application::getInstance())->gotoScreen2ScreenNoTransition();
}
previousButtonState = buttonState;
}
}
I have a custom container called Debug that I add to every scene using TouchGFX UI. Then when a scene is loaded, it's presenter sends that container's pointer to model using a bind method in ModelListener:
#ifndef MODELLISTENER_HPP
#define MODELLISTENER_HPP
#include <gui/model/Model.hpp>
#include <mvp/View.hpp>
#include <touchgfx/hal/Types.hpp>
class ModelListener
{
public:
ModelListener() : model(0) {}
virtual ~ModelListener() {}
void bind(Model* m)
{
model = m;
}
virtual void onButtonStateChange(uint16_t newButtonState) {}
template<typename T>
void bindCommonComponents(touchgfx::View<T>& view) {
Debug* debug = static_cast<Debug*>(view.getDebugWidgetPointer());
Header* header = static_cast<Header*>(view.getHeaderPointer());
model->debugWidgetPointer = debug;
model->headerPointer = header;
}
protected:
Model* model;
};
#endif // MODELLISTENER_HPP
Looks like if I forget to implement the call for this bind function, the debugWidgetPointer is not null but simply points to a weird place (I guess?) and cause unexpected results. I think the only thing I need is a way to nullify these pointers when a screen change happens. Do we have a single place that is called everytime screen changes? Preferably somewere that can access modellistener or model?
EDIT: I tried to nullify them in modellistener's constructor but the code still exits if I don't bind the pointer.