diff -r 5b238bc8ffb6 -r 01504893d9cb photosgallery/viewframework/uiutilities/src/glxvisualutilities.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/photosgallery/viewframework/uiutilities/src/glxvisualutilities.cpp Wed Oct 13 14:32:09 2010 +0300 @@ -0,0 +1,167 @@ +/* +* 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 +#include + +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 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& 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& 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& 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(); + } + }