/*
* Copyright (c) 2008 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:   ?Description
*
*/

#include <uiacceltk/HuiCanvasVisual.h>
#include <alfwindowstructs.h>

#include "huiwscanvascommands.h"
#include "alfnodes.h"
#include "alfhierarchymodel.h"
#include "alfstreamerserver.h"
#include "alfwindowmanager.h"
#include "alfwindow.h"
#include "alfwindowdata.h"

#ifdef ALF_DEBUG_PRINT_NODE_INFO
    #define _ALF_LOGGING
    #include "alflogger.h"
    #undef _ALF_LOGGING
#else
    #include "alflogger.h"
#endif
// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CAlfNode::CAlfNode( ) :  
    iVisible( ETrue )
    {
    }

// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfNode::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream  )
    {
    iModel = aModel;
    iId = aStream->ReadInt32L();
    }

void CAlfNode::SetTracking( TBool aValue )
    {
    iTrackNode = aValue;
    if ( iWindow )
        {
        iWindow->SetNodeTracking( aValue );
        }
    }
// ---------------------------------------------------------------------------
// OrphanMe
// ---------------------------------------------------------------------------
//
CAlfNode* CAlfNode::OrphanMe()

    {
    __ALFLOGSTRING1("CAlfNode::OrphanMe %d", iId);
    // Parent node has been deleted. Orphan the node: remove the parent/sibling relationship.
    CAlfNode* sibling = iSibling;
    iSibling = NULL;
    iParent = NULL;
    return sibling;
    }

// ---------------------------------------------------------------------------
// ResolveParentL
// ---------------------------------------------------------------------------
//
void CAlfNode::ResolveParent( TUint32 aParentId, TInt aMyId )
    {
    CAlfNode* tmp = iModel->FindNode( aParentId );
    if ( tmp )
        {
        // 1. set parent, if there is one (root node is the only exception )
        iParent = tmp;
        // Possible sprite, textcursor, anim and child windows have different lists on the node
        switch( iType )
            {
            default:
                {
                SetFirstChild();
                break;
                }
            case MWsWindowTreeNode::EWinTreeNodeAnim:
                {
                SetFirstAnim();
                break;
                }
            case MWsWindowTreeNode::EWinTreeNodeSprite:
                {
                SetFirstSprite();
                break;
                }
            case MWsWindowTreeNode::EWinTreeNodeStandardTextCursor:
                {
                ASSERT( !iParent->iTextCursor );
                __ALFLOGSTRING1("parent->iTextCursor %d", iParent->iTextCursor );
                iParent->iTextCursor = (CAlfNodeTextCursor*)this;
                __ALFLOGSTRING1("parent->iTextCursor %d", iParent->iTextCursor );
                break;
                }
            }
        } 
    iId = aMyId;
    iModel->InsertNode( iId, this );
    ASSERT( iParent != NULL || iType == MWsWindowTreeNode::EWinTreeNodeRoot);
    
    if ( iType == MWsWindowTreeNode::EWinTreeNodeGroup )
        {
        iGroupId = iId;
        }
    else
        {
        iGroupId = FindParentGroup();
        }
    }

// ---------------------------------------------------------------------------
// SetFirstChild
// ---------------------------------------------------------------------------
//
void CAlfNode::SetFirstChild()
    {
    if ( iParent->iChild )
        {
        // pass over the previous first child and make it my sibling
        iSibling = iParent->iChild;
        }
    // jealously make me the first child
    iParent->iChild = this;
    }
// ---------------------------------------------------------------------------
// SetFirstChild
// ---------------------------------------------------------------------------
//
void CAlfNode::SetFirstAnim()
    {
    if ( iParent->iAnimChild )
        {
        // pass over the previous first child and make it my sibling
        iSibling = iParent->iAnimChild;
        }
    // jealously make me the first child
    iParent->iAnimChild = (CAlfNodeAnim*)this;
    }

// ---------------------------------------------------------------------------
// SetFirstChild
// ---------------------------------------------------------------------------
//
void CAlfNode::SetFirstSprite()
    {
    if ( iParent->iSpriteChild )
        {
        // pass over the previous first child and make it my sibling
        iSibling = iParent->iSpriteChild;
        }
    // jealously make me the first child
    iParent->iSpriteChild = (CAlfNodeSprite*)this;
    }

// ---------------------------------------------------------------------------
// FindParentGroup
// ---------------------------------------------------------------------------
//
TUint32 CAlfNode::FindParentGroup()
    {
    // go back in parents, until a group node is found. return its id.
    if ( iType == MWsWindowTreeNode::EWinTreeNodeSprite )
        {
        if ( iParent->iType == MWsWindowTreeNode::EWinTreeNodeRoot )
            {
            return 0;
            }
        else
            {
            return iParent->iId; // TODO: THIS IS ROOT, MIGHT NOT BE ALWAYS
            }
        }
    
    
    if ( iType == MWsWindowTreeNode::EWinTreeNodeRoot )
        {
        return 0;
        }
    ASSERT( iParent );
    CAlfNode* parent = iParent;
    while( parent->iType != MWsWindowTreeNode::EWinTreeNodeGroup )
        {
        parent = parent->iParent;
        }
    return parent->iId;
    }

// ---------------------------------------------------------------------------
// GetAllChildrenInGroup
// ---------------------------------------------------------------------------
//
void CAlfNode::GetAllChildrenInGroup( RPointerArray<CAlfNode>& aNodes, TUint32 aParentId )
	{
	if ( iParent->iType != MWsWindowTreeNode::EWinTreeNodeRoot)
		{
		CAlfNode* parentGroupNode = iModel->FindNode( aParentId );
		for (CAlfNode::TIter iter( parentGroupNode ); iter.Current() != NULL;  iter.Next()) 
			{ 
			aNodes.Append(iter.Current()); 
			}
		}
	else
		{
		CAlfNode* child = iParent->iChild;
		do
			{
			aNodes.Append( child );
			child = child->iSibling; 
			}
		while( child );
		}
	}

// ---------------------------------------------------------------------------
// OrdinalPosition
// ---------------------------------------------------------------------------
//
TInt CAlfNode::OrdinalPosition()
    {
    //_LIT( KText, "OrdinalPosition");
    __ALFLOGSTRING("CAlfNode::OrdinalPosition");
    // __ALFLOGSTRING1("CAlfNode::OrdinalPosition - Looking for me %d", iId );
    RPointerArray<CAlfNode> nodes;
    TBool hasOrdinalPosition = ETrue;
    
    switch(iParent->iType)
        {
        case MWsWindowTreeNode::EWinTreeNodeClient:
            {
            CAlfNode* parentNode = iModel->FindNode( iParent->iId );
            __ASSERT_DEBUG(parentNode, USER_INVARIANT());
            if (parentNode  && parentNode->HasChildren())
                {
                // parent node is not added to the list
                // the anims, cursor and sprites directly in this parent are added to the list
                // siblings are added to the list, but their anims, cursors and sprites are not added
                TraverseNodeTree( parentNode, nodes, EFalse /* list all for this node */, EFalse /* dont add me */);
                }      
            break;
            }
        case MWsWindowTreeNode::EWinTreeNodeGroup:
            {
            TUint32 parentId = FindParentGroup();
            CAlfNode* parentGroupNode = iModel->FindNode( parentId );
            //__ALFLOGSTRING1("CAlfNode::OrdinalPosition - My parent %d", parentId );        
            CAlfNode* current;
            if ( parentGroupNode )
                {
                current = parentGroupNode->iChild;
                TraverseNodeTree( current, nodes, ETrue /* list siblings only */, ETrue /* add me */ );
                }      

            break;
            }


        case MWsWindowTreeNode::EWinTreeNodeRoot:
            {
            // Window group ordinal position calculation (their parent is EWinTreeNodeRoot)

            // Root node can have window groups, sprites and perhaps anims as children.
            // However, sprites & anims do not have ordinal position concept, but window groups do.
            // These sprites & anims are placed to floating sprite control group in alfbridge side 
            // and so they are excluded from ordinal position calculation.
            CAlfNode* child = iParent->iChild;
            if ( this == iParent->iTextCursor )
                {
                hasOrdinalPosition = EFalse;
                }
                
            if ( hasOrdinalPosition && iParent->iSpriteChild )
                {
                CAlfNode* animnode = iParent->iSpriteChild ;
                while ( animnode )
                    {
                    if ( this == animnode )
                        {
                        hasOrdinalPosition = EFalse;
                        break;
                        }
                    animnode = animnode->iSibling;
                    }
                }

            if( hasOrdinalPosition && iParent->iAnimChild )
                {
                CAlfNode* animnode = iParent->iAnimChild ;
                while ( animnode )
                    {
                    if ( this == animnode )
                        {
                        hasOrdinalPosition = EFalse;
                        break;
                        }                    
                    animnode = animnode->iSibling;
                    }
                }

            if ( child )
                {
                do
                    {
                    nodes.Append( child );
                    child = child->iSibling;
                    }
                while( child );
                }
            break;
            }
        }
        
    TInt ordinalPosition = -1;
    if ( hasOrdinalPosition )
        {        
        TInt i = nodes.Count();
        //   __ALFLOGSTRING1("Node count: %d", i );
        // return my position in the node array
        while( --i >=0 && nodes[i] != this ) 
            {
            }
        if ( i < 0)
            {
            __ALFLOGSTRING1("Node %d not found!", iId);
            __ASSERT_DEBUG( 0, USER_INVARIANT() );
            //USER_INVARIANT();
            }
        else
            {
            __ALFLOGSTRING2("Found %d at ordinal position %d!", nodes[i]->iId, i );
            }
        ordinalPosition = i;
        }
    
    nodes.Close();    
    return ordinalPosition;
    }

