/***************************************************************************** This may delete one or more rows depending on the makeup of the tree branch. It's analagous to deleting a file directory with all files and sub-directories deleted, too. *****************************************************************************/ int CTreeColumn::DeleteTreeBranch( int aiRow, // Row that the tree branch begins on BOOL abRedraw) // T=redraw; F=don't // returns: nbr of rows deleted { ASSERT( aiRow >= -1); ASSERT( m_pGrid != NULL); // Must call TreeSetup(), first if( aiRow < m_iFixedRowCount || aiRow >= m_iRowCount) return 0; int iRowDeleteCount = 0; m_bAllowDraw = FALSE; // prevents crash during reset // get level of initial row to delete from tree CGridTreeCell* pGridTreeCell = (CGridTreeCell*)m_pGrid->GetCell( aiRow, m_iColumnWithTree); unsigned char ucLevelCurrent = CHAR_MAX; if( pGridTreeCell != NULL) { // delete just the parent ucLevelCurrent = pGridTreeCell->GetLevel(); if( m_pGrid->DeleteRow( aiRow) ) { iRowDeleteCount++; m_iRowCount--; } } // see if any children need to be deleted, too unsigned char ucLevel; while( aiRow < m_iRowCount) { pGridTreeCell = (CGridTreeCell*)m_pGrid->GetCell( aiRow, m_iColumnWithTree); if( pGridTreeCell == NULL) break; ucLevel = pGridTreeCell->GetLevel(); if( ucLevel <= ucLevelCurrent) break; if( !m_pGrid->DeleteRow( aiRow) ) break; iRowDeleteCount++; m_iRowCount--; } ASSERT( m_iRowCount == m_pGrid->GetRowCount() ); // have to re-number all cells below deletion point if( iRowDeleteCount > 0) { int iRow; int iColumnCount = m_pGrid->GetColumnCount(); for( iRow=aiRow; iRow < m_iRowCount; iRow++) { int iCol; for (iCol = 0; iCol < iColumnCount; iCol++) { CGridCellBase* pGridCellBase = m_pGrid->GetCell( iRow, iCol); if( pGridCellBase != NULL) { pGridCellBase->SetCoords( iRow, iCol); } } } } m_bAllowDraw = TRUE; TreeRefreshRows(); if( abRedraw) m_pGrid->Invalidate(); return iRowDeleteCount; }
/***************************************************************************** 3/2001: Allows one to add to the existing tree structure. Repeatedly calling TreeSetup() with different tree configurations was the only way to change the tree structure with the original implementation, but had the disadvantage of destroying cell contents. The original implementation forced you to NOT store data directly in grid cells if you wished to change the tree. No validation of the tree branch "levels" done. Drawing code assumes a parent / child relationship of tree nodes. Thus, if the lines of the tree don't look right, make sure that the parent / child relationship is not violated. *****************************************************************************/ int CTreeColumn::InsertTreeBranch( const unsigned char* apucTreeLevelAry, // Tree Level data array -- // must have aiNbrElements of entries int aiNbrElements, // NUmber of tree elements to add int aiRow, // insert tree elements beginning at this row // If -1, append to end; If 0, Insert // at top no matter how many fixed rows BOOL abRedraw) // T=redraw; F=don't // returns: row where elements inserted; -1 on error { ASSERT( apucTreeLevelAry != NULL); ASSERT( aiNbrElements >= 0); ASSERT( aiRow >= -1); ASSERT( m_pGrid != NULL); // Must call TreeSetup(), first ASSERT( m_iFixedRowCount >= 0); ASSERT( m_pRuntimeClassTreeCell != NULL); if( aiNbrElements <= 0) return -1; // if user specified 0 or -1, adjust int iRowForAppend = 0; if( m_iRowCount <= m_iFixedRowCount) aiRow = -1; // if no non-fixed rows, then gotta append if( aiRow <= -1) { iRowForAppend = -1; aiRow = m_iRowCount; } else if( aiRow < m_iFixedRowCount) aiRow = m_iFixedRowCount; m_bAllowDraw = FALSE; // prevents crash during reset // retain old cell properties: establishes size for // tree drawing box based on current font CGridTreeCell GridCellCopy; GridCellCopy.SetTreeColumn( this); CGridCellBase* pCurrCell = m_pGrid->GetCell( m_iRowCount-1, m_iColumnWithTree); if (pCurrCell) GridCellCopy = *pCurrCell; // insert rows while replacing tree column cells to tree cell type int iCellRow = aiRow; int i1; for( i1=0; i1 < aiNbrElements; i1++) { // CGridCtrl's InsertRow() requires a -1 to append values to // the end of the grid if( iRowForAppend != -1) iRowForAppend = iCellRow; if( m_pGrid->InsertRow( "", iRowForAppend) < 0) { aiRow = -1; // error break; } if( !m_pGrid->SetCellType( iCellRow, m_iColumnWithTree, m_pRuntimeClassTreeCell ) ) { aiRow = -1; // error break; } CGridTreeCell* pGridTreeCell = (CGridTreeCell*)m_pGrid->GetCell( iCellRow, m_iColumnWithTree); if( pGridTreeCell != NULL) { pGridTreeCell->SetTreeColumn( this); pGridTreeCell->SetLevelAndHide( *apucTreeLevelAry ); pGridTreeCell->SetViewable( TRUE); } iCellRow++; m_iRowCount++; apucTreeLevelAry++; } ASSERT( m_iRowCount == m_pGrid->GetRowCount() ); // have to re-number all cells below insertion point if( aiRow > 0) { int iRow; int iColumnCount = m_pGrid->GetColumnCount(); for( iRow=iCellRow; iRow < m_iRowCount; iRow++) { int iCol; for (iCol = 0; iCol < iColumnCount; iCol++) { CGridCellBase* pGridCellBase = m_pGrid->GetCell( iRow, iCol); if( pGridCellBase != NULL) { pGridCellBase->SetCoords( iRow, iCol); } } } } m_bAllowDraw = TRUE; TreeRefreshRows(); if( abRedraw) m_pGrid->Invalidate(); return aiRow; }