cancel
Showing results for 
Search instead for 
Did you mean: 

Invalidate a listview seems to not invalidate and trigger the update callback

RonaldWerkhoven
Associate

Hi all,

For a project, I made a simple tab structure where I can put all kind of settings, The list is divided under the tabs and shown in 2 list views next to each other. In the class, I have a variable keeping track of the currently selected tab. After clicking a tab button this variable is set to the new tab. I set the number of items for the list views to the amount needed for the number of options and invalidate the list views.

After doing this, if the number of items in the listview did not change, the invalidate will not trigger an updateCallback so the list items will not be updated, and instead, the old items will stay in the view. For now, I solved this by setting the number of items first to 0 and calling the invalidate function before I set the number of items to the correct amount.

Is this expected behavior, or have I run into a bug here?

I attached a screenshot of the view and the code to give you more of an idea of the implementation

Code:

/**
*	Set the selected tab
*	Set the number of items for the list views
*/
void SettingsContainer::setSelectedTab(baulds::settingsTabs tab)
{
	// Set the selected tab internally
	this->selectedTab = tab;

	// Tell the menu controller to set the current scene
	this->menuController->setCurrentScene((int)tab);

	/**
	*	First we set the number of items to 0, this to make sure the invalidate is called
	*	If we set the number of items the same as it already had the invalidate wil not trigger properly
	*/

	SettingsListLeft.setNumberOfItems(0);				
	SettingsListRight.setNumberOfItems(0);
	this->invalidate();

	/**
	*	Set the number of items for the left and right menu
	*/
	SettingsListLeft.setNumberOfItems(this->_getLeftMenuSize());
	SettingsListRight.setNumberOfItems(this->_getRightMenuSize());
	this->invalidate();
}

/**
* Callback for the left menu to update
*/
void SettingsContainer::SettingsListLeftUpdateItem(SettingsContainerItem& item, int16_t itemIndex)
{
	baulds::settingsNode* node = this->settingsController->getSettingByIndex(itemIndex, this->selectedTab);
	if (node != nullptr)
	{
		item.setNode(*node);
	}
}

/**
* callback for the right menu to update
*/
void SettingsContainer::SettingsListRightUpdateItem(SettingsContainerItem& item, int16_t itemIndex)
{
	baulds::settingsNode* node = this->settingsController->getSettingByIndex(this->_getLeftMenuSize() + itemIndex, this->selectedTab);
	if (node != nullptr)
	{
		item.setNode(*node);
	}
}
6 REPLIES 6
GaetanGodart
ST Employee

Hello @RonaldWerkhoven ,

 

What is a listview?

Is it a scrollList or is it a custom creation of yours?

I think we need a bit more context here.
If it is a scrollList, I don't see how your code is relating to it.
If this is a custom creation, I think we will need the whole listview sources.

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)
RonaldWerkhoven
Associate

Hi @GaetanGodart,

This is a default scrollList from touchgfx itself.

What do you mean if you say the code is not related to the issue?

The issue I encounter is on line 25, 26 and 27, I get the number of items for both scrollLists and set the list to this number. After this I invalidate the scrollLists so an update will be triggered (SettingsListLeftUpdateItem & SettingsListRightUpdateItem bound in the SettingsContainerBase.cpp to the updateItemCallbackHandler)

This works without an issue as the size of the scrollLists changes at line 25 and 26, for example the first tab has 3 items in the left scrollList, and the second tab has 2 items. the numberOfItems on line 25 change in the scrollList from 3 to 2 I call the invalidate method and the SettingsListLeftUpdateItem method is called to update the content of the scrollList.

If I switch from the first to the fourth tab, in this case the left list both contain 2 items, so on line 25 the size is set to 2, but the size of the list is already 2. In this case after calling the invalidate on the scrollList the function SettingsListLeftUpdateItem is no longer called so the content of the scrollList is not updated

The workaround I now use for line 18,19 and 20 is to set both lists to a size of 0, invalidate them, and then set the size back to the size the lists need to be, this forces the SettingsListLeftUpdateItem & SettingsListRightUpdateItem to get called and update the content of the scrollLists

Ok, so SettingsListLeft and SettingsListRight are your 2 lists.

What is "this"? Is it your screen? Or a custom container?
You invalidate "this" and I don't think that its size changes if this is a screen or a custom container.
In that case I don't understand why adding the lines 18 to 21 changes anything.

What happens if you try to remove your lines 18 to 21 and add a line to invalidate the whole screen?

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)
RonaldWerkhoven
Associate

Yes, the SettingsListLeft and SettingsListRight are my 2 lists.

In this case, the this-> points to a container that extends from touchgfx::Container, so this should already invalidate the entire screen/ container, Everything I build for this tab system is part of this container

 

I attached 3 screenshots; perhaps this makes it a bit clearer.

The General, Mapping, Device, and About parts are buttons that trigger the setSelectedTab function with a different enum value to switch between the tabs.

Screen_1 is when the screen is shown for the first time,

Expected_screen_2 is when I clicked the about button with line 18 to 21 enabled,

Resulting_behavior, in the left list I get the items from the About page, and in the right list I get the menu items from the General page, This happens when I remove the lines 18 - 21.

 

 

If I add lines 18 to 21 and I click between the 2 tabs, the lists are getting updated the correct way and result in the same behavior as in Expected_screen_2

Hello @RonaldWerkhoven ,

 

Thank you for the extra information.

I am starting to think that the _getLeftMenuSize() function returns an unexpected number.

Can you share that function with us?

Can you try to print/log the result of this function to check that you get what you expect?

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)
RonaldWerkhoven
Associate

Hi,

I checked the value the functions return, I attached the result as screenshots.

The sizes/ values are the values as expected, the functions should always return a uint8_t as the response. The only reason this should not happen / would go wrong is an overflow as far as I can think about, but this is not the issue we experience with the scrollView

The code for both the functions is as follows

/**
* Get the size of the left menu, we ceil this so the left menu is always 1 bigger if the menu size is odd
*/
uint8_t SettingsContainer::_getLeftMenuSize()
{
	return (uint8_t)ceil(this->settingsController->getSettingsCount(this->selectedTab) / 2.0);
}

/**
* Get the size of the right menu, we floor this so the right menu is always 1 smaller if the menu size is odd
*/
uint8_t SettingsContainer::_getRightMenuSize()
{
	return (uint8_t)floor(this->settingsController->getSettingsCount(this->selectedTab) / 2.0);
}

 

In the this->settingsController->getSettingsCount, I loop through a custom-made linked list and count the number of elements with this->selectedTab 

	/**
	* Get the amount of settings for a specific tab
	*/
	uint8_t SettingsController::getSettingsCount(baulds::settingsTabs tabIndex)
	{
		// loop this->settingsList and count the number of settings with the given settingsTabs value
		this->settingsList->reset();
		uint8_t count = 0;
		while (this->settingsList->next())
		{
			settingsNode* node = this->settingsList->current();
			if (node->tabIndex == tabIndex)
			{
				count++;
			}
		}

		return count;
	}