// ---------------------------------------------------------------------------
// CAlfNode::TraverseNodeTree
// Traverse through node tree and fill node array 
// ---------------------------------------------------------------------------
//

// ---------------------------------------------------------------------------
// CAlfNode::TraverseNodeTree
// Traverse through node tree and fill node array 
// ---------------------------------------------------------------------------
//

void CAlfNode::TraverseNodeTree( CAlfNode* node,  RPointerArray<CAlfNode>& nodes, TBool aTraverseOnlySiblings, TBool aAddMe)
    {
    // Exit if we've already finished walking the tree.
    if ( node == NULL) 
        { 
        __ALFLOGSTRING(" returning NULL");                                  
        return;
        }
    if (!aTraverseOnlySiblings)
        {
        if ( node->iSpriteChild ) 
            {
        CAlfNode* spritenode = node->iSpriteChild ;
            while ( spritenode )
                {
                nodes.Append( spritenode );                
                spritenode = spritenode->iSibling;
                }
            }
    
        if( node->iTextCursor )
            {
            nodes.Append(node->iTextCursor );            
            }
    
        if( node->iAnimChild )
            {
            CAlfNode* animnode = node->iAnimChild ;
            while ( animnode )
                {
                nodes.Append( animnode );                
                animnode = animnode->iSibling;
                }
            }
        
        if ( node->iChild)
            {                
            TraverseNodeTree(node->iChild , nodes, EFalse, ETrue);            
            }
        } 

    if (aAddMe)
        {
        nodes.Append( node );
        }

    if ( node->iSibling )
        {                
        TraverseNodeTree(node->iSibling, nodes, ETrue, ETrue);               
        }
    }

// ---------------------------------------------------------------------------
// OrdinalPosition
// ---------------------------------------------------------------------------
//
#ifdef ALF_DEBUG_PRINT_NODE_INFO
TInt CAlfNode::PrintOrdinalPositions()
    {
    TInt i = 0;
    __ALFLOGSTRING("CAlfNode::PrintOrdinalPositions - ");
    
    RPointerArray<CAlfNode> nodes;
    if ( iParent->iType != MWsWindowTreeNode::EWinTreeNodeRoot)
        {
        TUint32 parentId = FindParentGroup();
        CAlfNode* parentGroupNode = iModel->FindNode( parentId );
        for (CAlfNode::TIter iter( parentGroupNode ); iter.Current() != NULL;  iter.Next()) 
            { 
            nodes.Append(iter.Current()); 
            }
        }
    else
        {
        CAlfNode* child = iParent->iChild;
        do
            {
            nodes.Append( child );
            }
        while( ( child = child->iSibling) != NULL );
        }
    
    i = nodes.Count();
    // return my position in the node arr
    TInt groupLevel = 0;
    while( --i >=0  ) 
    	{
    	CAlfNodeVisual* node = (CAlfNodeVisual*)nodes[i];
    	_LIT(KText, "PrintOrdinalPositions");
    	// PrintInfo( i, node, TPtrC(KText), 0);
    	}
    nodes.Close();    
    return i;
    }

void CAlfNode::PrintInfo( CAlfNode* aNode, TInt aHighLightNode, TInt aDepth)
    {
    HBufC16* buffer = HBufC16::NewL(256);
    TPtr iDebugText = buffer->Des();
    iDebugText.Format( _L(""));
    MWsWindowTreeNode::TType type = aNode->Type();

    for(TInt i = 0; i < aDepth; i++)
        {
        iDebugText.AppendFormat(_L(" "));
        }
		
    // Print the parent id in front of every children. For debugging the debugging code...
    //CAlfNode* parent = aNode->iParent;
    //if (parent)
    //	{
	//	iDebugText.AppendFormat(_L("[0x%x] "), parent->iId);
    //	}
    if ( aHighLightNode == aNode->iId )
        {
        iDebugText.AppendFormat( _L("\n-- MODIFIED NODE -- \n"));
        }

    switch ( type )
        {
        case MWsWindowTreeNode::EWinTreeNodeRoot:
            {
            iDebugText.AppendFormat( _L("Root 0x%x"), aNode->iId);
            break;
            }
        case MWsWindowTreeNode::EWinTreeNodeClient:
            {
            CAlfNodeVisual* nodeVisual = (CAlfNodeVisual*)aNode;
            iDebugText.AppendFormat(_L("Client 0x%x: iTl: (%3d,%3d), size (%3dx%3d)"), nodeVisual->iId, nodeVisual->iOrigin.iX, nodeVisual->iOrigin.iY, nodeVisual->iSize.iWidth, nodeVisual->iSize.iHeight );
                         
            break;
            }
        case MWsWindowTreeNode::EWinTreeNodeGroup:
            {
            CAlfNodeGroup* nodeGroup = (CAlfNodeGroup*)aNode;
            iDebugText.AppendFormat(_L("Group (%d) 0x%x: SecureId: 0x%x"), nodeGroup->iGroupId, nodeGroup->iId, nodeGroup->SecureId());
            break;
            }               
        case MWsWindowTreeNode::EWinTreeNodeAnim:
            {
            CAlfNodeVisual* nodeVisual = (CAlfNodeVisual*)aNode;
            iDebugText.AppendFormat(_L("Anim 0x%x: iTl: (%3d,%3d), size (%3dx%3d)"), nodeVisual->iId, nodeVisual->iOrigin.iX, nodeVisual->iOrigin.iY,nodeVisual->iSize.iWidth, nodeVisual->iSize.iHeight );
            break;
            }               
        case MWsWindowTreeNode::EWinTreeNodeSprite:
            {
            CAlfNodeVisual* nodeVisual = (CAlfNodeVisual*)aNode;
            iDebugText.AppendFormat(_L("Sprite 0x%x: iTl: (%3d,%3d), size (%3dx%3d)"), nodeVisual->iId, nodeVisual->iOrigin.iX, nodeVisual->iOrigin.iY,nodeVisual->iSize.iWidth, nodeVisual->iSize.iHeight );
            break;
            }               
        case MWsWindowTreeNode::EWinTreeNodeStandardTextCursor:
            {
            // TODO, add more cursor info
            CAlfNodeVisual* nodeVisual = (CAlfNodeVisual*)aNode;
            iDebugText.AppendFormat(_L("Cursor 0x%x: iTl: (%3d,%3d), size (%3dx%3d)"), nodeVisual->iId, nodeVisual->iOrigin.iX, nodeVisual->iOrigin.iY,nodeVisual->iSize.iWidth, nodeVisual->iSize.iHeight );
            break;
            }
        }
    switch( type )
    	{
    	case MWsWindowTreeNode::EWinTreeNodeStandardTextCursor:
    	case MWsWindowTreeNode::EWinTreeNodeSprite:
    	case MWsWindowTreeNode::EWinTreeNodeAnim:
    	case MWsWindowTreeNode::EWinTreeNodeClient:
    		{
    		CAlfNodeVisual* nodeVisual = (CAlfNodeVisual*)aNode;
    		iDebugText.AppendFormat(_L("\t\t\t"));
			if (nodeVisual->NonFading())
				{
				iDebugText.AppendFormat(_L("(NON FADING)"));
				}

			if (nodeVisual->Visible())
				{
				iDebugText.AppendFormat(_L("(VISIBLE)"));
				}
			
			if (nodeVisual->Faded())
				{
				iDebugText.AppendFormat(_L("(FADED)"));
				}
			
			if (nodeVisual->Activated())
				 {
				 iDebugText.AppendFormat(_L("(ACTIVATED)"));
				 }
    		}
    	}
    RDebug::Print(_L("%S"), &iDebugText);
    delete buffer;
    }

