_addChildWidget and _removeChildWidget

JPro

26-06-2007 17:40:05

It seems to me that these two functions do not work as they should. They add/remove a child widget from the parent widget's mChildWidget's vector, but they fail to update the child widget's parent pointer.

For clarification, I needed to remove an image from one window and add it to another. If I simply did _removeChildWidget(image) and then _addChildWidget(image) to move it from the former parent to the new one, it would still move around as if it were a child of the former parent. A look into the source code of QuickGUIWidget showed that mParentWidget is never changed. This makes it so that when using setPosition(...) in relative mode, the widget moves to its original parent widget's positions, not it's current parent.

To fix this, I edited the following:



void Widget::_addChildWidget(Widget* w)
{
w->setParentWidget(this);
mChildWidgets.push_back(w);
}

void Widget::_removeChildWidget(Widget* w)
{
std::vector<Widget*>::iterator it;
for( it = mChildWidgets.begin(); it != mChildWidgets.end(); ++it )
{
if( (*it)->getInstanceName() == w->getInstanceName() )
{
mChildWidgets.erase(it);
w->setParentWidget(NULL);
break;
}
}
}

void Widget::setParentWidget(Widget* newParent)
{
if(mParentWidget != NULL)
{
getParentWidget()->_removeChildWidget(this);
}
mParentWidget = newParent;
}




Let me know what you think. I have this overriding feeling that I've overlooked something.

kungfoomasta

02-07-2007 07:46:35

Thanks for pointing that out! I never had the scenario where I wanted to move a child widget from one parent to another. I just got back, so I'm a little rusty, but your code looks good to me. Removing a child widget should handle the reference to its parent properly.

I'll add your changes and we can make any modifications if we find problems. Thanks again! :)

kungfoomasta

06-07-2007 08:20:00

Ah, I found a problem.. :(

Currently, when a widget is created and added to another widget, it's zOrder is derived, and the parent window/sheet is notified of this, storing it in a list of zOrders. The problem is that when you set the parent to NULL, you can't traverse through the parents to find the parent window/sheet and remove this zOrder number. Not only that, but if you move a widget X from one parent to another, X could have child widgets of its own. Each of these child widgets would need to notify its parent before being removed, and also use its new parent's zOrder to derive its own, and notify it's parent window/sheet of its zOrder. zOrder is important for mouse picking, for example when widgets overlap.

...doh!

Will take some time to work this one out.. I just tried sorting it out and realized my brain turned off some time ago.. :lol:

kungfoomasta

08-07-2007 04:18:47

Working on a solution..

Adding functions:


/**
* Iterates through children and adds zOrder to parent window/sheet's zOrder list.
* Note: should be called after attaching this widget to a parent widget.
*/
void _attachPostProcessing();



/**
* Iterates through children and removes zOrder from parent window/sheet's zOrder list.
* Note: should be called before detaching this widget from it's parent.
*/
void _detachPreProcessing();


I should also create a bool mIsChildWidget; and bool isChildWidget(), to know if the widget is a child of another widget. (All widgets are child widgets except for the Sheet widget, except when detached (no parent))

kungfoomasta

09-07-2007 23:21:49

The function names I came up with were bothering me, so I thought about it more and came up with a new approach.


/**
* Notifies the parent panel of it's zOrder. If children is true,
* children will notify their parent panel also.
*/
void registerZOrder(bool children = true);

/**
* Notifies and removes zOrder from parent panel.
* If children is true, child widgets will unregister also.
*/
void unregisterZOrder(bool children = true);


Widget::setParentWidget() is added, and everything seems to be working.

I will throw up a version with all my current fixes tonight. :)