xcfw/src/xcfwtree.cpp
changeset 0 79c6a41cd166
equal deleted inserted replaced
-1:000000000000 0:79c6a41cd166
       
     1 /*
       
     2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of XCFW Content tree
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include    "xcfwtree.h"
       
    22 #include    "xcfwnode.h"
       
    23 #include    "xcfwpanic.h"
       
    24 
       
    25 // MACROS
       
    26 //Helper macro to cast MXCFWNode pointers to CXCFWNode
       
    27 #define WRAPNODE( aNode ) static_cast<CXCFWNode*>( aNode )
       
    28 
       
    29 // ============================ MEMBER FUNCTIONS ===============================
       
    30 
       
    31 // -----------------------------------------------------------------------------
       
    32 // CXCFWTree::CXCFWTree
       
    33 // C++ default constructor can NOT contain any code, that
       
    34 // might leave.
       
    35 // -----------------------------------------------------------------------------
       
    36 //
       
    37 CXCFWTree::CXCFWTree()
       
    38     {
       
    39     }
       
    40 
       
    41 // -----------------------------------------------------------------------------
       
    42 // CXCFWTree::ConstructL
       
    43 // Symbian 2nd phase constructor can leave.
       
    44 // -----------------------------------------------------------------------------
       
    45 //
       
    46 void CXCFWTree::ConstructL()
       
    47     {
       
    48     }
       
    49 
       
    50 // -----------------------------------------------------------------------------
       
    51 // CXCFWTree::NewL
       
    52 // Two-phased constructor.
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 EXPORT_C CXCFWTree* CXCFWTree::NewL()
       
    56     {
       
    57     CXCFWTree* self = new( ELeave ) CXCFWTree;
       
    58     
       
    59     CleanupStack::PushL( self );
       
    60     self->ConstructL();
       
    61     CleanupStack::Pop( self );
       
    62 
       
    63     return self;
       
    64     }
       
    65 
       
    66     
       
    67 // Destructor
       
    68 EXPORT_C CXCFWTree::~CXCFWTree()
       
    69     {
       
    70     //delete dtd name buffer
       
    71     delete iDTDName;
       
    72     
       
    73     //delete node array    
       
    74     iNodeList.ResetAndDestroy();
       
    75     iNodeList.Close();
       
    76     
       
    77     //reset node array for client
       
    78     iNodeListForClient.Reset();
       
    79     iNodeListForClient.Close();
       
    80     
       
    81     //Null root pointer (owned in the iNodeList array)
       
    82     iRoot = NULL;
       
    83     }
       
    84 
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // CXCFWTree::AddNodeL
       
    88 // this overload is for adding node under certain parent before certain child
       
    89 // -----------------------------------------------------------------------------
       
    90 //
       
    91 EXPORT_C MXCFWNode* CXCFWTree::AddNodeL(
       
    92     CGECOObjectBase* aData, 
       
    93     MXCFWNode* aParent, 
       
    94     MXCFWNode* aInsertBefore )
       
    95     {
       
    96     CleanupStack::PushL( aData );
       
    97     __ASSERT_LEAVE( aParent && aData && aInsertBefore &&
       
    98         aData->TypeIdentifier() != iRoot->Data()->TypeIdentifier() &&
       
    99         aInsertBefore->Parent() == aParent, KErrArgument );
       
   100 
       
   101     __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
       
   102     
       
   103     //Create new node and add to arrays.
       
   104     CXCFWNode* nodeToAdd = CXCFWNode::NewL( aData );
       
   105     CleanupStack::Pop( aData );
       
   106     CleanupStack::PushL( nodeToAdd );
       
   107     User::LeaveIfError( iNodeList.Append( nodeToAdd ) );
       
   108     CleanupStack::Pop( nodeToAdd );
       
   109 
       
   110     //update node references
       
   111     nodeToAdd->SetParent( aParent );
       
   112     nodeToAdd->SetNextSibling( aInsertBefore );
       
   113     nodeToAdd->SetPrevSibling( aInsertBefore->PrevSibling() );
       
   114         
       
   115     //if "insert before" -node has previous sibling, update that
       
   116     if ( aInsertBefore->PrevSibling() )
       
   117         {
       
   118         WRAPNODE( aInsertBefore->PrevSibling() )->SetNextSibling( nodeToAdd );
       
   119         }
       
   120 
       
   121     //set previous sibling
       
   122     WRAPNODE( aInsertBefore )->SetPrevSibling( nodeToAdd );            
       
   123 
       
   124     if( aParent->FirstChild() == aInsertBefore )
       
   125         {
       
   126         WRAPNODE( aParent )->SetFirstChild( nodeToAdd );            
       
   127         }
       
   128 
       
   129     //Set client list dirty => will be updated on next Nodes() request.
       
   130     iClientListDirty = ETrue;
       
   131     
       
   132     return nodeToAdd;
       
   133 
       
   134     }
       
   135 
       
   136 // -----------------------------------------------------------------------------
       
   137 // CXCFWTree::AddNodeL
       
   138 // this overload is for adding node under certain parent as last child
       
   139 // -----------------------------------------------------------------------------
       
   140 //
       
   141 EXPORT_C MXCFWNode* CXCFWTree::AddNodeL(
       
   142     CGECOObjectBase* aData, 
       
   143     MXCFWNode* aParent )
       
   144     {
       
   145     CleanupStack::PushL( aData );
       
   146     //Legality checks
       
   147     __ASSERT_LEAVE( aParent && aData && 
       
   148          aData->TypeIdentifier() != iRoot->Data()->TypeIdentifier(),
       
   149          KErrArgument );
       
   150 
       
   151     __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
       
   152 
       
   153 
       
   154     //Create new node and add to arrays
       
   155     CXCFWNode* nodeToAdd = CXCFWNode::NewL( aData );
       
   156     CleanupStack::Pop( aData );
       
   157     CleanupStack::PushL( nodeToAdd );
       
   158     User::LeaveIfError( iNodeList.Append( nodeToAdd ) );
       
   159     CleanupStack::Pop( nodeToAdd );
       
   160 
       
   161     //set parent for new node
       
   162     nodeToAdd->SetParent( aParent );
       
   163 
       
   164     //if parent has a last child
       
   165     if( aParent->LastChild() )
       
   166         {
       
   167         nodeToAdd->SetPrevSibling( aParent->LastChild() );
       
   168         WRAPNODE( aParent->LastChild() )->SetNextSibling( nodeToAdd );
       
   169         }
       
   170     else
       
   171         {
       
   172         WRAPNODE( aParent )->SetFirstChild( nodeToAdd );
       
   173         }
       
   174 
       
   175     //update last child of the parent        
       
   176     WRAPNODE( aParent )->SetLastChild( nodeToAdd );        
       
   177 
       
   178     //Set client list dirty => will be updated on next Nodes() request.
       
   179     iClientListDirty = ETrue;
       
   180 
       
   181     return nodeToAdd;        
       
   182     }
       
   183 
       
   184 // -----------------------------------------------------------------------------
       
   185 // CXCFWTree::AddNodeL
       
   186 // this overload is for adding root node only
       
   187 // -----------------------------------------------------------------------------
       
   188 //
       
   189 EXPORT_C MXCFWNode* CXCFWTree::AddNodeL(
       
   190     CGECOObjectBase* aData )
       
   191     {
       
   192     CleanupStack::PushL( aData );
       
   193     //if we already have a root, this is illegal
       
   194     __ASSERT_LEAVE( iRoot==NULL, KErrAlreadyExists );
       
   195 
       
   196     __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
       
   197 
       
   198     //Create root node and add to arrays
       
   199     CXCFWNode* nodeToAdd = CXCFWNode::NewL( aData );
       
   200     CleanupStack::Pop( aData );
       
   201     CleanupStack::PushL( nodeToAdd );
       
   202     User::LeaveIfError( iNodeList.Append( nodeToAdd ) );
       
   203     CleanupStack::Pop( nodeToAdd );
       
   204 
       
   205     //Set internal root member.
       
   206     iRoot = nodeToAdd;
       
   207     nodeToAdd = NULL;
       
   208 
       
   209     //Set client list dirty => will be updated on next Nodes() request.
       
   210     iClientListDirty = ETrue;
       
   211 
       
   212     return iRoot;
       
   213     }
       
   214 
       
   215 // -----------------------------------------------------------------------------
       
   216 // CXCFWTree::GetChildNodesL
       
   217 // Put child nodes of the given parent to the given array
       
   218 // -----------------------------------------------------------------------------
       
   219 //
       
   220 EXPORT_C void CXCFWTree::GetChildNodesL(
       
   221     MXCFWNode* aParent, 
       
   222     RNodeArray& aNodeList)
       
   223     {
       
   224     
       
   225     __ASSERT_LEAVE( aParent != NULL, KErrArgument );
       
   226     
       
   227     MXCFWNode* pointer = aParent->FirstChild();
       
   228     while ( pointer )
       
   229         {
       
   230         User::LeaveIfError( aNodeList.Append( pointer ) );
       
   231         pointer = pointer->NextSibling();
       
   232         }
       
   233 
       
   234     }
       
   235 
       
   236 // -----------------------------------------------------------------------------
       
   237 // CXCFWTree::GetNodesOfTypeL
       
   238 // Put nodes that have dataobject of given type to given array.
       
   239 // In case of recursion, pre-order recursion is used
       
   240 // -----------------------------------------------------------------------------
       
   241 //
       
   242 EXPORT_C void CXCFWTree::GetNodesOfTypeL( 
       
   243     const TDesC& aType, 
       
   244     RNodeArray& aNodeList, 
       
   245     MXCFWNode* aParent, 
       
   246     TBool aRecursive )
       
   247     {
       
   248 
       
   249     __ASSERT_LEAVE( aParent != NULL, KErrArgument );
       
   250 
       
   251     MXCFWNode* pointer = aParent->FirstChild();
       
   252     
       
   253     while ( pointer )
       
   254         {
       
   255         if ( pointer->Data()->TypeIdentifier().Compare( aType ) == 0 )
       
   256             {
       
   257             User::LeaveIfError( aNodeList.Append( pointer ) );                
       
   258             }
       
   259         if ( aRecursive )
       
   260             {
       
   261             GetNodesOfTypeL( aType, aNodeList, pointer, aRecursive );                
       
   262             }
       
   263         pointer = pointer->NextSibling();
       
   264         }
       
   265 
       
   266     }
       
   267 
       
   268 // -----------------------------------------------------------------------------
       
   269 // CXCFWTree::MoveNodeL
       
   270 // Moves a node in tree and updates the relative nodes in both original and
       
   271 // new location.
       
   272 // -----------------------------------------------------------------------------
       
   273 //
       
   274 EXPORT_C void CXCFWTree::MoveNodeL(
       
   275     MXCFWNode* aNodeToMove, 
       
   276     MXCFWNode* aNewParent, 
       
   277     MXCFWNode* aInsertBefore )
       
   278     {
       
   279 
       
   280     // assure parameter legality
       
   281     __ASSERT_LEAVE( aNodeToMove && aNewParent && 
       
   282         aNodeToMove != iRoot && aInsertBefore != iRoot &&
       
   283         aNodeToMove != aNewParent,
       
   284         KErrArgument );            
       
   285 
       
   286     __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
       
   287 
       
   288 
       
   289     //if "insert before" node is child node of the given parent, move is illegal
       
   290     if ( aInsertBefore && aInsertBefore->Parent() != aNewParent )
       
   291         {
       
   292         User::Leave( KErrArgument );            
       
   293         }
       
   294     
       
   295     MXCFWNode* check = aNewParent->Parent();
       
   296     while ( check )
       
   297         {
       
   298         //if user tries to move a node under itself (it is among the parents 
       
   299         // of the given new parent) we'll leave
       
   300         if ( check == aNodeToMove )
       
   301             {
       
   302             User::Leave( KErrArgument );
       
   303             }
       
   304         check = check->Parent();
       
   305         }
       
   306     check = NULL;
       
   307     
       
   308     //first update old parent if necessary
       
   309     if ( aNodeToMove->Parent()->FirstChild() == aNodeToMove )
       
   310         {
       
   311         WRAPNODE( aNodeToMove->Parent() )->SetFirstChild( 
       
   312                                 aNodeToMove->NextSibling() );            
       
   313         }
       
   314     if ( aNodeToMove->Parent()->LastChild() == aNodeToMove )
       
   315         {
       
   316         WRAPNODE( aNodeToMove->Parent() )->SetLastChild(
       
   317                                    aNodeToMove->PrevSibling() );            
       
   318         }
       
   319     
       
   320     //update old siblings
       
   321     if ( aNodeToMove->PrevSibling() )
       
   322         {
       
   323         WRAPNODE( aNodeToMove->PrevSibling())->SetNextSibling(
       
   324                                 aNodeToMove->NextSibling() );            
       
   325         }
       
   326     
       
   327     if ( aNodeToMove->NextSibling() )
       
   328         {
       
   329         WRAPNODE( aNodeToMove->NextSibling() )->SetPrevSibling( 
       
   330                                 aNodeToMove->PrevSibling() );            
       
   331         }
       
   332         
       
   333     //set new parent:
       
   334     WRAPNODE( aNodeToMove )->SetParent( aNewParent );
       
   335     
       
   336     //update new siblings
       
   337     if ( aInsertBefore )
       
   338         {
       
   339 
       
   340         //if "insert before" -node has a sibling before it, we update that
       
   341         if ( aInsertBefore->PrevSibling() )
       
   342             {
       
   343             WRAPNODE( aInsertBefore->PrevSibling() )->SetNextSibling(
       
   344                                 aNodeToMove );                
       
   345             }
       
   346         else 
       
   347         //no previous sibling => insertbefore is the first child of new parent
       
   348             {
       
   349             WRAPNODE( aNewParent )->SetFirstChild( aNodeToMove );                
       
   350             }
       
   351         WRAPNODE( aNodeToMove )->SetPrevSibling( aInsertBefore->PrevSibling() );
       
   352         WRAPNODE( aNodeToMove )->SetNextSibling( aInsertBefore );
       
   353         WRAPNODE( aInsertBefore )->SetPrevSibling( aNodeToMove );
       
   354         }
       
   355     else
       
   356         {
       
   357         //if new parent had children
       
   358         if ( aNewParent->LastChild() )
       
   359             {
       
   360             WRAPNODE( aNewParent->LastChild() )->SetNextSibling( aNodeToMove );
       
   361             WRAPNODE( aNodeToMove )->SetPrevSibling( aNewParent->LastChild() );
       
   362             WRAPNODE( aNewParent )->SetLastChild( aNodeToMove );
       
   363             WRAPNODE( aNodeToMove )->SetNextSibling(NULL);
       
   364             }
       
   365         else //no children before
       
   366             {
       
   367             WRAPNODE( aNewParent )->SetFirstChild( aNodeToMove );
       
   368             WRAPNODE( aNewParent )->SetLastChild( aNodeToMove );
       
   369             WRAPNODE( aNodeToMove )->SetPrevSibling( NULL );
       
   370             WRAPNODE( aNodeToMove )->SetNextSibling( NULL );            
       
   371             }
       
   372         }
       
   373 
       
   374     //Set client list dirty => will be updated on next Nodes() request.
       
   375     iClientListDirty = ETrue;
       
   376 
       
   377     }
       
   378         
       
   379 // -----------------------------------------------------------------------------
       
   380 // CXCFWTree::Nodes
       
   381 // return tree nodes as array of MXCFWNode pointers
       
   382 // -----------------------------------------------------------------------------
       
   383 //
       
   384 EXPORT_C RNodeArray& CXCFWTree::Nodes()
       
   385     {
       
   386 
       
   387     //see if we should update the MXCFWNode array to reflect the new
       
   388     if ( iClientListDirty )
       
   389         {
       
   390 
       
   391         if ( iNodeListForClient.Count() > 0 )
       
   392             {
       
   393             iNodeListForClient.Reset();
       
   394             }
       
   395 
       
   396         TInt count = iNodeList.Count();
       
   397         for ( TInt i = 0; i < count; i++ )
       
   398             {
       
   399             iNodeListForClient.Append( (MXCFWNode*)iNodeList[i] );           
       
   400             }
       
   401         iClientListDirty = EFalse;
       
   402         }
       
   403 
       
   404     return iNodeListForClient;
       
   405     }
       
   406 
       
   407         
       
   408 // -----------------------------------------------------------------------------
       
   409 // CXCFWTree::RemoveNodeL
       
   410 // Removes a node from tree by updating all relative nodes and removing from
       
   411 // arrays.
       
   412 // -----------------------------------------------------------------------------
       
   413 //
       
   414 EXPORT_C void CXCFWTree::RemoveNodeL(
       
   415     MXCFWNode* aNodeToRemove )
       
   416     {
       
   417 
       
   418     __ASSERT_LEAVE( aNodeToRemove != NULL, KErrArgument );
       
   419 
       
   420     __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
       
   421     
       
   422     if ( iRoot != aNodeToRemove )
       
   423         {
       
   424         //update related nodes before removal, unless removing root node.
       
   425         if ( aNodeToRemove->PrevSibling() )
       
   426             {
       
   427             WRAPNODE( aNodeToRemove->PrevSibling() )->SetNextSibling(
       
   428                                     aNodeToRemove->NextSibling() );            
       
   429             }
       
   430         
       
   431         if ( aNodeToRemove->NextSibling() )
       
   432             {
       
   433             WRAPNODE( aNodeToRemove->NextSibling() )->SetPrevSibling( 
       
   434                                     aNodeToRemove->PrevSibling() );    
       
   435             }
       
   436 
       
   437         if ( aNodeToRemove->Parent()->FirstChild() == aNodeToRemove )
       
   438             {
       
   439             WRAPNODE( aNodeToRemove->Parent() )->SetFirstChild( 
       
   440                                     aNodeToRemove->NextSibling() );            
       
   441             }
       
   442         
       
   443         if ( aNodeToRemove->Parent()->LastChild() == aNodeToRemove )
       
   444             {
       
   445             WRAPNODE( aNodeToRemove->Parent() )->SetLastChild( 
       
   446                                     aNodeToRemove->PrevSibling() );            
       
   447             }
       
   448         }
       
   449     else
       
   450         {
       
   451         //root was removed.
       
   452         iRoot = NULL;            
       
   453         }
       
   454 
       
   455     //Set client list dirty => will be updated on next Nodes() request.
       
   456     iClientListDirty = ETrue;
       
   457     
       
   458     RemoveNodeRecursiveL( aNodeToRemove );
       
   459 
       
   460     }
       
   461 
       
   462 
       
   463 // -----------------------------------------------------------------------------
       
   464 // CXCFWTree::RemoveFromArray
       
   465 // Removes node pointer from CXCFWNode and MXCFWNode pointer arrays. 
       
   466 // Deletes from CXCFWNode array as well.
       
   467 // -----------------------------------------------------------------------------
       
   468 //
       
   469 void CXCFWTree::RemoveFromNodeList(
       
   470     MXCFWNode* aNode )
       
   471     {
       
   472 
       
   473     //remove node from the pointer array.
       
   474     TInt i = iNodeList.Count() - 1 ;
       
   475     for ( ;i>=0 && aNode != iNodeList[i] ; i-- ){}
       
   476     if ( i>=0 )
       
   477         {
       
   478         //delete object
       
   479         delete iNodeList[i];
       
   480         //remove from pointer arrays.
       
   481         iNodeList.Remove(i);
       
   482         }
       
   483 
       
   484     }
       
   485 
       
   486 // -----------------------------------------------------------------------------
       
   487 // CXCFWTree::RemoveNodeRecursiveL
       
   488 // Post-order recursion is used to make sure that no orhpan nodes are left
       
   489 // floating.
       
   490 // -----------------------------------------------------------------------------
       
   491 //
       
   492 void CXCFWTree::RemoveNodeRecursiveL(
       
   493     MXCFWNode* aNode )
       
   494     {
       
   495 
       
   496     __ASSERT_LEAVE ( aNode != NULL, KErrArgument );
       
   497 
       
   498     MXCFWNode* pointer = aNode->FirstChild();
       
   499     
       
   500     while ( pointer )
       
   501         {
       
   502         MXCFWNode* temp = pointer->NextSibling();
       
   503         RemoveNodeRecursiveL( pointer );
       
   504         pointer = temp;            
       
   505         }
       
   506 
       
   507     RemoveFromNodeList( aNode );
       
   508     
       
   509     }
       
   510 
       
   511 
       
   512 // -----------------------------------------------------------------------------
       
   513 // CXCFWTree::Root
       
   514 // Returns MXCFWNode pointer to root node.
       
   515 // -----------------------------------------------------------------------------
       
   516 //
       
   517 EXPORT_C MXCFWNode* CXCFWTree::Root()
       
   518     {
       
   519     return iRoot;
       
   520     }
       
   521 
       
   522 EXPORT_C void CXCFWTree::SetLocked( TBool aLockStatus )
       
   523     {
       
   524     iLocked = aLockStatus;
       
   525     }
       
   526 
       
   527 EXPORT_C TBool CXCFWTree::IsLocked()
       
   528     {
       
   529     return iLocked;
       
   530     }
       
   531 
       
   532 const TDesC& CXCFWTree::DTDName()
       
   533     {
       
   534     if ( !iDTDName )
       
   535         {
       
   536         return KNullDesC;
       
   537         }
       
   538     else
       
   539         {
       
   540         return *iDTDName;        
       
   541         }
       
   542     }
       
   543 
       
   544 void CXCFWTree::SetDTDNameL( const TDesC& aName )
       
   545     {
       
   546     delete iDTDName;
       
   547     iDTDName = NULL;
       
   548     iDTDName = aName.AllocL();        
       
   549     }
       
   550 
       
   551 //  End of File