void CAlfNode::PrintNodeTree(
        CAlfNodeRoot* aNode,
        TInt aHighlightNode)
    {
    if (!aNode->iLogging) // Change this value during run-time. This produces A LOT of output
        {
        return;
        }
    TInt depth(0);
    CAlfNode::PrintSubTree((CAlfNode*)aNode,aHighlightNode, depth);
    }

void CAlfNode::PrintSubTree( CAlfNode* aNode, TInt aHighlightNode, TInt& aDepth )
    {
    aDepth++;
    CAlfNode::PrintInfo(aNode, aHighlightNode, aDepth);
   
    CAlfNode* node = (CAlfNode*)aNode->iSpriteChild;
       while( node )
           {
           CAlfNode::PrintInfo( node, aHighlightNode, aDepth + 1);
           node = node->iSibling;
           }
       node = (CAlfNode*)aNode->iAnimChild;
       while( node )
           {
           CAlfNode::PrintInfo(node, aHighlightNode, aDepth + 1);
           node = node->iSibling;
           }
       if ( aNode->iTextCursor )
           {
           CAlfNode::PrintInfo( aNode->iTextCursor, aHighlightNode, aDepth + 1);
           }
       node = (CAlfNode*)aNode->iChild;
       while ( node )        
           {
           node->PrintSubTree( node, aHighlightNode, aDepth );
           node = node->iSibling;
           }
       aDepth--;
    }

 #endif
// ---------------------------------------------------------------------------
// TIter::TIter
// ---------------------------------------------------------------------------
//
CAlfNode::TIter::TIter(CAlfNode* aTopNode) 
        : iTopNode(aTopNode) 
        , iCurrentNode(aTopNode),
        iState( ESearchingSprites )
        { 
        // Find the first node 
        while(iCurrentNode->iChild!=NULL) 
                { 
                iCurrentNode=iCurrentNode->iChild; 
                } 
        
        iCurrentSibling=iCurrentNode->iSibling;        // De-reference iCurrent so it can be destroyed by caller 
        iCurrentParent=iCurrentNode->iParent; 
        } 

// ---------------------------------------------------------------------------
// TIter::Current
// ---------------------------------------------------------------------------
//
CAlfNode* CAlfNode::TIter::Current() 
        { 
        return iCurrentNode; 
        } 

// ---------------------------------------------------------------------------
// TIter::Next
// ---------------------------------------------------------------------------
//
CAlfNode* CAlfNode::TIter::Next() 
        { 
        // Exit if we've already finished walking the tree. Do not return the group node
        if (iCurrentNode == iTopNode || iCurrentNode == NULL) 
                { 
                __ALFLOGSTRING("Iter returning NULL");
                iCurrentNode = NULL;
                iState = ESearchingSprites;
                return NULL; 
                }
        
//Diagram shows visit order with parent (/) and sibling relationships (>) 
//  
//              -  14 - 
//            /           \ 
//          6       >       13 
//         / \           /  |   \ 
//        3 > 5        10 > 11 > 12 
//       / \   \     / | \ 
//      1 > 2   4  7 > 8 > 9 
//  
// 
        // Todo.
        // Return sprites in order
        
      
        if ( iState == ESearchingSprites )
            {
            iMasterNode = iCurrentNode;
                    
            if ( iCurrentNode->iSpriteChild )
                {
                // TODO: As long as we are putting sprites into their own group, we cannot count their ordinals
                //iCurrentNode = (CAlfNode*)iCurrentNode->iSpriteChild;
                //iState = ESearchMoreSprites;
                //return iCurrentNode;
                iState = ESearchingTextCursor;
                }
            else
                {
                iState = ESearchingTextCursor;
                }
            }
        
        if ( iState == ESearchMoreSprites )
            {
            if ( iCurrentNode->iSibling )
                {
                iCurrentNode = iCurrentNode->iSibling;
                return iCurrentNode;
                
                }
            else
                {
                iCurrentNode = iMasterNode;
                iState = ESearchingTextCursor;
                }
            }
        
        if ( iState == ESearchingTextCursor )
            {
            if ( iMasterNode->iTextCursor )
                {
                iCurrentNode = iMasterNode->iTextCursor;
                iState = ESearchingMoreTextCursor;
                return iCurrentNode;
                }
            else
                {
                iState = ESearchingAnims;
                }
            }
        
        if ( iState == ESearchingMoreTextCursor )
            {
            iCurrentNode = iMasterNode;
            iState = ESearchingAnims;        
            return iCurrentNode;
        
            }
        
        if ( iState == ESearchingAnims )
            {
            if ( iCurrentNode->iAnimChild )
                {
                iCurrentNode = (CAlfNode*)iCurrentNode->iAnimChild;
                iState = ESearchMoreAnims;
                return iCurrentNode;
                }
            else
                {
                iState = ESearchingChildWindows;
                iChildrenProcessed = ETrue;
                iCurrentSibling = iMasterNode->iSibling;
                }
            }
        
        if ( iState == ESearchMoreAnims )
            {
            if ( iCurrentNode->iSibling ) // anim sibling
                {
                iCurrentNode = iCurrentNode->iSibling;
                return iCurrentNode;
                
                }
            else
                {
                iCurrentNode = iMasterNode;

                iState = ESearchingChildWindows;
                // if this node is having children windows, then we need to go to them
                if ( iCurrentNode->iChild )
                    {
                    iCurrentSibling = iCurrentNode->iChild;
                    // Look the deepest child
                    iCurrentNode=iCurrentSibling; 
                    while(iCurrentNode->iChild!=NULL) 
                        { 
                        iCurrentNode=iCurrentNode->iChild; 
                        } 
                    
                    iState = ESearchingSprites;
                    return iCurrentNode;
                    }
                else
                    {
                    // if no children windows, then this node is done and it should be returned
                    return iCurrentNode;
                    }
                }
            }
            
            if ( iState == ESearchingChildWindows )
                {
                if (iCurrentSibling!=NULL) 
                    { 
                    iCurrentNode=iCurrentSibling; 
                    while(iCurrentNode->iChild!=NULL) 
                        { 
                        iCurrentNode=iCurrentNode->iChild; 
                        } 
                    } 
                else 
                    { 
                    iCurrentNode = iCurrentParent;
                    iChildrenProcessed = EFalse;
                    } 
    
                iCurrentSibling=iCurrentNode->iSibling;        // De-reference iCurrent so it can be destroyed by caller 
                iChildrenProcessed = EFalse;
                iState = ESearchingSprites;
                iCurrentParent=iCurrentNode->iParent; 
                if ( iCurrentNode == iTopNode )
                    {
                    iCurrentNode = NULL;
                    }
                return iCurrentNode; 
                }
        return NULL;
        } 

// ---------------------------------------------------------------------------
// FindPreviousChild
// ---------------------------------------------------------------------------
//
CAlfNode* CAlfNode::FindPreviousChild()
    {
    CAlfNode* previousSibling = NULL;
    switch ( iType )
        {
        default:
            {
            previousSibling = iParent->iChild;
            break;
            }
        case MWsWindowTreeNode::EWinTreeNodeAnim:
            {
            previousSibling = iParent->iAnimChild;
            break;
            }
        case MWsWindowTreeNode::EWinTreeNodeSprite:
            {
            previousSibling = iParent->iSpriteChild;
            break;
            }
        case MWsWindowTreeNode::EWinTreeNodeStandardTextCursor:
            {
            previousSibling = iParent->iTextCursor;
            break;
            }
        }
     
    if ( previousSibling == this ) 
        {
        return NULL; // return NULL, if I was the first child
        }
    // starting from the first child, loop until this one is found.
    
    while( previousSibling && previousSibling->iSibling != this)
        {
        previousSibling = previousSibling->iSibling;
        }
    
    return previousSibling; // return the previous child. return NULL, if this was the first child
    }

// ---------------------------------------------------------------------------
// FadeCountChanged
// Fade count changes are sent also to Anim, Sprite and text cursor nodes.
// ---------------------------------------------------------------------------
//
void CAlfNode::FadeCountChanged( TInt aFadeCount )
    {
	RArray<CAlfNode*> children;
	ListOffspring(children, EFalse); // EFalse = dont list chilren, only sprites, anims and textcursor
	TBool fade = aFadeCount ? ETrue : EFalse;
    
    for(TInt i=0;i<children.Count(); i++)
    	{
		children[i]->SetFaded(fade);        
    	}
    children.Close();
    iFadeCount = aFadeCount;
    }

