xcfw/src/xcfwtree.cpp
author jake
Tue, 13 Apr 2010 15:07:27 +0300
branchv5backport
changeset 56 7b5c31fac191
parent 0 79c6a41cd166
permissions -rw-r--r--
Many of the components were not compilingm,because bld.inf had undefined flag #ifdef RD_CUSTOMIZABLE_AI. All the flags removed now. Components do not compile right away. E.g. many icons are missing and need to be copied from Symbian3. See example from MCSPlugin. Shortcut plugin does not need to be compiled as MCSPlugin replaces it.

/*
* 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