xcfw/src/xcfwtree.cpp
changeset 0 79c6a41cd166
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xcfw/src/xcfwtree.cpp	Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,551 @@
+/*
+* Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implementation of XCFW Content tree
+*
+*/
+
+
+
+// INCLUDE FILES
+#include    "xcfwtree.h"
+#include    "xcfwnode.h"
+#include    "xcfwpanic.h"
+
+// MACROS
+//Helper macro to cast MXCFWNode pointers to CXCFWNode
+#define WRAPNODE( aNode ) static_cast<CXCFWNode*>( aNode )
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::CXCFWTree
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CXCFWTree::CXCFWTree()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CXCFWTree::ConstructL()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CXCFWTree* CXCFWTree::NewL()
+    {
+    CXCFWTree* self = new( ELeave ) CXCFWTree;
+    
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+    
+// Destructor
+EXPORT_C CXCFWTree::~CXCFWTree()
+    {
+    //delete dtd name buffer
+    delete iDTDName;
+    
+    //delete node array    
+    iNodeList.ResetAndDestroy();
+    iNodeList.Close();
+    
+    //reset node array for client
+    iNodeListForClient.Reset();
+    iNodeListForClient.Close();
+    
+    //Null root pointer (owned in the iNodeList array)
+    iRoot = NULL;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::AddNodeL
+// this overload is for adding node under certain parent before certain child
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MXCFWNode* CXCFWTree::AddNodeL(
+    CGECOObjectBase* aData, 
+    MXCFWNode* aParent, 
+    MXCFWNode* aInsertBefore )
+    {
+    CleanupStack::PushL( aData );
+    __ASSERT_LEAVE( aParent && aData && aInsertBefore &&
+        aData->TypeIdentifier() != iRoot->Data()->TypeIdentifier() &&
+        aInsertBefore->Parent() == aParent, KErrArgument );
+
+    __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
+    
+    //Create new node and add to arrays.
+    CXCFWNode* nodeToAdd = CXCFWNode::NewL( aData );
+    CleanupStack::Pop( aData );
+    CleanupStack::PushL( nodeToAdd );
+    User::LeaveIfError( iNodeList.Append( nodeToAdd ) );
+    CleanupStack::Pop( nodeToAdd );
+
+    //update node references
+    nodeToAdd->SetParent( aParent );
+    nodeToAdd->SetNextSibling( aInsertBefore );
+    nodeToAdd->SetPrevSibling( aInsertBefore->PrevSibling() );
+        
+    //if "insert before" -node has previous sibling, update that
+    if ( aInsertBefore->PrevSibling() )
+        {
+        WRAPNODE( aInsertBefore->PrevSibling() )->SetNextSibling( nodeToAdd );
+        }
+
+    //set previous sibling
+    WRAPNODE( aInsertBefore )->SetPrevSibling( nodeToAdd );            
+
+    if( aParent->FirstChild() == aInsertBefore )
+        {
+        WRAPNODE( aParent )->SetFirstChild( nodeToAdd );            
+        }
+
+    //Set client list dirty => will be updated on next Nodes() request.
+    iClientListDirty = ETrue;
+    
+    return nodeToAdd;
+
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::AddNodeL
+// this overload is for adding node under certain parent as last child
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MXCFWNode* CXCFWTree::AddNodeL(
+    CGECOObjectBase* aData, 
+    MXCFWNode* aParent )
+    {
+    CleanupStack::PushL( aData );
+    //Legality checks
+    __ASSERT_LEAVE( aParent && aData && 
+         aData->TypeIdentifier() != iRoot->Data()->TypeIdentifier(),
+         KErrArgument );
+
+    __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
+
+
+    //Create new node and add to arrays
+    CXCFWNode* nodeToAdd = CXCFWNode::NewL( aData );
+    CleanupStack::Pop( aData );
+    CleanupStack::PushL( nodeToAdd );
+    User::LeaveIfError( iNodeList.Append( nodeToAdd ) );
+    CleanupStack::Pop( nodeToAdd );
+
+    //set parent for new node
+    nodeToAdd->SetParent( aParent );
+
+    //if parent has a last child
+    if( aParent->LastChild() )
+        {
+        nodeToAdd->SetPrevSibling( aParent->LastChild() );
+        WRAPNODE( aParent->LastChild() )->SetNextSibling( nodeToAdd );
+        }
+    else
+        {
+        WRAPNODE( aParent )->SetFirstChild( nodeToAdd );
+        }
+
+    //update last child of the parent        
+    WRAPNODE( aParent )->SetLastChild( nodeToAdd );        
+
+    //Set client list dirty => will be updated on next Nodes() request.
+    iClientListDirty = ETrue;
+
+    return nodeToAdd;        
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::AddNodeL
+// this overload is for adding root node only
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MXCFWNode* CXCFWTree::AddNodeL(
+    CGECOObjectBase* aData )
+    {
+    CleanupStack::PushL( aData );
+    //if we already have a root, this is illegal
+    __ASSERT_LEAVE( iRoot==NULL, KErrAlreadyExists );
+
+    __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
+
+    //Create root node and add to arrays
+    CXCFWNode* nodeToAdd = CXCFWNode::NewL( aData );
+    CleanupStack::Pop( aData );
+    CleanupStack::PushL( nodeToAdd );
+    User::LeaveIfError( iNodeList.Append( nodeToAdd ) );
+    CleanupStack::Pop( nodeToAdd );
+
+    //Set internal root member.
+    iRoot = nodeToAdd;
+    nodeToAdd = NULL;
+
+    //Set client list dirty => will be updated on next Nodes() request.
+    iClientListDirty = ETrue;
+
+    return iRoot;
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::GetChildNodesL
+// Put child nodes of the given parent to the given array
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CXCFWTree::GetChildNodesL(
+    MXCFWNode* aParent, 
+    RNodeArray& aNodeList)
+    {
+    
+    __ASSERT_LEAVE( aParent != NULL, KErrArgument );
+    
+    MXCFWNode* pointer = aParent->FirstChild();
+    while ( pointer )
+        {
+        User::LeaveIfError( aNodeList.Append( pointer ) );
+        pointer = pointer->NextSibling();
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::GetNodesOfTypeL
+// Put nodes that have dataobject of given type to given array.
+// In case of recursion, pre-order recursion is used
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CXCFWTree::GetNodesOfTypeL( 
+    const TDesC& aType, 
+    RNodeArray& aNodeList, 
+    MXCFWNode* aParent, 
+    TBool aRecursive )
+    {
+
+    __ASSERT_LEAVE( aParent != NULL, KErrArgument );
+
+    MXCFWNode* pointer = aParent->FirstChild();
+    
+    while ( pointer )
+        {
+        if ( pointer->Data()->TypeIdentifier().Compare( aType ) == 0 )
+            {
+            User::LeaveIfError( aNodeList.Append( pointer ) );                
+            }
+        if ( aRecursive )
+            {
+            GetNodesOfTypeL( aType, aNodeList, pointer, aRecursive );                
+            }
+        pointer = pointer->NextSibling();
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::MoveNodeL
+// Moves a node in tree and updates the relative nodes in both original and
+// new location.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CXCFWTree::MoveNodeL(
+    MXCFWNode* aNodeToMove, 
+    MXCFWNode* aNewParent, 
+    MXCFWNode* aInsertBefore )
+    {
+
+    // assure parameter legality
+    __ASSERT_LEAVE( aNodeToMove && aNewParent && 
+        aNodeToMove != iRoot && aInsertBefore != iRoot &&
+        aNodeToMove != aNewParent,
+        KErrArgument );            
+
+    __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
+
+
+    //if "insert before" node is child node of the given parent, move is illegal
+    if ( aInsertBefore && aInsertBefore->Parent() != aNewParent )
+        {
+        User::Leave( KErrArgument );            
+        }
+    
+    MXCFWNode* check = aNewParent->Parent();
+    while ( check )
+        {
+        //if user tries to move a node under itself (it is among the parents 
+        // of the given new parent) we'll leave
+        if ( check == aNodeToMove )
+            {
+            User::Leave( KErrArgument );
+            }
+        check = check->Parent();
+        }
+    check = NULL;
+    
+    //first update old parent if necessary
+    if ( aNodeToMove->Parent()->FirstChild() == aNodeToMove )
+        {
+        WRAPNODE( aNodeToMove->Parent() )->SetFirstChild( 
+                                aNodeToMove->NextSibling() );            
+        }
+    if ( aNodeToMove->Parent()->LastChild() == aNodeToMove )
+        {
+        WRAPNODE( aNodeToMove->Parent() )->SetLastChild(
+                                   aNodeToMove->PrevSibling() );            
+        }
+    
+    //update old siblings
+    if ( aNodeToMove->PrevSibling() )
+        {
+        WRAPNODE( aNodeToMove->PrevSibling())->SetNextSibling(
+                                aNodeToMove->NextSibling() );            
+        }
+    
+    if ( aNodeToMove->NextSibling() )
+        {
+        WRAPNODE( aNodeToMove->NextSibling() )->SetPrevSibling( 
+                                aNodeToMove->PrevSibling() );            
+        }
+        
+    //set new parent:
+    WRAPNODE( aNodeToMove )->SetParent( aNewParent );
+    
+    //update new siblings
+    if ( aInsertBefore )
+        {
+
+        //if "insert before" -node has a sibling before it, we update that
+        if ( aInsertBefore->PrevSibling() )
+            {
+            WRAPNODE( aInsertBefore->PrevSibling() )->SetNextSibling(
+                                aNodeToMove );                
+            }
+        else 
+        //no previous sibling => insertbefore is the first child of new parent
+            {
+            WRAPNODE( aNewParent )->SetFirstChild( aNodeToMove );                
+            }
+        WRAPNODE( aNodeToMove )->SetPrevSibling( aInsertBefore->PrevSibling() );
+        WRAPNODE( aNodeToMove )->SetNextSibling( aInsertBefore );
+        WRAPNODE( aInsertBefore )->SetPrevSibling( aNodeToMove );
+        }
+    else
+        {
+        //if new parent had children
+        if ( aNewParent->LastChild() )
+            {
+            WRAPNODE( aNewParent->LastChild() )->SetNextSibling( aNodeToMove );
+            WRAPNODE( aNodeToMove )->SetPrevSibling( aNewParent->LastChild() );
+            WRAPNODE( aNewParent )->SetLastChild( aNodeToMove );
+            WRAPNODE( aNodeToMove )->SetNextSibling(NULL);
+            }
+        else //no children before
+            {
+            WRAPNODE( aNewParent )->SetFirstChild( aNodeToMove );
+            WRAPNODE( aNewParent )->SetLastChild( aNodeToMove );
+            WRAPNODE( aNodeToMove )->SetPrevSibling( NULL );
+            WRAPNODE( aNodeToMove )->SetNextSibling( NULL );            
+            }
+        }
+
+    //Set client list dirty => will be updated on next Nodes() request.
+    iClientListDirty = ETrue;
+
+    }
+        
+// -----------------------------------------------------------------------------
+// CXCFWTree::Nodes
+// return tree nodes as array of MXCFWNode pointers
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RNodeArray& CXCFWTree::Nodes()
+    {
+
+    //see if we should update the MXCFWNode array to reflect the new
+    if ( iClientListDirty )
+        {
+
+        if ( iNodeListForClient.Count() > 0 )
+            {
+            iNodeListForClient.Reset();
+            }
+
+        TInt count = iNodeList.Count();
+        for ( TInt i = 0; i < count; i++ )
+            {
+            iNodeListForClient.Append( (MXCFWNode*)iNodeList[i] );           
+            }
+        iClientListDirty = EFalse;
+        }
+
+    return iNodeListForClient;
+    }
+
+        
+// -----------------------------------------------------------------------------
+// CXCFWTree::RemoveNodeL
+// Removes a node from tree by updating all relative nodes and removing from
+// arrays.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CXCFWTree::RemoveNodeL(
+    MXCFWNode* aNodeToRemove )
+    {
+
+    __ASSERT_LEAVE( aNodeToRemove != NULL, KErrArgument );
+
+    __ASSERT_LEAVE( !iLocked, KErrAccessDenied );
+    
+    if ( iRoot != aNodeToRemove )
+        {
+        //update related nodes before removal, unless removing root node.
+        if ( aNodeToRemove->PrevSibling() )
+            {
+            WRAPNODE( aNodeToRemove->PrevSibling() )->SetNextSibling(
+                                    aNodeToRemove->NextSibling() );            
+            }
+        
+        if ( aNodeToRemove->NextSibling() )
+            {
+            WRAPNODE( aNodeToRemove->NextSibling() )->SetPrevSibling( 
+                                    aNodeToRemove->PrevSibling() );    
+            }
+
+        if ( aNodeToRemove->Parent()->FirstChild() == aNodeToRemove )
+            {
+            WRAPNODE( aNodeToRemove->Parent() )->SetFirstChild( 
+                                    aNodeToRemove->NextSibling() );            
+            }
+        
+        if ( aNodeToRemove->Parent()->LastChild() == aNodeToRemove )
+            {
+            WRAPNODE( aNodeToRemove->Parent() )->SetLastChild( 
+                                    aNodeToRemove->PrevSibling() );            
+            }
+        }
+    else
+        {
+        //root was removed.
+        iRoot = NULL;            
+        }
+
+    //Set client list dirty => will be updated on next Nodes() request.
+    iClientListDirty = ETrue;
+    
+    RemoveNodeRecursiveL( aNodeToRemove );
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::RemoveFromArray
+// Removes node pointer from CXCFWNode and MXCFWNode pointer arrays. 
+// Deletes from CXCFWNode array as well.
+// -----------------------------------------------------------------------------
+//
+void CXCFWTree::RemoveFromNodeList(
+    MXCFWNode* aNode )
+    {
+
+    //remove node from the pointer array.
+    TInt i = iNodeList.Count() - 1 ;
+    for ( ;i>=0 && aNode != iNodeList[i] ; i-- ){}
+    if ( i>=0 )
+        {
+        //delete object
+        delete iNodeList[i];
+        //remove from pointer arrays.
+        iNodeList.Remove(i);
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::RemoveNodeRecursiveL
+// Post-order recursion is used to make sure that no orhpan nodes are left
+// floating.
+// -----------------------------------------------------------------------------
+//
+void CXCFWTree::RemoveNodeRecursiveL(
+    MXCFWNode* aNode )
+    {
+
+    __ASSERT_LEAVE ( aNode != NULL, KErrArgument );
+
+    MXCFWNode* pointer = aNode->FirstChild();
+    
+    while ( pointer )
+        {
+        MXCFWNode* temp = pointer->NextSibling();
+        RemoveNodeRecursiveL( pointer );
+        pointer = temp;            
+        }
+
+    RemoveFromNodeList( aNode );
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CXCFWTree::Root
+// Returns MXCFWNode pointer to root node.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MXCFWNode* CXCFWTree::Root()
+    {
+    return iRoot;
+    }
+
+EXPORT_C void CXCFWTree::SetLocked( TBool aLockStatus )
+    {
+    iLocked = aLockStatus;
+    }
+
+EXPORT_C TBool CXCFWTree::IsLocked()
+    {
+    return iLocked;
+    }
+
+const TDesC& CXCFWTree::DTDName()
+    {
+    if ( !iDTDName )
+        {
+        return KNullDesC;
+        }
+    else
+        {
+        return *iDTDName;        
+        }
+    }
+
+void CXCFWTree::SetDTDNameL( const TDesC& aName )
+    {
+    delete iDTDName;
+    iDTDName = NULL;
+    iDTDName = aName.AllocL();        
+    }
+
+//  End of File