// ---------------------------------------------------------------------------
// SetFaded
// ---------------------------------------------------------------------------
//
void CAlfNode::SetFaded( TBool aFaded )
    {
    iFadeState = aFaded && ( !iNonFading );
    if (Type()== MWsWindowTreeNode::EWinTreeNodeRoot)
        {
        // NO need to deliver fades for root
        return;
        }
    if (iFadeState != iPostedFadeState)
        {
        iModel->Server().Bridge()->AddData( EAlfDSSetFadeEffect, iId , iFadeState, (TAny*)iType);
        iPostedFadeState = iFadeState;
        }
    }

// ---------------------------------------------------------------------------
// FadeAllChildren
// ---------------------------------------------------------------------------
//
void CAlfNode::FadeAllChildren( TBool aFaded )
    {
    SetFaded(aFaded);
    
    CAlfNode* node = (CAlfNode*)iSpriteChild;
    while( node )
        {
        node->SetFaded( iFadeState );        
        node = node->iSibling;
        }
    node = (CAlfNode*)iAnimChild;
    while( node )
        {
        node->SetFaded( iFadeState );       
        node = node->iSibling;
        }
    if ( iTextCursor )
        {
        iTextCursor->SetFaded( iFadeState );
        }
    node = (CAlfNode*)iChild;
    while ( node )        
        {
        node->FadeAllChildren( iFadeState );
        node = node->iSibling;
        }
    }

// ---------------------------------------------------------------------------
// ListOffspring
// ---------------------------------------------------------------------------
//
void CAlfNode::ListOffspring( RArray<CAlfNode*>& aList, TBool aListChildren)
    {
    aList.Append(this);
    
    CAlfNode* node = (CAlfNode*)iSpriteChild;
    while( node )
        {
		aList.Append(node);        
        node = node->iSibling;
        }
    node = (CAlfNode*)iAnimChild;
    while( node )
        {
		aList.Append(node);       
        node = node->iSibling;
        }
    if ( iTextCursor )
        {
		aList.Append(iTextCursor);
        }
    if (aListChildren)
    	{
		node = (CAlfNode*)iChild;
		while ( node )        
			{
			node->ListOffspring( aList );
			node = node->iSibling;
			}
    	}
    }
// ---------------------------------------------------------------------------
// FlagChanged
// ---------------------------------------------------------------------------
//
void CAlfNode::FlagChanged( MWsWindowTreeObserver::TFlags aFlag, TBool aNewValue )
    {
    switch( aFlag )
        {
        case MWsWindowTreeObserver::EVisible:
            {
            // TODO: Do something!!!!
            iVisible = aNewValue;
            break;
            }
        case MWsWindowTreeObserver::ENonFading:
            {
            iNonFading = aNewValue;
            FadeAllChildren(iFadeState);
            break;
            }
        case MWsWindowTreeObserver::EAlphaChannelTransparencyEnabled:
            {
            iAlphaChannelTransparencyEnabled = aNewValue;
            break;
            }
        case MWsWindowTreeObserver::ECursorClipRectSet:
            {
            // TODO: take into account with cursor 
            // ECursorClipRectSet
            break;
            }
        }
    }

// ---------------------------------------------------------------------------
// CreateWindowAttributes
// ---------------------------------------------------------------------------
//
TAny* CAlfNode::CreateWindowAttributes(TInt& aIndex, TInt aSize )
    {
    TAny* attributes = NULL;
    TRAP_IGNORE(attributes = (TAny*)iModel->Server().Bridge()->AppendVarDataL( aSize, aIndex ))
    Mem::FillZ( (TUint8*)attributes, aSize ); // Initialize the returned memory area to 0
    return attributes;
    }

// ---------------------------------------------------------------------------
// SiblingOrderChanged
// ---------------------------------------------------------------------------
//
 void CAlfNode::SiblingOrderChanged( TInt aNewPos )
    {
    // __ALFLOGSTRING1("CAlfNode::SiblingOrderChanged - Id %d, Old ordinal position: %d"), iId, OrdinalPosition());
    ASSERT( iType != MWsWindowTreeNode::EWinTreeNodeRoot); 
    ASSERT( iType != MWsWindowTreeNode::EWinTreeNodeSprite);
    ASSERT( iType != MWsWindowTreeNode::EWinTreeNodeAnim);
    ASSERT( iType != MWsWindowTreeNode::EWinTreeNodeStandardTextCursor);
    ASSERT( iType == MWsWindowTreeNode::EWinTreeNodeGroup || iType == MWsWindowTreeNode::EWinTreeNodeClient );
    ASSERT(iParent != NULL); 
    ASSERT(iParent->iChild != NULL); 
    CAlfNode* previous = FindPreviousChild();
    ASSERT( previous || this == iParent->iChild );
        
    
    // Need to find the previous node to this node (oldPrevNode) 
    // and the node previous to aNewPos (newPrevNode) 
    // Then link oldPrevNode->iSibling to this->iSibling (unlink this node from the chain) 
    // And  link this->iSibling to newPrevNode->iSibling (link the right hand side of this node back in) 
    // And  link newPrevNode->iSibling to this                          (link the left hand side of this node back in) 

    // Will point to the prev node for the current/old position 
    CAlfNode* oldPrevNode = NULL; 
    // Will point to the prev node for the new position 
    CAlfNode* newPrevNode = NULL; 

    // parent 
    //   | 
    //   |   0   1   2   3   4 
    //   +-->A ->B ->C ->D ->E ->null 
    //      ^^^ 
    // position 0 is a special case... 
    // if the new position is 0 then newPrevNode is the parent 
    // if this is the leftmost sibling then oldPrevNode is the parent 

    TInt iterNodePosition=0; 
    CAlfNode* iterPrevNode = iParent; 
    CAlfNode* iterNode = iParent->iChild;         

    while (oldPrevNode == NULL || newPrevNode == NULL) 
        { 
        // Have we found the current/old position? 
            if (iterNode == this) 
                { 
                oldPrevNode = iterPrevNode; 

                if (newPrevNode == NULL && iterNodePosition != aNewPos) 
                    { 
                    // Found the old position first 
                    // and not at the new position yet 
                    // so "this" will be moving to the right 
                    // which will cause the following nodes to move left by one 
                    // so we need to compensate by adding one to the target position 
                    // 
                    //     0   1   2   3   4 
                    // p ->A ->B ->C ->D ->E ->n  if we are moving B to position 3 then need to find D->E link (iterPrevNode->iterNode) 
                    // p ->A ->C ->D ->B ->E ->n  but because C and D will be moving left, 
                    //                            D->E is actually position at 4. 
                    ++aNewPos; 
                    }                         
                } 

            // Have we found the new position? 
            if (iterNodePosition == aNewPos) 
                { 
                newPrevNode = iterPrevNode; 
                } 

            // Move onto the next node - if there is one 
            if (iterNode != NULL) 
                { 
                // move to next node 
                iterPrevNode = iterNode; 
                iterNode = iterNode->iSibling;                 
                ++iterNodePosition; 
                } 
            else 
                { 
                // parent 
                //   | 
                //   |   0   1   2   3   4 
                //   +-->A ->B ->C ->D ->E ->null 
                //                           ^^^ 
                // if iterNode gets to NULL, then we must have found both matches 
                // - i.e. either the new or current/old position is the rightmost node   
                ASSERT(oldPrevNode!=NULL && newPrevNode!=NULL); 
                } 

            ASSERT(iterPrevNode!=NULL);                 
        } // end while loop 

    if (newPrevNode == oldPrevNode) 
        { 
        // we are being asked to move to our current position 
        // nothing to do 

        return; 
        } 

    // In the following example, oldPrevNode is A, this is B and newPrevNode is D - as discussed above 
    // 
    // Unlink this node from the chain (A->B becomes A->C, nothing points to B) 
    //      0    1    2    3    4 
    // p--->A-¬  B-+->C--->D--->E--->n 
    //         \--/ 
    if (oldPrevNode == iParent) 
        { 
        iParent->iChild = iSibling; 
        } 
    else 
        { 
        oldPrevNode->iSibling = iSibling; 
        } 

    // Link the right hand side of this node back in (B->C becomes B->E, B half at position 3) 
    //      0         1    2 3  4 
    // p--->A-------->C--->D-+->E--->n 
    //                B-----/ 
    if (newPrevNode == iParent) 
        { 
        iSibling = iParent->iChild; 
        } 
    else 
        { 
        iSibling = newPrevNode->iSibling; 
        } 

    // Link the left hand side of this node back in (D->E becomes D->B, B fully linked into position 3) 
    //      0    1    2    3    4 
    // p--->A--->C--->D¬     +->E--->n 
    //                  \-B-/ 
    if (newPrevNode == iParent) 
        { 
        iParent->iChild = this; 
        } 
    else 
        { 
        newPrevNode->iSibling = this; 
        } 
    
    UpdateOrdinalPosition();
    
    if (HasChildren())
        {
        UpdateChildrenOrdinalPositions(this);
        }
    
    /*
    TInt ordinal = OrdinalPosition();
    __ALFLOGSTRING1("New ordinal position: %d"), OrdinalPosition());
#ifdef _DEBUG    
    PrintOrdinalPositions();
#endif    
    TInt offset;
    TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)CreateWindowAttributes(offset, sizeof(TAlfWindowAttributes));
    windowAttributes->iOrdinalPosition = ordinal; 
    windowAttributes->iWindowNodeType = iType;
    windowAttributes->iScreenNumber = iScreenNumber;
    
    iModel->Server().Bridge()->AddData( EAlfDSReorder, 
            iGroupId, 
            iId, 
            (TAny*)offset );
            */
            
            
    }

