photosgallery/viewframework/uiutilities/src/glxvisualutilities.cpp
branchRCL_3
changeset 75 01504893d9cb
parent 0 4e91876724a2
--- /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 <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();
+        }
+    }