photosgallery/viewframework/uiutilities/src/glxvisualutilities.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:32:09 +0300
branchRCL_3
changeset 75 01504893d9cb
parent 0 4e91876724a2
permissions -rw-r--r--
Revision: 201039 Kit: 201041

/*
* Copyright (c) 2008-2009 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:    ALF visual utilities
*
*/




// CLASS HEADER
#include "glxvisualutilities.h"

// EXTERNAL HEADERS
#include <uiacceltk/huicontrol.h>
#include <uiacceltk/huivisual.h>

namespace NGlxVisualUtilities
    {
    /**
     * TGlxVisualTransferCleanup
     * This class handles the awkward situation in visual ownership transfer
     * that some of the visuals are transferred to new parent and a leave occurs.
     * In leave case we need to undo the ownership transfer completely.
     * This class also removes the ownership from the old control in case
     * there was no leave.
     * @usage:
     * \code
     *      RArray<CHuiVisual*> allvisuals;
     *      TGlxVisualTransferCleanup cleanup( allvisuals );
     *       // set the parent to remove from to be the new one
     *      cleanup.iParentToRemoveFrom = aNewParent;
     *      CleanupClosePushL( cleanup );
     *      // start to append the visuals to the new parent
     *      // in case of leave they are removed from new parent
     *      RecurseAndTransferVisualsL( visualcleanup, aVisual, aNewParent );
     *      // set the parent to remove to be the old one
     *      cleanup.iParentToRemoveFrom = oldParent;
     *      // remove the item from cleanupstack,
     *      // this removes the visuals from their old parent 
     *      CleanupStack::PopAndDestroy( &cleanup );
     * \endcode
     */
    NONSHARABLE_CLASS( TGlxVisualTransferCleanup )
    	{
    	public:

            /**
    		 * Constructor.
    		 * @param aArray, the array of Visuals 
    		 * @param aOldParent, the old parent of visuals
    		 * @param aNewParent, the new parent for visuals
    		 */
    		inline TGlxVisualTransferCleanup( 
                RArray<CHuiVisual*>& aArray )
                : iArray( aArray )
    			{
                }

            /**
             * Close. Put this class to Cleanupstack with 
             * CleanupClosePushL so that this gets called in case of a leave
             */
            inline void Close()
                {
                // need to remove all visuals from the given parent
                // loop through all the CHuiVisuals
                for( TInt i = 0; i < iArray.Count(); ++i )
                    {
                    // remove from the given parent
                    iParentToRemoveFrom->Remove( iArray[ i ] );
                    }
                // reset the array
                iArray.Reset();
                }

            /// Ref: the parent where to remove
            MHuiVisualOwner* iParentToRemoveFrom;

        private: // Implementation

            /// Ref: the array containing all the visuals
            RArray<CHuiVisual*>& iArray; 

    	};

    /**
     * Recursive helper method to transfer the ownership of visuals
     * @param aVisualCleanup an array containing all visuals in the hierarchy
     * @param aVisual the visual to move to new control
     * @param aNewParent the new parent for the visual
     */
    void RecurseAndTransferVisualsL(
        RArray<CHuiVisual*>& aVisualCleanup,
        CHuiVisual& aVisual, CHuiControl& aNewParent )
        {
        // make room to the pointer so that we always succeed in appending
        // Note that we need to make room for one new item, thus count + 1
        aVisualCleanup.ReserveL( aVisualCleanup.Count() + 1 );
        // append us to the new parent, Note that for a while we are
        // owner by two controls but thats not a problem as the other parent 
        // is removed by either TGlxVisualTransferCleanup.Close() by CleanupStack
        // or destructor of TGlxVisualTransferCleanup and there is no other way
        // of getting out from this method (of course panic is ;)
        aNewParent.AppendL( &aVisual );
        // add us in the cleanuparray so that we can be removed from the 
        // new parent in case some of the following AppendLs leave
        // this does not fail as reserve was called so no AppendL needed
        aVisualCleanup.Append( &aVisual );
        // check if the visual has childs
        TInt childCount = aVisual.Count();
        // transfer all the childs
        while( childCount-- > 0 )
            {
            // get the child
            CHuiVisual& childVisual = aVisual.Visual( childCount );
            // call transfer recursively on the child
            RecurseAndTransferVisualsL( 
                aVisualCleanup, childVisual, aNewParent );
            }
        }

    // -------------------------------------------------------------------------
	// TransferVisualsL
	// -------------------------------------------------------------------------
    EXPORT_C void TransferVisualsL( 
        CHuiVisual& aVisual, CHuiControl& aNewParent )
        {
        // check if parent is already correct
        if( &( aVisual.Owner() ) == 
            static_cast< MHuiVisualOwner* >( &aNewParent ) )
            {
            // nothing else to be done
            return;
            }
        // create an array for visual pointers on the stack
        RArray< CHuiVisual* > visualcleanup;
        // create the cleanup item from stack as well
        TGlxVisualTransferCleanup removeParent( visualcleanup );
        // set the parent to remove from to be the new one
        removeParent.iParentToRemoveFrom = &aNewParent;
        // need to remember the old parent
        MHuiVisualOwner* oldParent = &( aVisual.Owner() );
        // put it to cleanupstack so that close gets called in case of leave
        CleanupClosePushL( removeParent );
        // run the recursive loop, if it leaves the visuals are removed from
        // new parent by the Close method of cleanParents
        RecurseAndTransferVisualsL( visualcleanup, aVisual, aNewParent );
        // set the parent to remove to be the old one
        removeParent.iParentToRemoveFrom = oldParent;
        // remove the item from cleanupstack,
        // this removes the visuals from the old parent 
        CleanupStack::PopAndDestroy( &removeParent );
        // close the array
        visualcleanup.Close();
        }
    }