// ---------------------------------------------------------------------------
// destructor
// ---------------------------------------------------------------------------
// 
CAlfNode::~CAlfNode()
    {
    __ALFLOGSTRING1("CAlfNode::~CAlfNode %d", iId);
	if ( iWindow && iModel ) // just in case: the window should be deleted already
        {
        iModel->Server().WindowMgr()->DestroyWindow( *iWindow );
        iWindow = NULL;
        }
    }

// ---------------------------------------------------------------------------
// HasChildren
// ---------------------------------------------------------------------------
// 
TBool CAlfNode::HasChildren()
    {
    return iSpriteChild || iAnimChild || iTextCursor || iChild;
    }

// ---------------------------------------------------------------------------
// RemoveDependencies
// ---------------------------------------------------------------------------
// 
void CAlfNode::RemoveDependencies( CAlfNode* aFirstChildOfMyType )
    {
    // if I have siblings, then make my previous sibling's next sibling, that used to be my next sibling
    /*if ( iParent )
        {
        __ALFLOGSTRING1( "%d %d %d %d"), iParent->iChild , iParent->iSpriteChild , iParent->iAnimChild, iParent->iTextCursor );
        }*/

    if ( iModel && iParent && aFirstChildOfMyType )
        {
        CAlfNode* previousSibling = FindPreviousChild();
        if ( previousSibling )
            {
            previousSibling->iSibling = iSibling;
            }
        else
            {
            // If we do not have previous sibling
            switch ( iType )
                {
                default:
                    {
                    iParent->iChild = iSibling; // Parent's child needs to change ONLY IF I was the first one.
                    break;
                    }
                case MWsWindowTreeNode::EWinTreeNodeAnim:
                    {
                    iParent->iAnimChild = (CAlfNodeAnim*)iSibling;
                    break;
                    }
                case MWsWindowTreeNode::EWinTreeNodeSprite:
                    {
                    iParent->iSpriteChild = (CAlfNodeSprite*)iSibling;
                    break;
                    }
                }
            
            }
        }
    else
        {
        __ALFLOGSTRING1("My parent says, that I'm not his child :..( or no parent %d ", iParent );
        }
    
    // Orphan all the children
    CAlfNode* child = iChild; 
    while( child )
        {
        child = child->OrphanMe();
        }
    iChild = NULL;
    if ( iModel )
        {    
        iModel->RemoveNode( iId );
        }
    }

// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CAlfNodeVisual::CAlfNodeVisual() 
    {
    iWindow =  NULL;
    };

// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
void CAlfNodeVisual::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream )
	{
	CAlfNode::ConstructL( aModel, aStream );
    aStream->ReadL( (TUint8*)&iOrigin, sizeof(TPoint));
    aStream->ReadL( (TUint8*)&iSize, sizeof(TSize));
	}

// ---------------------------------------------------------------------------
// ReadEndMarkerL
// ---------------------------------------------------------------------------
//
void CAlfNodeVisual::ReadEndMarkerL( RMemReadStream& aStream )
    {
    TUint8 marker = aStream.ReadInt8L();
    ASSERT( marker == EAlfCommandEndMarker ) ; // endmarker
    }
 
// ---------------------------------------------------------------------------
// UpdateOrdinalPosition
// ---------------------------------------------------------------------------
//
void CAlfNode::UpdateOrdinalPosition()
    {
    TInt ordinal = OrdinalPosition();
    if ( ordinal >= 0 )
        {
        if ( iWindow )
            {
            iWindow->Move( ordinal );
            }
        else
            {
            //!!!! There is no window???
            // position must be updated, because it not necessary the first drawn.
            TInt offset;
            TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)CreateWindowAttributes(offset, sizeof(TAlfWindowAttributes));
            windowAttributes->iOrdinalPosition = ordinal; 
            windowAttributes->iWindowNodeType = iType;
            windowAttributes->iScreenNumber = iScreenNumber;
            // for updating window group ordinals
            iModel->Server().Bridge()->AddData( EAlfDSReorder, 
                    iGroupId, 
                    iId, 
                    (TAny*)offset );
            }
        }
    }

// ---------------------------------------------------------------------------
// UpdateChildrenOrdinalPositions
// ---------------------------------------------------------------------------
//
void CAlfNode::UpdateChildrenOrdinalPositions(CAlfNode* aNode)
    {
    CAlfNode* node = (CAlfNode*)aNode->iSpriteChild;
    while( node )
        {
        node->UpdateOrdinalPosition();
        node = node->iSibling;
        }
    node = (CAlfNode*)aNode->iAnimChild;
    while( node )
        {
        node->UpdateOrdinalPosition();
        node = node->iSibling;
        }
    if ( aNode->iTextCursor )
        {
        (aNode->iTextCursor)->UpdateOrdinalPosition();
        }
    node = (CAlfNode*)aNode->iChild;
    while ( node )        
        {
        node->UpdateChildrenOrdinalPositions(node);
        node->UpdateOrdinalPosition();
        node = node->iSibling;
        }

    }

// ---------------------------------------------------------------------------
// CommitCommandsL
// ---------------------------------------------------------------------------
//
void CAlfNodeVisual::CommitCommands( TInt aCurrentPos, TInt aFrameSize, TBool aPartial, TBool aLastPart, TInt aChunkInUse  )
    {
    // __ALFLOGSTRING1("CAlfNodeVisual::CommitCommandsL, Id/Group: %d/%d Type: %d, Pos: %d, Size: %d, last part %d"), iId, iGroupId, iType, aCurrentPos, aFrameSize, aLastPart );
    if ( !iWindow )
        {
        __ALFLOGSTRING("CAlfHierarchyModel::CommitCommandsL Discarding window commands");
        return;
        }

    if ( !aFrameSize )
        {
        __ALFLOGSTRING3("CAlfHierarchyModel::CommitCommandsL empty frame Pos: %d, Size: %d, last part %d ", aCurrentPos, aFrameSize, aLastPart );
        return;
        }
    
    TBool emptyBuffer = EFalse;
    
    TInt nodeFlags = 0;

    // By default nodes are always opaque, unless they are sprites (or anims?) or
    // transparency has been enabled in the window.    
    if (iType != MWsWindowTreeNode::EWinTreeNodeSprite && 
        iType != MWsWindowTreeNode::EWinTreeNodeAnim &&
       iType != MWsWindowTreeNode::EWinTreeNodeStandardTextCursor &&
        !iAlphaChannelTransparencyEnabled)
        {
        nodeFlags |= EAlfWinNodeFlagOpaque;         
        }
        
    if ( iType == MWsWindowTreeNode::EWinTreeNodeStandardTextCursor )
        {
        emptyBuffer = ETrue;
        }
       
    iWindow->PostPartialBuffer( iModel->ChunkBase(aChunkInUse) + aCurrentPos, aFrameSize, aPartial, aLastPart , emptyBuffer, nodeFlags );
    }

