Forum
Please
Log In
to post a new message or reply to an existing one. If you are not registered, please
register.
NOTE: Some forums may be read-only if you are not currently subscribed to
our technical support services.
Subject |
Author |
Date |
|
Rado Manzela
|
May 23, 2007 - 10:22 AM
|
I’ve made recursive function for sorting tree grid items based on the ItemSortChildren() function. The problem is that ItemSortChildren() function expands the sorted items. How can I avoid this? (I’m sorting all items including their children by selected column but need to preserve expand status of tree). It seems to be inefficient to remember expand state of sorted node and restore it after sort. Is it necessary to expand the node in prof-uis library while sorting? Thank you.
|
|
Technical Support
|
May 24, 2007 - 4:31 AM
|
Thank you for reporting us this issue. The following updated method fixes the problem. CExtTreeGridCellNode * CExtTreeGridDataProvider::_Tree_NodeCopyMove(
CExtTreeGridCellNode * pNodeCopyMove,
CExtTreeGridCellNode * pNodeNewParent, // if NULL - root
ULONG nIdxInsertBefore, // = (ULONG(-1)) // if (ULONG(-1)) - insert to end
bool bMove, // = true
bool bCloneOnMove, // = true
bool bCloneCellObjects, // = true
INT nExpandAction, // = TVE_TOGGLE // TVE_TOGGLE in this case - keep expanded state
bool bEnableCopyingIntoInnerBranch, // = true
bool * p_bCopyingIntoInnerBranch // = NULL
)
{
ASSERT_VALID( this );
if( bMove )
bEnableCopyingIntoInnerBranch = false;
bool bCopyingIntoInnerBranch = false;
bool bCopyMoveTestRetVal =
_Tree_NodeCopyMoveTest(
pNodeCopyMove,
pNodeNewParent,
nIdxInsertBefore,
bEnableCopyingIntoInnerBranch,
&bCopyingIntoInnerBranch
);
if( p_bCopyingIntoInnerBranch != NULL )
(*p_bCopyingIntoInnerBranch) = bCopyingIntoInnerBranch;
if( ! bCopyMoveTestRetVal )
return NULL;
ASSERT_VALID( pNodeCopyMove );
CExtTreeGridCellNode * pNodeRoot = _Tree_NodeGetRoot();
ASSERT_VALID( pNodeRoot );
if( pNodeNewParent == NULL )
pNodeNewParent = pNodeRoot;
ASSERT_VALID( pNodeNewParent );
ULONG nTargetParentSiblingCount = pNodeNewParent->TreeNodeGetChildCount();
if( nIdxInsertBefore == ULONG(-1L)
|| nIdxInsertBefore > nTargetParentSiblingCount
)
nIdxInsertBefore = nTargetParentSiblingCount;
CExtTreeGridCellNode * pNodeRetVal = NULL;
if( bMove && ( ! bCloneOnMove ) )
{
bool b1 = pNodeCopyMove->TreeNodeIsExpanded();
bool b2 = pNodeNewParent->TreeNodeIsExpanded();
if( ! b1 )
_Tree_NodeExpand( pNodeCopyMove, TVE_EXPAND );
if( ! b2 )
_Tree_NodeExpand( pNodeNewParent, TVE_EXPAND );
if( _Tree_NodeMoveImpl(
pNodeCopyMove,
pNodeNewParent,
nIdxInsertBefore,
nExpandAction
)
)
pNodeRetVal = pNodeCopyMove;
if( ! b1 )
_Tree_NodeExpand( pNodeCopyMove, TVE_COLLAPSE );
if( ! b2 )
_Tree_NodeExpand( pNodeNewParent, TVE_COLLAPSE );
}
else
pNodeRetVal =
_Tree_NodeCopyImpl(
pNodeCopyMove,
pNodeNewParent,
NULL,
nIdxInsertBefore,
nExpandAction,
bCloneCellObjects
);
if( pNodeRetVal == NULL )
return NULL;
ASSERT_VALID( pNodeRetVal );
if( bMove && bCloneOnMove )
_Tree_NodeRemove( pNodeCopyMove );
return pNodeRetVal;
} We used this project for testing.
|
|
Rado Manzela
|
May 24, 2007 - 5:52 AM
|
|
|
Technical Support
|
May 26, 2007 - 10:25 AM
|
We have just improved the code to perform deep sorting without losing expanded row states and without expanding/collapsing while sorting. Please update the source code for the following two methods: CExtTreeGridCellNode * CExtTreeGridDataProvider::_Tree_NodeCopyMove(
CExtTreeGridCellNode * pNodeCopyMove,
CExtTreeGridCellNode * pNodeNewParent, // if NULL - root
ULONG nIdxInsertBefore, // = (ULONG(-1)) // if (ULONG(-1)) - insert to end
bool bMove, // = true
bool bCloneOnMove, // = true
bool bCloneCellObjects, // = true
INT nExpandAction, // = TVE_TOGGLE // TVE_TOGGLE in this case - keep expanded state
bool bEnableCopyingIntoInnerBranch, // = true
bool * p_bCopyingIntoInnerBranch // = NULL
)
{
ASSERT_VALID( this );
if( bMove )
bEnableCopyingIntoInnerBranch = false;
bool bCopyingIntoInnerBranch = false;
bool bCopyMoveTestRetVal =
_Tree_NodeCopyMoveTest(
pNodeCopyMove,
pNodeNewParent,
nIdxInsertBefore,
bEnableCopyingIntoInnerBranch,
&bCopyingIntoInnerBranch
);
if( p_bCopyingIntoInnerBranch != NULL )
(*p_bCopyingIntoInnerBranch) = bCopyingIntoInnerBranch;
if( ! bCopyMoveTestRetVal )
return NULL;
ASSERT_VALID( pNodeCopyMove );
CExtTreeGridCellNode * pNodeRoot = _Tree_NodeGetRoot();
ASSERT_VALID( pNodeRoot );
if( pNodeNewParent == NULL )
pNodeNewParent = pNodeRoot;
ASSERT_VALID( pNodeNewParent );
ULONG nTargetParentSiblingCount = pNodeNewParent->TreeNodeGetChildCount();
if( nIdxInsertBefore == ULONG(-1L)
|| nIdxInsertBefore > nTargetParentSiblingCount
)
nIdxInsertBefore = nTargetParentSiblingCount;
CExtTreeGridCellNode * pNodeRetVal = NULL;
if( bMove && ( ! bCloneOnMove ) )
{
if( _Tree_NodeMoveImpl(
pNodeCopyMove,
pNodeNewParent,
nIdxInsertBefore,
nExpandAction
)
)
pNodeRetVal = pNodeCopyMove;
}
else
pNodeRetVal =
_Tree_NodeCopyImpl(
pNodeCopyMove,
pNodeNewParent,
NULL,
nIdxInsertBefore,
nExpandAction,
bCloneCellObjects
);
if( pNodeRetVal == NULL )
return NULL;
ASSERT_VALID( pNodeRetVal );
if( bMove && bCloneOnMove )
_Tree_NodeRemove( pNodeCopyMove );
return pNodeRetVal;
}
bool CExtTreeGridDataProvider::_Tree_NodeMoveImpl(
CExtTreeGridCellNode * pNodeCopyMove,
CExtTreeGridCellNode * pNodeNewParent,
ULONG nIdxInsertBefore,
INT nExpandAction
)
{
ASSERT_VALID( this );
ASSERT_VALID( pNodeCopyMove );
ASSERT_VALID( pNodeNewParent );
nExpandAction;
ULONG nIndex;
CExtTreeGridCellNode * pNode = NULL;
bool b3 = pNodeCopyMove->TreeNodeIsDisplayed();
bool b4 = pNodeNewParent->TreeNodeIsDisplayed() && pNodeNewParent->TreeNodeIsExpanded();
if( ! ( ( b3 && b4 ) || ( (!b3) && (!b4) ) ) )
{
ASSERT( FALSE );
return false;
}
if( b3 )
{
CExtTreeGridCellNode * pNodeRoot = TreeNodeGetRoot();
ASSERT_VALID( pNodeRoot );
ASSERT( pNodeCopyMove != pNodeRoot );
pNode = pNodeCopyMove->TreeNodeGetParent();
ASSERT_VALID( pNode );
for( ; LPCVOID(pNodeRoot) != LPCVOID(pNode); )
{
TreeNodeExpand( pNode, TVE_EXPAND );
pNode = pNode->TreeNodeGetParent();
ASSERT_VALID( pNode );
} // for( ; LPCVOID(pNodeRoot) == LPCVOID(pNode); )
pNode = pNodeNewParent;
for( ; LPCVOID(pNodeRoot) != LPCVOID(pNode); )
{
TreeNodeExpand( pNode, TVE_EXPAND );
pNode = pNode->TreeNodeGetParent();
ASSERT_VALID( pNode );
} // for( ; LPCVOID(pNodeRoot) == LPCVOID(pNode); )
}
CExtTreeGridCellNode * pNodeOldParent = pNodeCopyMove->m_pNodeParent;
ASSERT_VALID( pNodeOldParent );
ULONG nOldOptIndex = pNodeCopyMove->TreeNodeGetSiblingIndex();
ULONG nTargetChildrenCount = pNodeNewParent->TreeNodeGetChildCount();
ASSERT( nIdxInsertBefore <= nTargetChildrenCount );
CExtTreeGridCellNode * pNodeTargetCalc = NULL;
if( nIdxInsertBefore == nTargetChildrenCount )
pNodeTargetCalc = pNodeNewParent;
else
pNodeTargetCalc = pNodeNewParent->TreeNodeGetChildAt( nIdxInsertBefore );
ULONG nExpandedOffsetSrc = pNodeCopyMove->TreeNodeCalcOffset( true );
ULONG nPhysicalOffsetSrc = pNodeCopyMove->TreeNodeCalcOffset( false );
ULONG nExpandedOffsetDst = pNodeTargetCalc->TreeNodeCalcOffset( true );
ULONG nPhysicalOffsetDst = pNodeTargetCalc->TreeNodeCalcOffset( false );
ULONG nMoveWeightExpanded = pNodeCopyMove->_ContentWeight_Get( true ) + 1;
ULONG nMoveWeightPhysical = pNodeCopyMove->_ContentWeight_Get( false ) + 1;
if( nIdxInsertBefore == nTargetChildrenCount )
{
nExpandedOffsetDst += pNodeTargetCalc->_ContentWeight_Get( true ) + 1;
nPhysicalOffsetDst += pNodeTargetCalc->_ContentWeight_Get( false ) + 1;
}
CExtTreeGridCellNode::NodeArr_t _arrNodes;
if( b3 )
{
_arrNodes.SetSize( nMoveWeightExpanded );
for( nIndex = 0; nIndex < nMoveWeightExpanded; nIndex ++ )
{
pNode = m_arrGridVis[ nExpandedOffsetSrc + nIndex ];
ASSERT_VALID( pNode );
_arrNodes.SetAt( nIndex, pNode );
}
m_arrGridVis.RemoveAt( nExpandedOffsetSrc, nMoveWeightExpanded );
ULONG _nExpandedOffsetDst = nExpandedOffsetDst;
if( _nExpandedOffsetDst > nExpandedOffsetSrc )
_nExpandedOffsetDst -= nMoveWeightExpanded;
m_arrGridVis.InsertAt( _nExpandedOffsetDst, &_arrNodes );
}
_arrNodes.SetSize( nMoveWeightPhysical );
for( nIndex = 0; nIndex < nMoveWeightPhysical; nIndex ++ )
{
pNode = m_arrGridRef[ nPhysicalOffsetSrc + nIndex ];
ASSERT_VALID( pNode );
_arrNodes.SetAt( nIndex, pNode );
}
m_arrGridRef.RemoveAt( nPhysicalOffsetSrc, nMoveWeightPhysical );
ULONG _nPhysicalOffsetDst = nPhysicalOffsetDst;
if( _nPhysicalOffsetDst > nPhysicalOffsetSrc )
_nPhysicalOffsetDst -= nMoveWeightPhysical;
m_arrGridRef.InsertAt( _nPhysicalOffsetDst, &_arrNodes );
ULONG nReservedRowCount = 0L;
m_DP.CacheReservedCountsGet( NULL, &nReservedRowCount );
nPhysicalOffsetSrc += nReservedRowCount;
nPhysicalOffsetDst += nReservedRowCount;
LONG nTmp = 0;
for( nIndex = 0; nIndex < nMoveWeightPhysical; nIndex ++ )
{
if( nPhysicalOffsetSrc < nPhysicalOffsetDst )
{
ULONG nOffsetSrc = nPhysicalOffsetSrc + nMoveWeightPhysical - 1 - nIndex;
ULONG nOffsetDst = nPhysicalOffsetDst + nMoveWeightPhysical - 1 - nIndex;
for( ; nOffsetSrc != nOffsetDst; )
{
m_DP._SortSwapSeries(
nOffsetSrc,
nOffsetSrc + 1,
nTmp,
NULL,
false
);
nOffsetSrc ++;
}
}
else
{
ULONG nOffsetSrc = nPhysicalOffsetSrc + nIndex;
ULONG nOffsetDst = nPhysicalOffsetDst + nIndex;
for( ; nOffsetSrc != nOffsetDst; )
{
m_DP._SortSwapSeries(
nOffsetSrc,
nOffsetSrc - 1,
nTmp,
NULL,
false
);
nOffsetSrc --;
}
}
}
CExtTreeGridCellNode * pNodePrev = pNodeCopyMove->m_pNodePrev;
CExtTreeGridCellNode * pNodeNext = pNodeCopyMove->m_pNodeNext;
if( pNodePrev != NULL )
{
ASSERT_VALID( pNodePrev );
pNodePrev->m_pNodeNext = pNodeNext;
}
if( pNodeNext != NULL )
{
ASSERT_VALID( pNodeNext );
pNodeNext->m_pNodePrev = pNodePrev;
}
pNodeCopyMove->m_pNodePrev = pNodeCopyMove->m_pNodeNext = NULL;
if( nIdxInsertBefore == nTargetChildrenCount )
{
if( nTargetChildrenCount > 0 )
{
pNode = pNodeNewParent->TreeNodeGetLastChild();
ASSERT_VALID( pNode );
ASSERT( pNode->m_pNodeNext == NULL );
pNode->m_pNodeNext = pNodeCopyMove;
pNodeCopyMove->m_pNodePrev = pNode;
}
}
else
{
pNodeCopyMove->m_pNodeNext = pNodeTargetCalc;
pNodeCopyMove->m_pNodePrev = pNodeTargetCalc->m_pNodePrev;
if( pNodeCopyMove->m_pNodePrev != NULL )
{
ASSERT_VALID( pNodeCopyMove->m_pNodePrev );
pNodeCopyMove->m_pNodePrev->m_pNodeNext = pNodeCopyMove;
}
if( pNodeCopyMove->m_pNodeNext != NULL )
{
ASSERT_VALID( pNodeCopyMove->m_pNodeNext );
pNodeCopyMove->m_pNodeNext->m_pNodePrev = pNodeCopyMove;
}
}
if( LPVOID(pNodeNewParent) != LPVOID(pNodeOldParent) )
{
pNodeOldParent->m_arrChildren.RemoveAt( nOldOptIndex, 1 );
ULONG nStartIndex = nOldOptIndex;
ULONG nEndIndex = ULONG( pNodeOldParent->m_arrChildren.GetSize() );
for( nIndex = nStartIndex; nIndex < nEndIndex; nIndex ++ )
{
pNode = pNodeOldParent->m_arrChildren[ nIndex ];
ASSERT_VALID( pNode );
pNode->m_nOptIndex = nIndex;
}
pNodeNewParent->m_arrChildren.InsertAt( nIdxInsertBefore, pNodeCopyMove, 1 );
nStartIndex = nIdxInsertBefore;
nEndIndex = ULONG( pNodeNewParent->m_arrChildren.GetSize() );
for( nIndex = nStartIndex; nIndex < nEndIndex; nIndex ++ )
{
pNode = pNodeNewParent->m_arrChildren[ nIndex ];
ASSERT_VALID( pNode );
pNode->m_nOptIndex = nIndex;
}
for( pNode = pNodeOldParent; pNode != NULL && pNode->TreeNodeIsExpanded(); pNode = pNode->m_pNodeParent )
{
pNode->m_nContentWeightAll -= nMoveWeightPhysical;
pNode->m_nContentWeightExpanded -= nMoveWeightExpanded;
}
for( pNode = pNodeNewParent; pNode != NULL && pNode->TreeNodeIsExpanded(); pNode = pNode->m_pNodeParent )
{
pNode->m_nContentWeightAll += nMoveWeightPhysical;
pNode->m_nContentWeightExpanded += nMoveWeightExpanded;
}
}
else
{
pNodeOldParent->m_arrChildren.RemoveAt( nOldOptIndex, 1 );
ULONG _nIdxInsertBefore = nIdxInsertBefore;
if( _nIdxInsertBefore >= nOldOptIndex )
_nIdxInsertBefore --;
pNodeOldParent->m_arrChildren.InsertAt( _nIdxInsertBefore , pNodeCopyMove, 1 );
ULONG nStartIndex = min( nOldOptIndex, nIdxInsertBefore );
ULONG nEndIndex = ( max( nOldOptIndex, nIdxInsertBefore ) ) + 1;
if( nEndIndex >= ULONG(pNodeOldParent->m_arrChildren.GetSize()) )
nEndIndex = ULONG(pNodeOldParent->m_arrChildren.GetSize()) - 1;
for( nIndex = nStartIndex; nIndex <= nEndIndex; nIndex ++ )
{
pNode = pNodeOldParent->m_arrChildren[ nIndex ];
ASSERT_VALID( pNode );
pNode->m_nOptIndex = nIndex;
}
}
return true;
}
|
|