void GraphComponent::removeChild( GraphComponentPtr child ) { if( child->m_parent!=this ) { throw Exception( "Object is not a child." ); } if( refCount() ) { // someone is pointing to us, so we may have a ScriptNode ancestor and we should do things // in an undoable way. Action::enact( this, // ok to bind raw pointers to this, because enact() guarantees // the lifetime of the subject. boost::bind( &GraphComponent::removeChildInternal, this, child, true ), boost::bind( &GraphComponent::addChildInternal, this, child, child->index() ) ); } else { // we have no references to us - chances are we're in construction still. adding ourselves to an // undo queue is impossible, and creating temporary smart pointers to ourselves (as above) will // cause our destruction before construction completes. just do the work directly. removeChildInternal( child, true ); } }
void GraphComponent::addChild( GraphComponentPtr child ) { if( child->m_parent==this ) { return; } throwIfChildRejected( child.get() ); if( refCount() ) { // someone is pointing to us, so we may have a ScriptNode ancestor and we should do things // in an undoable way. figure out what our undo function should be - it varies based on what // the previous parent was. Action::Function undoFn; if( child->m_parent ) { if( child->m_parent->isInstanceOf( (IECore::TypeId)ScriptNodeTypeId ) ) { // use raw pointer to avoid circular reference between script and undo queue undoFn = boost::bind( &GraphComponent::addChildInternal, child->m_parent, child, child->index() ); } else { // use smart pointer to ensure parent remains alive, even if something unscrupulous // messes it with non-undoable actions that aren't stored in the undo queue. undoFn = boost::bind( &GraphComponent::addChildInternal, GraphComponentPtr( child->m_parent ), child, child->index() ); } } else { // no previous parent. undoFn = boost::bind( &GraphComponent::removeChildInternal, this, child, true ); } Action::enact( this, // ok to use raw pointer for this - lifetime of subject guaranteed. boost::bind( &GraphComponent::addChildInternal, this, child, m_children.size() ), undoFn ); } else { // we have no references to us - chances are we're in construction still. adding ourselves to an // undo queue is impossible, and creating temporary smart pointers to ourselves (as above) will // cause our destruction before construction completes. just do the work directly. addChildInternal( child, m_children.size() ); } }