// ---------------------------------------------------------------------------
// DrawWindowFrameL
// ---------------------------------------------------------------------------
void CAlfNodeVisual::DrawWindowFrameL( RMemReadStream& aStream )
    {
    TInt32 chunkInUse = aStream.ReadInt32L();
    TInt nextFramePos = aStream.ReadInt32L();
       
    // jump to the next frame
    if ( nextFramePos == 12345678 )
        {
        __ALFLOGSTRING("CAlfHierarchyModel::PostBufferL, Address of the frame has not been initialized!");
        }
    // read frame flags. For offscreen content, we'll add the complete packets 
     // as partial, if they have not been implicitly flushed 
     
     TUint8 command = aStream.ReadInt8L();
     __ASSERT_DEBUG( command == EAlfFrameFlags, USER_INVARIANT() );
     TInt32 frameFlags = aStream.ReadInt32L();

    TUint8 padding = aStream.ReadInt8L();
    ReadEndMarkerL( aStream );
    while( padding--)
        {
        aStream.ReadInt8L();
        }
        
    TInt currentPos = aStream.Source()->TellL( MStreamBuf::ERead ).Offset();
    aStream.Source()->SeekL( MStreamBuf::ERead, TStreamPos(nextFramePos));
    TSgcCanvasCommands packetState = (TSgcCanvasCommands)aStream.ReadInt8L();
    TInt frameSize = nextFramePos - currentPos;
#ifdef _DEBUG
    ASSERT( currentPos % 8 == 0 );
#endif
    
    //__ALFLOGSTRING1("CAlfHierarchyModel::PostBufferL endMarker: %d partial: %d"), endMarker, iReadingPartialBuffer );
    switch( packetState )
        {
        case EAlfPacketReady:
            {
            if ( frameFlags & EAlfTransparentContent )
                {
                if ( frameFlags & EAlfTransparentContentFlush  )
                    {
                    CommitCommands( currentPos, frameSize, !iReadingPartialBuffer /*partial*/, ETrue /*lastpart*/, chunkInUse );
                    }
                else
                    {
                    CommitCommands( currentPos, frameSize, ETrue /*partial*/, EFalse/*not lastpart*/, chunkInUse );
                    }
                }
            else
                {
                CommitCommands( currentPos, frameSize, iReadingPartialBuffer, ETrue, chunkInUse );
                }
            iReadingPartialBuffer = EFalse;
                            
            break;
            }
        case EAlfPacketNotReady:
            {
            __ASSERT_DEBUG( nextFramePos % 8 == 0, USER_INVARIANT() );
            __ASSERT_DEBUG( frameSize % 8 == 0, USER_INVARIANT() );
            iReadingPartialBuffer = ETrue;
            CommitCommands( currentPos, frameSize, iReadingPartialBuffer, EFalse, chunkInUse );
            break;
            }
        default:
            {
            __ALFLOGSTRING1("CAlfHierarchyModel::PostBufferL endMarker: %d ", packetState);
            break;
            }
        }
    }


// ---------------------------------------------------------------------------
// FlagChanged
// ---------------------------------------------------------------------------
//
void CAlfNodeVisual::FlagChanged( MWsWindowTreeObserver::TFlags aFlag, TBool aNewValue )
    {
    switch( aFlag )
        {
        case MWsWindowTreeObserver::EVisible:
            {
            iVisible = aNewValue;
            if ( iWindow )
            	{
            	if ( iVisible && iNodeActivated )
            		{
            		iWindow->SetActive( ETrue );
            		}
            	else
            		{
                    iWindow->SetActive( EFalse );
            		}
            	
            	iWindow->IncludeToVisibilityCalculation( iVisible && iNodeActivated );
            	}
            break;
            }
        case MWsWindowTreeObserver::ENonFading:
            {
            iNonFading = aNewValue;
            SetFaded(iFadeState);
            break;
            }
        case MWsWindowTreeObserver::EAlphaChannelTransparencyEnabled:
            {
            iAlphaChannelTransparencyEnabled = aNewValue;
            if ( iWindow )
                {
                iWindow->SetTransparencyAlphaChannel( aNewValue );
                }
            break;
            }
        }
    if ( aFlag == MWsWindowTreeObserver::ENonFading && HasChildren() )
        {
        UpdateChildrenFlags( aFlag, iFadeState );
        }
    }

// ---------------------------------------------------------------------------
// UpdateChildrenFlags
// ---------------------------------------------------------------------------
//
void CAlfNodeVisual::UpdateChildrenFlags( MWsWindowTreeObserver::TFlags aFlag, TBool aNewValue )
    {
    CAlfNode* node = (CAlfNode*)iSpriteChild;
    while( node )
        {
        node->FlagChanged( aFlag, aNewValue );
        node = node->iSibling;
        }
    node = (CAlfNode*)iAnimChild;
    while( node )
        {
        node->FlagChanged( aFlag, aNewValue );
        node = node->iSibling;
        }
    if ( iTextCursor )
        {
        iTextCursor->FlagChanged( aFlag, aNewValue );
        }
    node = (CAlfNode*)iChild;
    while ( node )
        
        {
        node->FlagChanged( aFlag, aNewValue ); // causes recursion on children
        node = node->iSibling;
        }
    }

// ---------------------------------------------------------------------------
// SetExtent
// ---------------------------------------------------------------------------
//
void CAlfNodeVisual::SetExtent( TRect& aRect )
    {
	// aRect is in screen coordinates whereas iOrigin and iSize are relative.
    if ( iSize != aRect.Size() )
    	{
    	iSize = aRect.Size();
    	if ( iWindow) 
    		{
    		iWindow->SetSize(iSize,0);
    		}
    	}
  	// Recursively, TODO, check this with flash example
   	TPoint parentPosition; 
   	CAlfNodeVisual* parent = (CAlfNodeVisual*)iParent;
   	while(parent)
   	    {
        if(parent->Type() != MWsWindowTreeNode::EWinTreeNodeGroup)
            { // parent 
            parentPosition += parent->iOrigin;
            parent = (CAlfNodeVisual*)parent->iParent;
            }
        else
            {
            break;
            }
                
    	}
            
    TPoint newOrigin = aRect.iTl - parentPosition;
    if ( iOrigin != newOrigin )
    	{            
    	iOrigin = newOrigin;
    	if (iWindow)
    		{
    		iWindow->SetPos(iOrigin, 0 );
    		/*if (HasChildren())
    		    {
    		    UpdateChildrenExtents(posDelta);
    		    }*/
    		// __ALFLOGSTRING1("CAlfNodeVisual, SetPos %d,%d, iType %d"), iOrigin.iX, iOrigin.iY, iType );
    		}
    	}
    // __ALFLOGSTRING1("CAlfNodeVisual, SetExtent iSize: %d,%d ; iPosition %d,%d "), iSize.iWidth, iSize.iHeight, iOrigin.iX, iOrigin.iY ); 
    }

void CAlfNodeVisual::UpdateParentPosition(TPoint aPosDelta)
    {
    // iParentPosition = aRect.iTl;
    // iParentSize = aRect.Size();
    
    // Todo, size change?
    if (iWindow)
        {
        iOrigin += aPosDelta;
        iWindow->SetPos( iOrigin, 0 );
        UpdateChildrenExtents(aPosDelta);
        // __ALFLOGSTRING1("CAlfNodeVisual, SetPos %d,%d, iType %d"), iOrigin.iX, iOrigin.iY, iType );
        }

    }

void CAlfNodeVisual::UpdateChildrenExtents(TPoint aPosDelta)
    {
        CAlfNode* node = (CAlfNode*)iSpriteChild;
        while( node )
            {
            ((CAlfNodeVisual*)node)->UpdateParentPosition(aPosDelta);
            node = node->iSibling;
            }
        node = (CAlfNodeVisual*)iAnimChild;
        while( node )
            {
            ((CAlfNodeVisual*)node)->UpdateParentPosition(aPosDelta);
            node = node->iSibling;
            }
        if ( iTextCursor )
            {
            ((CAlfNodeVisual*)iTextCursor)->UpdateParentPosition(aPosDelta);
            }
        node = (CAlfNodeVisual*)iChild;
        while ( node )        
            {
            ((CAlfNodeVisual*)node)->UpdateChildrenExtents(aPosDelta);
            ((CAlfNodeVisual*)node)->UpdateParentPosition(aPosDelta);
                        
            node = node->iSibling;
            }
        }

