That wouldn't work for the children of children. But making a recursive call down the tree that problem could be solved.
The only reason I can think of to not do it that way would be the issues that come up when you would disable a high level control. Say you had a window with a few buttons, and one of the buttons was disabled. Something happens in the UI and the entire window is disabled for a short period. When the window disabled state is restored, the button that was disabled would be enabled, and that would most likely be bad.
I think a more appropriate solution would be to have a function like
getEnabledAbsolute() that would be used by a control to decide how to render itself. That function would walk up its parent pointer trying to see if one of the ancestor controls was disabled.
Code: Select all
bool IGUIElement_getEnabledAbsolute(IGUIElement* element)
{
for (/**/; element; element = element->getParent())
{
if (!element->getEnabled())
return false;
}
return true;
}
Unfortunately this makes rendering gui elements more expensive because they have to walk the heirarchy every render to see if they are enabled or not.
Another possible option is to keep a few enabled flags. One enabled flag indicates that this control is the one that is enabled, and another indicating that all ancestors are enabled. I think it would look something like this...
Code: Select all
// bit 1 indicates we are enabled
// bit 2 indicates all ancestors are enabled
u8 IsEnabled;
bool ISceneNode::getEnabled() const
{
return (IsEnabled & 3) == 3; // fully enabled
}
void ISceneNode::setEnabled(bool enabled)
{
// set/clear bit indicating this control is enabled
if (enabled)
IsEnabled |= 1;
else
IsEnabled &= ~1;
// tell children that parent is enabled or disabled
core::list<IGUIElement*>::Iterator it = Children.begin();
for (; it != Children.end(); ++it)
(*it)->setEnabledAncestor(enabled);
}
void ISceneNode::setEnabledAncestor(bool enabled)
{
// set/clear bit indicating that ancestor is enabled
if (enabled)
IsEnabled |= 2;
else
IsEnabled &= ~2;
// if ancestor is getting enabled and we are currently disabled don't
// bother updating children states. the child 'ancestor enabled' flag
// will remain false this way.
if (enabled && !(IsEnabled & 1))
return;
core::list<IGUIElement*>::Iterator it = Children.begin();
for (; it != Children.end(); ++it)
(*it)->setEnabledAncestor(enabled);
}
Travis