cancel
Showing results for 
Search instead for 
Did you mean: 

Can I make a global warning window?

Wrend.1
Senior

I want to display a ​warning window when a single triggered from hardware.

It seems that if I want to achieve this effect in touchGFX, I need to add a model window to each interface. Can I add a global window to implement it elegantly?:face_without_mouth:

1 ACCEPTED SOLUTION

Accepted Solutions
Michael K
Senior III

If you are triggering a warning from hardware, I assume you want to call this function from the Model.cpp file.

I've accomplished this by creating a BaseLayer custom container with all elements common to all screens (such as warning modals) having their code defined within. This BaseLayer is added to all screens. I register a pointer in Model.cpp to the current instance of the BaseLayer. Then when I need the modal, I (carefully) call the function directly from the Model to the BaseLayer. This BaseLayer pointer needs to be updated every time it is instantiated or destroyed (i.e. every screen change), and nullptr checks need to be done in Model.cpp before it is used otherwise you risk a hardfault.

Here's how to do it:

  1. Create a "BaseLayer" custom container. Any common elements you need on all screens should be added here (such as your modal window).
  2. Create a method in BaseLayer that pops up your warning window.
  3. Create a global Model pointer in Model.cpp.
  4. Define a member pointer of type BaseLayer* in Model.hpp
  5. In Model::Model() constructor, set the BaseLayer pointer to nullptr, and set your Model pointer to this
  6. In your BaseLayer code, create an extern Model* reference.
  7. In your BaseLayer::BaseLayer() constructor, register this instance of the BaseLayer in the Model by setting the model's BaseLayer pointer to this (via the extern Model pointer)
  8. Create a BaseLayer::~BaseLayer() destructor, and in it make sure to reset that BaseLayer pointer in Model back to nullptr (again via the extern Model pointer)
  9. When your hardware event happens in your Model.cpp code, check if the BaseLayer pointer is null and if not, call the function that displays the modal.

It's not really "elegant" insofar as it doesn't follow the MVP pattern. However, I tried following the MVP pattern and calling a modellistener function to alert the presenters to call a view method to call a BaseLayer method... it's way too much hassle. Breaking the "rules" and selectively using a global pointer from the model to the baselayer is much easier as long as it is used sparingly and carefully.

Hope this helps. I've heard rumors of "Template Screens" coming in future TGFX versions.

View solution in original post

2 REPLIES 2
Michael K
Senior III

If you are triggering a warning from hardware, I assume you want to call this function from the Model.cpp file.

I've accomplished this by creating a BaseLayer custom container with all elements common to all screens (such as warning modals) having their code defined within. This BaseLayer is added to all screens. I register a pointer in Model.cpp to the current instance of the BaseLayer. Then when I need the modal, I (carefully) call the function directly from the Model to the BaseLayer. This BaseLayer pointer needs to be updated every time it is instantiated or destroyed (i.e. every screen change), and nullptr checks need to be done in Model.cpp before it is used otherwise you risk a hardfault.

Here's how to do it:

  1. Create a "BaseLayer" custom container. Any common elements you need on all screens should be added here (such as your modal window).
  2. Create a method in BaseLayer that pops up your warning window.
  3. Create a global Model pointer in Model.cpp.
  4. Define a member pointer of type BaseLayer* in Model.hpp
  5. In Model::Model() constructor, set the BaseLayer pointer to nullptr, and set your Model pointer to this
  6. In your BaseLayer code, create an extern Model* reference.
  7. In your BaseLayer::BaseLayer() constructor, register this instance of the BaseLayer in the Model by setting the model's BaseLayer pointer to this (via the extern Model pointer)
  8. Create a BaseLayer::~BaseLayer() destructor, and in it make sure to reset that BaseLayer pointer in Model back to nullptr (again via the extern Model pointer)
  9. When your hardware event happens in your Model.cpp code, check if the BaseLayer pointer is null and if not, call the function that displays the modal.

It's not really "elegant" insofar as it doesn't follow the MVP pattern. However, I tried following the MVP pattern and calling a modellistener function to alert the presenters to call a view method to call a BaseLayer method... it's way too much hassle. Breaking the "rules" and selectively using a global pointer from the model to the baselayer is much easier as long as it is used sparingly and carefully.

Hope this helps. I've heard rumors of "Template Screens" coming in future TGFX versions.

VKost.1
Associate II

My solution to this problem is to use a "static" instance of the container I need to show on top of the current screen and put it into FrontendHeap class.

class FrontendHeap: public FrontendHeapBase {
pubilc:
...
    ErrorsWindowTop errorsWindowTop;
}

This way you have an instance of the container (global window) that's created with the application and you can access it from every view and put it on the top:

Container& root = FrontendApplication::getInstance()->getCurrentScreen()->getRootContainer();
root.add(FrontendHeap::getInstance().errorsWindowTop);
root.invalidate();

The function for putting a Top containet looks like this:

bool Model::addTopContainer(Drawable& d) {
	FrontendApplication* app = FrontendApplication::getInstance();
	if (!app->getTransition()->isDone())
		return false;
 
	Container& root = app->getCurrentScreen()->getRootContainer();
 
	if (root.contains(d))
		return false;
 
	d.resetParent();
	root.add(d);
	root.invalidate();
 
	app->registerTimerWidget(&d);
 
	return true;
}

I've added a method to Drawable class to reset the parent as otherwise it messes up the hierarchy:

void Drawable::resetParent() {
	parent = nullptr;
}