// ---------------------------------------------------------------------------
// ActivateNodeL
// ---------------------------------------------------------------------------
//
void CAlfNodeVisual::ActivateNode()
     { 
     if ( !iNodeActivated)
         {
         iNodeActivated = ETrue;
        
         if ( iWindow )
            {
        	if ( iVisible )
        		{
        		iWindow->SetActive( ETrue );
        		}
        	
        	iWindow->IncludeToVisibilityCalculation( iVisible && iNodeActivated );
            }
         }
     else
         {
         __ALFLOGSTRING("CAlfNodeVisual::ActivateNodeL - Node ALREADY active! ");
         }
     }


// ---------------------------------------------------------------------------
// CreateWindowL
// ---------------------------------------------------------------------------
void CAlfNodeVisual::CreateWindowL(TInt aWindowGroupHandle, TInt aWindowHandle, TInt aParentWindowHandle)
    {
    TWindowIdentifier windowIdentifier( iGroupId, iId );
    TWindowIdentifier clientSideIdentifier( aWindowGroupHandle, aWindowHandle );
    TWindowIdentifier parentIdentifier( 0, aParentWindowHandle ); // Group id not used, set to zero.
    
    TAlfWServInfo info;     
    info.iSize = iSize;
    info.iPosition = iOrigin;    
    info.iRefId = windowIdentifier; // Node ids   
    info.iClientSideId = clientSideIdentifier; // Client handles
    info.iNodeType = iType;
    info.iScreenNumber = iScreenNumber;    
    info.iParentRefId = parentIdentifier;
#ifdef ALF_DEBUG_TRACK_DRAWING    
    info.iTrackWindow = iTrackNode;
#endif
    iWindow = iModel->Server().WindowMgr()->CreateNewWindowL( iId, info );
    iWindow->CommitGc();
    }

// ---------------------------------------------------------------------------
// destructor
// ---------------------------------------------------------------------------
//
CAlfNodeVisual::~CAlfNodeVisual()
    {
    if ( iWindow && iModel )
        {
        iModel->Server().WindowMgr()->DestroyWindow( *iWindow );
		iWindow = NULL; // make sure there is no double deletion
        }
    }

// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CAlfNodeWindow::CAlfNodeWindow()
    {
    iType = MWsWindowTreeNode::EWinTreeNodeClient;
    };

CAlfNodeWindow::~CAlfNodeWindow()
    {
    RemoveDependencies( iParent ? iParent->iChild : NULL );
    }
// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfNodeWindow::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream  )
	{
	CAlfNodeVisual::ConstructL( aModel, aStream );
	aStream->ReadL( (TUint8*)&iNodeWindowConstructionStruct, sizeof( TNodeWindowConstructionStruct ) );
    iOrdinalPriority = iNodeWindowConstructionStruct.iOrdinalPriority;
    ResolveParent( iNodeWindowConstructionStruct.iParentId, iId );
    CreateWindowL( iNodeWindowConstructionStruct.iWindowGroupHandle, iNodeWindowConstructionStruct.iWindowHandle, iNodeWindowConstructionStruct.iParentId );
    UpdateOrdinalPosition();
	}

// ---------------------------------------------------------------------------
// MoveToWindowGroup
// !!!! THIS METHOD HAS NOT BEEN TESTED AT ALL!!!!!! EXPECT TROUBLE!!!!
// ---------------------------------------------------------------------------
//
void CAlfNodeWindow::MoveToWindowGroup( TUint32 aNewGroupId )
	{
	__ALFLOGSTRING("CAlfNodeWindow::MoveToWindowGroup, THIS METHOD IS UNTESTED. EXPECT TROUBLE!");
	CAlfNodeGroup* newGroup = (CAlfNodeGroup*)iModel->FindNode( aNewGroupId );
	if ( newGroup )
		{
		// collect my children in my old group
		RPointerArray<CAlfNode> myChildNodes;
		GetAllChildrenInGroup( myChildNodes, iId );
			    
		// release old relationships
		CAlfNode* previous = FindPreviousChild();
		if ( !previous )
			{
			iParent->iChild = iSibling; // I was the first and possibly only child
			}
		else
			{
			previous->iSibling = iSibling; // there was the a previous child. update the link to my next sibling (which might be NULL)
			}
		TUint32 oldGroupId = iParent->iId;
		iParent = newGroup;
		SetFirstChild();
		
		// yippii, new parent, 		
		// add me as the first child of the new group
		// TODO: Move the nodes to the new group?
		TInt i = myChildNodes.Count();
		while( --i >=0 ) // update groupid and send new location to appui 
			{
			iModel->Server().Bridge()->AddData( EAlfDSMoveWindowToNewGroup, 
					myChildNodes[i]->iId, 
					oldGroupId, 
					(TAny*)aNewGroupId );
			myChildNodes[i]->iGroupId = aNewGroupId;
			}
	  
		myChildNodes.Close();
		}
	else
		{
		__ALFLOGSTRING("CAlfNodeWindow::MoveToWindowGroupL, new group does not exists");
		USER_INVARIANT();
		}
	}

// ---------------------------------------------------------------------------
// SetWindowAreaL
// ---------------------------------------------------------------------------
//
void CAlfNodeWindow::SetWindowAreaL( RMemReadStream* aStream )
    {
    TPoint pos;
    RRegion region;
    CleanupClosePushL( region );
    
    pos.iX = aStream->ReadInt32L();
    pos.iY = aStream->ReadInt32L();
    
    TInt count = aStream->ReadInt32L();
    for ( TInt i = 0; i < count; ++i )
        {
        TRect r;
        aStream->ReadL((TUint8*)&r.iTl.iX, 4 * sizeof(TInt32 ));
        region.AddRect(r);
        }
    
    if ( region.CheckError() )
        {
        // Fallback to non-shape version
        region.Clear();
        }
    
    iWindow->SetWindowArea( pos, region );
    
    CleanupStack::PopAndDestroy();
    }

// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CAlfNodeWindow* CAlfNodeWindow::NewL( CAlfHierarchyModel* aModel, RMemReadStream* aStream, TInt aScreenNumber  )
    {
    CAlfNodeWindow* self = new(ELeave)CAlfNodeWindow();
    CleanupStack::PushL( self );
    self->iScreenNumber = aScreenNumber;
    self->ConstructL( aModel, aStream ); 
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// Construct
// ---------------------------------------------------------------------------
//
CAlfNodeRoot::CAlfNodeRoot( )
    {
    iType = MWsWindowTreeNode::EWinTreeNodeRoot;
    }

// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfNodeRoot::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream  )
	{
	CAlfNodeVisual::ConstructL( aModel, aStream );
	
	// TODO: 
	ResolveParent( 0, iId );
	CreateWindowL(0,0,0); // Currently renderstage does not deliver ws/wg handles
	}

// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CAlfNodeRoot* CAlfNodeRoot::NewL( CAlfHierarchyModel* aModel, RMemReadStream* aStream, TInt aScreenNumber  )
    {
    CAlfNodeRoot* self = new(ELeave)CAlfNodeRoot();
    CleanupStack::PushL( self );
    self->iScreenNumber = aScreenNumber;
    self->ConstructL( aModel, aStream ); 
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// destructor
// ---------------------------------------------------------------------------
//
CAlfNodeRoot::~CAlfNodeRoot( )
    {
    // TODO: destroy all children nodes?
    RemoveDependencies( NULL );
    }

// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CAlfNodeGroup::CAlfNodeGroup()
    {
    iType = MWsWindowTreeNode::EWinTreeNodeGroup;
    }

// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfNodeGroup::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream  )
	{
	CAlfNode::ConstructL( aModel, aStream );
    TInt32 clientHandle = aStream->ReadUint32L();
    iSecureId = aStream->ReadUint32L();
    TInt32 parentId = aStream->ReadUint32L();
    
    ResolveParent( parentId, iId );
    
    TInt offset;
    TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)CreateWindowAttributes(offset, sizeof(TAlfWindowAttributes));
    windowAttributes->iWindowNodeType = iType; 
    windowAttributes->iClientHandle = clientHandle;
    windowAttributes->iScreenNumber = iScreenNumber;
    windowAttributes->iSecureId = iSecureId;
    windowAttributes->iParentNodeId = parentId;
	
    iModel->Server().Bridge()->AddData( EAlfDSNewWindow, 
            iGroupId, 
            iId, 
            (TAny*)offset );
	}

// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CAlfNodeGroup* CAlfNodeGroup::NewL( CAlfHierarchyModel* aModel, RMemReadStream* aStream , TInt aScreenNumber )
    {
    CAlfNodeGroup* self = new(ELeave)CAlfNodeGroup();
    CleanupStack::PushL( self );
    self->iScreenNumber = aScreenNumber;
    self->ConstructL( aModel, aStream ); 
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// WindowGroupChainedL
// ---------------------------------------------------------------------------
//
void CAlfNodeGroup::WindowGroupChained( TUint32 aChainedGroup )
	{
	iChainedTo = (CAlfNodeGroup*)iModel->FindNode( aChainedGroup );
	if ( iChainedTo )
		{
		iChainedTo->iChainedFrom = this;
		}
	else
		{
		USER_INVARIANT();
		}
	
    if (iModel)
        {
        iModel->Server().Bridge()->AddData( EAlfDSGroupChained, 
                iId, 
                aChainedGroup, 
                (TAny*)iScreenNumber
                );                
        }
	}

// ---------------------------------------------------------------------------
// GroupChainBrokenAfter
// ---------------------------------------------------------------------------
//
void CAlfNodeGroup::GroupChainBrokenAfter(  )
	{
	if ( iChainedTo )
		{
		iChainedTo->iChainedFrom = NULL;
		iChainedTo = NULL;
		}
	if (iModel)
		{
		iModel->Server().Bridge()->AddData( EAlfDSGroupChainBroken, 
				iId, 
				0, 
				(TAny*)iScreenNumber );                
		}

	}


// ---------------------------------------------------------------------------
// destructor
// ---------------------------------------------------------------------------
//
CAlfNodeGroup::~CAlfNodeGroup()
    {
    if ( iChainedTo )
    	{
    	GroupChainBrokenAfter();
    	}
    if ( iChainedFrom )
    	{
    	iChainedFrom->iChainedTo = NULL;
    	}
    
    if (iModel)
        {
        TInt offset;
        TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)CreateWindowAttributes(offset, sizeof(TAlfWindowAttributes));
        windowAttributes->iWindowNodeType = iType; 
        windowAttributes->iScreenNumber = iScreenNumber; 

        iModel->Server().Bridge()->AddData( EAlfDSDestroyWindow, 
                iGroupId, 
                iId, 
                (TAny*)offset );
        iWindow = 0; // just in case
        }
    RemoveDependencies( iParent->iChild );
    };

// ---------------------------------------------------------------------------
// constructor
// ---------------------------------------------------------------------------
//
CAlfNodeAnim::CAlfNodeAnim( )
    {
    iType = MWsWindowTreeNode::EWinTreeNodeAnim;
     }

CAlfNodeAnim::~CAlfNodeAnim( )
    {
    if ( iParent )
        {
        RemoveDependencies( iParent->iAnimChild );
        }
    }

// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfNodeAnim::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream  )
	{
	CAlfNodeVisual::ConstructL( aModel, aStream );
	TInt32 parentId = aStream->ReadUint32L();

	// TODO: 
	ResolveParent( parentId, iId );
	CreateWindowL(0,0,iParent->iId); // Currently renderstage does not deliver ws/wg handles
	UpdateOrdinalPosition();
	}

// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CAlfNodeAnim* CAlfNodeAnim::NewL( CAlfHierarchyModel* aModel, RMemReadStream* aStream, TInt aScreenNumber  )
    {
    CAlfNodeAnim* self = new(ELeave)CAlfNodeAnim();
    CleanupStack::PushL( self );
    self->iScreenNumber = aScreenNumber;
    self->ConstructL( aModel, aStream ); 
    CleanupStack::Pop( self );
    return self;
    }


// ---------------------------------------------------------------------------
// constructor
// ---------------------------------------------------------------------------
//
CAlfNodeSprite::CAlfNodeSprite( )
    {
    iType = MWsWindowTreeNode::EWinTreeNodeSprite;
    }

CAlfNodeSprite::~CAlfNodeSprite( )
    {
    if ( iParent )
        {
        RemoveDependencies( iParent->iSpriteChild );
        }
    }
// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfNodeSprite::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream  )
	{
	CAlfNodeVisual::ConstructL( aModel, aStream );
	TInt32 parentId = aStream->ReadUint32L();

	// TODO: 
	ResolveParent( parentId, iId );
	CreateWindowL(0,0,iParent->iId); // Currently renderstage does not deliver ws/wg handles
	// Sprite may not be first in its group
	UpdateOrdinalPosition();
	}

// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CAlfNodeSprite* CAlfNodeSprite::NewL( CAlfHierarchyModel* aModel, RMemReadStream* aStream, TInt aScreenNumber  )
    {
    CAlfNodeSprite* self = new(ELeave)CAlfNodeSprite();
    CleanupStack::PushL( self );
    self->iScreenNumber = aScreenNumber;
    self->ConstructL( aModel, aStream ); 
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// constructor
// ---------------------------------------------------------------------------
//
CAlfNodeTextCursor::CAlfNodeTextCursor( )
    {
    iType = MWsWindowTreeNode::EWinTreeNodeStandardTextCursor;
    }

// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfNodeTextCursor::ConstructL( CAlfHierarchyModel* aModel, RMemReadStream* aStream  )
    {
    CAlfNode::ConstructL( aModel, aStream );
    iCursorType = aStream->ReadInt32L();
    aStream->ReadL( (TUint8*)&iRect, sizeof(TRect));
    aStream->ReadL( (TUint8*)&iClipRect, sizeof(TRect));
    iSize = iRect.Size();
    iOrigin = iRect.iTl;
    
    iFlags = aStream->ReadInt32L();
    iColor = aStream->ReadInt32L();
    iFlashInterval = aStream->ReadInt32L(); 
    TInt32 parentId = aStream->ReadUint32L();
    
    // TODO: 
    ResolveParent( parentId, iId );
    
    CreateWindowL(0,0,iParent->iId); // Currently renderstage does not deliver ws/wg handles
    TInt offset;
    // pass rest of the cursor data
    TAlfCursorDataBufferAttributes* attributes = (TAlfCursorDataBufferAttributes*)CreateWindowAttributes(offset, sizeof(TAlfCursorDataBufferAttributes));
    attributes->iColor = iColor;
    attributes->iFlags = iFlags;
    attributes->iFlashInterval = iFlashInterval;
    attributes->iScreenNumber = iScreenNumber;
    
    aModel->Server().Bridge()->AddData( EAlfDSSetCursorData, 
            iGroupId, 
            iId, 
            (TAny*)offset );
    
    UpdateOrdinalPosition();
    }

// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CAlfNodeTextCursor* CAlfNodeTextCursor::NewL( CAlfHierarchyModel* aModel, RMemReadStream* aStream, TInt aScreenNumber  )
    {
    CAlfNodeTextCursor* self = new(ELeave)CAlfNodeTextCursor();
    CleanupStack::PushL( self );
    self->iScreenNumber = aScreenNumber;
    self->ConstructL( aModel, aStream ); 
    CleanupStack::Pop( self );
    return self;
    }

void CAlfNodeTextCursor::AttributeChangedL( RMemReadStream* aStream )
    {
    // TODO: PASS FORWARD!!!
    TInt attribute = aStream->ReadInt32L();
    switch ( attribute )
        {
        case MWsWindowTreeObserver::ECursorType:
            {
            iCursorType = aStream->ReadInt32L();
            break;
            }
        case MWsWindowTreeObserver::ECursorClipRect:
            {
            aStream->ReadL( (TUint8*)&iClipRect, sizeof(TRect));
            break;
            }

        case MWsWindowTreeObserver::ECursorFlags:
            {
            iFlags = aStream->ReadInt32L();
            break;
            }

        case MWsWindowTreeObserver::ECursorColor:
            {
            iColor = aStream->ReadInt32L();
            break;
            }
        }
    TInt offset;
    TAlfCursorDataBufferAttributes* attributes = (TAlfCursorDataBufferAttributes*)CreateWindowAttributes(offset, sizeof(TAlfCursorDataBufferAttributes));
       attributes->iColor = iColor;
       attributes->iFlags = iFlags;
       attributes->iFlashInterval = iFlashInterval;
       attributes->iScreenNumber = iScreenNumber;
       __ALFLOGSTRING("Forwarding cursor data");
       iModel->Server().Bridge()->AddData( EAlfDSSetCursorData, 
               iGroupId, 
               iId, 
               (TAny*)offset );
    }
CAlfNodeTextCursor::~CAlfNodeTextCursor( )
    {
    // text cursor is the only text cursor in its parent. No need to check siblings.
    if(iParent)
        {
        iParent->iTextCursor = NULL;
        }
    // RemoveNode is called instead of RemoveDependeciesL, because this node has no depencies.
    if(iModel)
        {
        iModel->RemoveNode( iId );
        }
    }

// end of file

