uifw/AvKon/aknhlist/src/akntree.cpp
changeset 0 2f259fa3e83a
child 7 08e69e956a8c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/aknhlist/src/akntree.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1463 @@
+/*
+* Copyright (c) 2006, 2007 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 for CAknTree class.
+*
+*/
+
+
+
+#include <AknUtils.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknsUtils.h>
+#include <avkon.mbg>
+#include <AknMarqueeControl.h>
+
+#include "akntree.h"
+#include "akntreelist.h"
+#include "akntreeordering.h"
+#include "aknhlistlib.h"
+#include "akntreeiterator.h"
+#include "akntreelisticon.h"
+#include "akncustomtreeordering.h"
+#include "akntreelistinternalconstants.h"
+
+const TInt KObserverArrayGranularity = 1;
+
+// Tree flag definitions
+enum TAknTreeFlags
+    {
+    ETabModeFunctionIndicators
+    };
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CAknTree* CAknTree::NewL( CAknTreeList& aList, CAknTreeOrdering* aOrdering )
+    {
+    CAknTree* self = new( ELeave ) CAknTree( aList, aOrdering );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CAknTree::~CAknTree()
+    {
+    delete iOrdering; iOrdering = NULL;
+    iCustomOrdering = NULL;
+    iObservers.Close();
+    iItems.Close();
+    iIcons.ResetAndDestroy();
+    delete iMarquee; iMarquee = NULL;
+    iMarqueeItem = NULL;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Id for the given item.
+// ---------------------------------------------------------------------------
+//
+TAknTreeItemID CAknTree::Id( const CAknTreeItem* aItem ) const
+    {
+    if ( aItem == this )
+        {
+        return KAknTreeIIDRoot;
+        }
+    else
+        {
+        return reinterpret_cast<TInt>( aItem );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets ordering for tree items. Previously set ordering is deleted and
+// customized ordering interface discarded.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::SetOrdering( CAknTreeOrdering* aOrdering, TBool aDrawNow )
+    {
+    delete iOrdering;
+    iOrdering = aOrdering;
+
+    iCustomOrdering = NULL;
+
+    Sort( aDrawNow );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets custom ordering for tree items.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::SetCustomOrdering( MAknCustomTreeOrdering* aOrdering,
+    TBool aDrawNow )
+    {
+    iCustomOrdering = aOrdering;
+
+    delete iOrdering;
+    iOrdering = NULL;
+
+    Sort( aDrawNow );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sorts the specified tree node.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::Sort( TAknTreeItemID aNode, TBool aSortDescendants,
+    TBool aDrawNow )
+    {
+    // The sorting can be done only when ordering is set for the tree.
+    if ( iCustomOrdering || iOrdering )
+        {
+        CAknTreeNode* node = Node( aNode );
+        node->Sort();
+        if ( aSortDescendants )
+            {
+            // Iterate through the descendants of the node and sort
+            // each descendant node separately.
+            TAknTreeIterator iterator( node, NULL );
+            while ( iterator.HasNext() )
+                {
+                node = iterator.Next()->Node();
+                if ( node )
+                    {
+                    node->Sort();
+                    }
+                }
+            }
+        }
+
+    NotifyObservers( MAknTreeObserver::ETreeSorted, this, aDrawNow );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Compares two tree list items.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::Compare( const CAknTreeItem& aFirst,
+    const CAknTreeItem& aSecond ) const
+    {
+    TInt value = NULL;
+    if ( iCustomOrdering )
+        {
+        value = iCustomOrdering->Compare( Id( &aFirst ), Id( &aSecond ) );
+        }
+    else if ( iOrdering )
+        {
+        value = iOrdering->Compare( aFirst, aSecond );
+        }
+    else
+        {
+        TInt first = KMaxTInt;
+        TInt second = KMaxTInt;
+        if ( aFirst.Parent() )
+            {
+            first = aFirst.Parent()->Index( &aFirst );
+            }
+        if  ( aSecond.Parent() )
+            {
+            second = aSecond.Parent()->Index( &aSecond );
+            }
+        value = first - second;
+        }
+    return value;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the number of items in the tree.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::ItemCount() const
+    {
+    return iItems.Count();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the number of visible items in the tree.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::VisibleItemCount() const
+    {
+    return VisibleDescendantCount();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the index of specified item. The index equals to the number of
+// tree items in the tree structure before the specified item.
+// The value KErrNotFound is returned, if the specified item is not found,
+// and this applies also to the root node.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::ItemIndex( const CAknTreeItem* aItem ) const
+    {
+    TInt count = KErrNotFound; // ( -1 )
+    if ( iItems.FindInAddressOrder( aItem ) >= 0 )
+        {
+        const CAknTreeItem* item = aItem;
+        const CAknTreeNode* parent = item->Parent();
+        while ( parent )
+            {
+            // Add the number of descendants of each sibling preceeding the
+            // item to the count.
+            const TInt index = parent->Index( item );
+            __ASSERT_DEBUG( index >= 0, User::Invariant() );
+            for ( TInt ii = 0; ii < index; ++ii )
+                {
+                const CAknTreeNode* node = parent->Child( ii )->Node();
+                if ( node )
+                    {
+                    count += node->DescendantCount();
+                    }
+                }
+
+            // Add the item and its preceeding siblings to the count.
+            count += index + 1;
+
+            item = parent;
+            parent = item->Parent();
+            }
+        }
+    return count;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Similar to ItemIndex, but returns the index from subset of items that
+// belong to expanded part of the tree.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::VisibleItemIndex( const CAknTreeItem* aItem ) const
+    {
+    TInt count = KErrNotFound; // ( -1 )
+    if ( iItems.FindInAddressOrder( aItem ) >= 0 )
+        {
+        const CAknTreeItem* item = aItem;
+        const CAknTreeNode* parent = item->Parent();
+        while ( parent )
+            {
+            if ( !parent->IsExpanded() )
+                {
+                return KErrNotFound;
+                }
+
+            // Add the number of visible descentants of each sibling preceeding
+            // the item to the count.
+            const TInt index = parent->Index( item );
+            __ASSERT_DEBUG( index >= 0, User::Invariant() );
+            for ( TInt ii = 0; ii < index; ++ii )
+                {
+                const CAknTreeNode* node = parent->Child( ii )->Node();
+                if ( node )
+                    {
+                    count += node->VisibleDescendantCount();
+                    }
+                }
+
+            // Add the item and its preceeding siblings to the count.
+            count += index + 1;
+
+            // All ancestors of specified item has to be expanded in order to
+            // the item to be in expanded tree structure.
+            if ( parent->IsExpanded() )
+                {
+                item = parent;
+                parent = item->Parent();
+                }
+            else
+                {
+                // Specified item is not visible, KErrNotFound returned.
+                parent = NULL;
+                count = KErrNotFound;
+                }
+            }
+        }
+    return count;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the tree item at the specified index of the expanded tree.
+// ---------------------------------------------------------------------------
+//
+CAknTreeItem* CAknTree::VisibleItem( TInt aIndex ) const
+    {
+    if ( aIndex < 0 || aIndex >= iItems.Count() )
+        {
+        return NULL;
+        }
+
+    TAknTreeIterator iterator = Iterator();
+    while( aIndex && iterator.HasNext() )
+        {
+        iterator.Next();
+        --aIndex;
+        }
+
+    return iterator.Next();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the depth of the tree. Iterates through the whole tree structure.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::Depth() const
+    {
+    TAknTreeIterator iterator = Iterator();
+    TInt depth = 0;
+    while ( iterator.HasNext() )
+        {
+        CAknTreeItem* item = iterator.Next();
+        depth = Max( depth, item->Level() );
+        }
+    return depth;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Finds the specified item from the sorted array of tree items. The constants
+// KAknTreeIIDRoot and KAknTreeIIDNone are handled as special cases.
+// 
+// Note: Recently used items could be cached somehow to eliminate the need to
+// lookup them from the table when consecutive calls refer to the same items,
+// for example, when adding several items to the same node.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::GetItem( TAknTreeItemID aItemId, CAknTreeItem*& aItem ) const
+    {
+    TInt error = KErrNone;
+    if ( aItemId == KAknTreeIIDRoot )
+        {
+        aItem = const_cast<CAknTree*>( this );
+        }
+    else if ( aItemId == KAknTreeIIDNone )
+        {
+        error = KErrNotFound;
+        }
+    else
+        {
+        TInt index = iItems.FindInAddressOrder(
+            reinterpret_cast<CAknTreeItem*>( aItemId ) );
+        if ( index == KErrNotFound )
+            {
+            error = KErrNotFound;
+            }
+        else
+            {
+            aItem = iItems[index];
+            }
+        }
+    return error;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Retrieves an item from the tree structure. Panics if the item is not found.
+// ---------------------------------------------------------------------------
+//
+CAknTreeItem* CAknTree::Item( TAknTreeItemID aItemId ) const
+    {
+    CAknTreeItem* item = NULL;
+    TInt error = GetItem( aItemId, item );
+    __ASSERT_ALWAYS( item && !error, Panic( EAknHListPanicInvalidItemID ) );
+    return item;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Retrieves a node from the tree structure. Panics if the node is not found,
+// or if the specified item is not a node.
+// ---------------------------------------------------------------------------
+//
+CAknTreeNode* CAknTree::Node( TAknTreeItemID aNodeId ) const
+    {
+    CAknTreeNode* node = Item( aNodeId )->Node();
+    __ASSERT_ALWAYS( node, Panic( EAknHListPanicInvalidItemType ) );
+    return node;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Adds an item to the tree structure.
+// ---------------------------------------------------------------------------
+//
+TAknTreeItemID CAknTree::AddItemL( CAknTreeItem* aItem,
+    TAknTreeItemID aParent, TBool aDrawNow )
+    {
+    __ASSERT_DEBUG( aItem, User::Invariant() );
+
+    // Add item to the specified parent node.
+    CAknTreeNode* parent = Node( aParent );
+
+    if ( iOrdering )
+        {
+        // Let ordering determine the position of the new child.
+        parent->AddChildL( aItem );
+        }
+    else
+        {
+        // Append to the end, as custom ordering cannot be used to determine
+        // the correct position when inserting new items to the tree.
+        parent->AddChildL( aItem, parent->ChildCount() );
+        }
+
+    // Store pointer also in lookup table.
+    TInt error = iItems.InsertInAddressOrder( aItem );
+    if ( error )
+        {
+        parent->RemoveChild( aItem );
+        User::Leave( error );
+        }
+
+    aItem->SetParent( parent );
+
+    NotifyObservers( MAknTreeObserver::EItemAdded, aItem, aDrawNow );
+
+    return Id( aItem );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Moves the specified item to specified target node. The method has to make
+// sure that the target node is not a descendant of the moved item in order
+// to keep the tree structure intact.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::MoveItemL( TAknTreeItemID aItem, TAknTreeItemID aTargetNode,
+    TBool aDrawNow )
+    {
+    CAknTreeItem* item = Item( aItem );
+    CAknTreeNode* targetNode = Node( aTargetNode );
+
+    // The current parent of the moved item.
+    CAknTreeNode* parent = item->Parent();
+
+    // Move is necessary only when target node differs from current node.
+    if ( targetNode != parent )
+        {
+        // Check that the moved item is neither the target node nor an ancestor
+        // of target node. This should also ensure that the root is not moved.
+        CAknTreeNode* ancestor = targetNode;
+        while ( ancestor )
+            {
+            if ( ancestor == item )
+                {
+                User::Leave( KErrArgument );
+                }
+            ancestor = ancestor->Parent();
+            }
+
+        // Move the item to the target node.
+        targetNode->AddChildL( item );
+        item->SetParent( targetNode );
+        if ( parent )
+            {
+            parent->RemoveChild( item );
+            }
+        
+        NotifyObservers( MAknTreeObserver::EItemMoved, item, aDrawNow );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Removes an item from the tree structure. If the specified item is not
+// found, method is paniced with panic code EAknHListPanicInvalidItemID.
+//
+// When removed item is a node with descendants, the node and its descendants
+// are removed from the list separately and each removal is also reported
+// separately to the observers.
+//
+// Note: Observers are notified of the removal before the item is actually
+// removed from the tree and deleted, so that the observers can still query
+// the item's position in the tree.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::RemoveItem( TAknTreeItemID aItem, TBool aDrawNow )
+    {
+    // Get the item from the array.    
+    CAknTreeItem* item = Item( aItem );
+    
+    TBool drawNow( EFalse );
+
+    // Remove from array and delete the descendants of node non-recursively.
+    if ( item->IsNode() )
+        {
+        TAknTreeIterator iterator = Iterator( item->Node(), NULL );
+        CAknTreeItem* current = iterator.Last();
+        iterator.SetCurrent( current ); 
+        while ( current )
+            {
+            CAknTreeItem* previous = iterator.Previous();
+            if ( previous == NULL)
+            	{
+            	drawNow = aDrawNow;
+            	}
+
+            // Notify tree observers of removal before the item is removed.
+            NotifyObservers( MAknTreeObserver::EItemRemoveBegin, current, EFalse );
+
+            // Remove item from the table.
+            TInt index = iItems.FindInAddressOrder( current );
+            __ASSERT_DEBUG( index >= 0, User::Invariant()  );
+            iItems.Remove( index );
+
+            // Remove item from its parent node.
+            CAknTreeNode* parent = current->Parent();
+            __ASSERT_DEBUG( parent, User::Invariant() );
+            parent->RemoveChild( current );
+            current->SetParent( NULL );
+
+            __ASSERT_DEBUG( current->IsLeaf() || 
+                current->Node()->ChildCount() == 0, User::Invariant() );
+
+            // Notify tree observers when the item has been removed.
+            NotifyObservers( MAknTreeObserver::EItemRemoveEnd, current, drawNow );
+
+            // Notify also tree list observers of removal.
+            iList.NotifyObservers( MAknTreeListObserver::EItemRemoved,
+                Id( current ) );
+
+            delete current;
+            current = previous;
+            }
+        }
+
+    // Remove the specified item, unless it is the root node.
+    if ( item != this )
+        {
+        // Notify tree observers before removing the item.
+        NotifyObservers( MAknTreeObserver::EItemRemoveBegin, item, EFalse );
+
+        // Remove the item from array and from the tree and delete it.
+        TInt index = iItems.FindInAddressOrder( item );
+        __ASSERT_DEBUG( index >= 0, User::Invariant() );
+        iItems.Remove( index );
+
+        CAknTreeNode* parent = item->Parent();
+        __ASSERT_DEBUG( parent, User::Invariant() );
+        parent->RemoveChild( item );
+        item->SetParent( NULL );
+
+        __ASSERT_DEBUG( item->IsLeaf() || item->Node()->ChildCount() == 0,
+            User::Invariant() );
+
+        // Notify tree observers after the item has been removed.
+        NotifyObservers( MAknTreeObserver::EItemRemoveEnd, item, aDrawNow );
+
+        // Notify also tree list observers of removal.
+        iList.NotifyObservers( MAknTreeListObserver::EItemRemoved,
+            Id( item ) );
+
+        delete item;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Expands the specified node.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::ExpandNode( TAknTreeItemID aNode, TBool aDrawNow )
+    {
+    CAknTreeNode* node = Node( aNode );
+    DoExpandNode( node, aDrawNow );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Collapses the specified node and removes the children from collapsed node
+// that are not set perisitent or do not contain any persistent descendants.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::CollapseNode( TAknTreeItemID aNode, TBool aDrawNow )
+    {
+    CAknTreeNode* node = Node( aNode );
+
+    node->Collapse();
+    iList.NotifyObservers( MAknTreeListObserver::ENodeCollapsed, aNode );
+    NotifyObservers( MAknTreeObserver::ENodeCollapsed, node, aDrawNow );
+
+    if ( aNode != KAknTreeIIDRoot )
+        {
+        // Remove all the children from the node that are not persistent or
+        // marked and do not contain any persistent or marked descendants.
+        for ( TInt ii = node->ChildCount() - 1; ii >= 0; --ii )
+            {
+            CAknTreeItem* item = node->Child( ii );
+            __ASSERT_DEBUG( item, User::Invariant() );
+            if ( item->IsRemovableFromCollapsedNode() )
+                {
+                RemoveItem( Id( item ), EFalse );
+                }
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Checks whether the specified node is expanded.
+// ---------------------------------------------------------------------------
+//
+TBool CAknTree::IsExpanded( TAknTreeItemID aNode ) const
+    {
+    return Node( aNode )->IsExpanded();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the child count for the specified node.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::ChildCount( TAknTreeItemID aNode ) const
+    {
+    return Node( aNode )->ChildCount();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the item ID of specified child for a tree node.
+// ---------------------------------------------------------------------------
+//
+TAknTreeItemID CAknTree::Child( TAknTreeItemID aNode, TInt aIndex ) const
+    {
+    return Id( Node( aNode )->Child( aIndex ) );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the item ID of a parent of specified item.
+// ---------------------------------------------------------------------------
+//
+TAknTreeItemID CAknTree::Parent( TAknTreeItemID aItem ) const
+    {
+    return Id( Item( aItem )->Parent() );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Adds a tree observer.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::AddObserverL( MAknTreeObserver* aObserver )
+    {
+    iObservers.InsertInAddressOrderL( aObserver );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Removes a tree observer.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::RemoveObserver( MAknTreeObserver* aObserver )
+    {
+    TInt index = iObservers.FindInAddressOrder( aObserver );
+    if ( index != KErrNotFound )
+        {
+        iObservers.Remove( index );
+        return KErrNone;
+        }
+    else
+        {
+        return KErrNotFound;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Checks whether the specified item is marked.
+// ---------------------------------------------------------------------------
+//
+TBool CAknTree::IsMarked( TAknTreeItemID aItem ) const
+    {
+    return Item( aItem )->IsMarked();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets the specified item marked or unmarked.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::SetMarked( TAknTreeItemID aItem, TBool aMarked, TBool aDrawNow )
+    {
+    CAknTreeItem* item = Item( aItem );
+    if ( item->IsMarkable() )
+        {        
+        if ( item->IsNode() )
+            {
+            // When specified item is a node, the same marking is set to
+            // every descendant as well.
+            TAknTreeIterator iterator = Iterator( item->Node(), NULL );
+            while ( iterator.HasNext() )
+                {
+                iterator.Next()->SetMarked( aMarked );
+                }
+            }
+
+        item->SetMarked( aMarked );
+        
+        if ( aMarked == EFalse)
+        	{
+        	CAknTreeNode* parent = item->Parent();
+        	if ( parent && parent->IsNode() && parent->IsMarkable() && parent->IsMarked() )
+        		{
+        		TAknTreeIterator iterator = Iterator( parent->Node(), NULL );
+            	TBool marked = EFalse;	
+            	
+            	while ( iterator.HasNext() )
+                	{
+                	CAknTreeItem* item = iterator.Next();
+                	if ( item->IsMarkable() && item->IsMarked() )
+                		{
+                		marked = ETrue;
+                		break;
+                		}
+                	}
+                // all items under the parent are unmarked, unmark parent	
+        		if ( !marked )
+        			{
+        			parent->SetMarked( EFalse );
+        			}
+        		
+        		}
+        	
+        	}
+        
+        iList.NotifyObservers( aMarked ? MAknTreeListObserver::EItemMarked :
+            MAknTreeListObserver::EItemUnmarked, Id( item ) );
+        NotifyObservers( MAknTreeObserver::EItemModified, item, aDrawNow );        
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Enables/disables marking for specified list item.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::EnableMarking( TAknTreeItemID aItem, TBool aEnable )
+    {
+    CAknTreeItem* item = Item( aItem );
+    item->SetMarkable( aEnable );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Gets all the marked items from the specified node to the given array.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::GetMarkedItemsL( TAknTreeItemID aNode,
+    RArray<TAknTreeItemID>& aMarkedItems ) const
+    {
+    aMarkedItems.Reset();
+    if ( aNode == KAknTreeIIDRoot )
+        {
+        // Get marked items from the tree by iterating through array.
+        CAknTreeItem* item = NULL;
+        const TInt count = iItems.Count();
+        for ( TInt ii = 0; ii < count; ++ii )
+            {
+            item = iItems[ii];
+            __ASSERT_DEBUG( item, User::Invariant() );
+            if ( item->IsMarked() )
+                {
+                aMarkedItems.AppendL( Id( item ) );
+                }
+            }
+        }
+    else
+        {
+        // Get marked items only from the specified node with iterator.
+        TAknTreeIterator iterator( Node( aNode ), NULL );
+        CAknTreeItem* item = NULL;
+        while ( iterator.HasNext() )
+            {
+            item = iterator.Next();
+            __ASSERT_DEBUG( item, User::Invariant() );
+            if ( item->IsMarked() )
+                {
+                aMarkedItems.AppendL( Id( item ) );
+                }
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Checks whether the specified node is empty.
+// ---------------------------------------------------------------------------
+//
+TBool CAknTree::IsEmpty( TAknTreeItemID aNode ) const
+    {
+    return Node( aNode )->IsEmpty();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets whether the node appears as non-empty when it is empty.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::SetNonEmpty( TAknTreeItemID aNode, TBool aNonEmpty,
+    TBool aDrawNow )
+    {
+    CAknTreeNode* node = Node( aNode );
+    node->SetNonEmpty( aNonEmpty );
+    NotifyObservers( MAknTreeObserver::EItemModified, node, aDrawNow );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Checks whether the specified item is persistent.
+// ---------------------------------------------------------------------------
+//
+TBool CAknTree::IsPersistent( TAknTreeItemID aItem ) const
+    {
+    return Item( aItem )->IsPersistent();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets the specified item persistent or non-persistent.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::SetPersistent( TAknTreeItemID aItem, TBool aPersistent )
+    {
+    Item( aItem )->SetPersistent( aPersistent );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns iterator for the expanded tree structure.
+// ---------------------------------------------------------------------------
+//
+TAknTreeIterator CAknTree::Iterator() const
+    {
+    return TAknTreeIterator( const_cast<CAknTree*>( this ),
+        KAknSkipCollapsedNodeContents );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns iterator for the specified node.
+// ---------------------------------------------------------------------------
+//
+TAknTreeIterator CAknTree::Iterator( CAknTreeNode* aNode, TUint aFlags ) const
+    {
+    return TAknTreeIterator( aNode, aFlags );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Notifies the observers that an item in the tree has been modified.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::ItemModified( CAknTreeItem* aItem )
+    {
+    NotifyObservers( MAknTreeObserver::EItemModified, aItem, ETrue );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Adds an icon to the tree and returns the index of created icon.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::AddIconL( const TAknsItemID& aId, const TDesC& aFilename,
+    TInt aBitmapId, TInt aMaskId, TScaleMode aScaleMode )
+    {
+    TInt newIconId = AvailableIconId();
+    CAknTreeListIcon* icon = CAknTreeListIcon::NewLC( newIconId, aId,
+        aFilename, aBitmapId, aMaskId, aScaleMode );
+    AddIconL( icon );
+    CleanupStack::Pop( icon );
+    return newIconId;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Adds an icon to the tree and returns the index of created icon.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::AddIconL( CFbsBitmap* aIcon, CFbsBitmap* aMask, 
+    TBool aTransferOwnership, TScaleMode aScaleMode )
+    {
+    TInt newIconId = AvailableIconId();
+    CAknTreeListIcon* icon = CAknTreeListIcon::NewLC( newIconId, aIcon, aMask,
+        aTransferOwnership, aScaleMode );
+    AddIconL( icon );
+    CleanupStack::Pop( icon );
+    return newIconId;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Adds colored icon to the tree.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::AddColorIconL( const TAknsItemID& aId,
+    const TAknsItemID& aColorId, TInt aColorIndex, const TDesC& aFilename,
+    TInt aBitmapId, TInt aMaskId, TRgb aDefaultColor, TScaleMode aScaleMode )
+    {
+    TInt newIconId = AvailableIconId();
+    CAknTreeListIcon* icon = CAknTreeListIcon::NewLC( newIconId, aId,
+        aColorId, aColorIndex, aFilename, aBitmapId, aMaskId, aDefaultColor,
+        aScaleMode );
+    AddIconL( icon );
+    CleanupStack::Pop( icon );
+    return newIconId;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets icon for specified ID.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::SetIconL( TInt aIconId, const TAknsItemID& aId,
+    const TDesC& aFilename, TInt aBitmapId, TInt aMaskId,
+    TScaleMode aScaleMode )
+    {
+    CAknTreeListIcon* icon = CAknTreeListIcon::NewLC( aIconId, aId, aFilename,
+        aBitmapId, aMaskId, aScaleMode );
+    AddIconL( icon );
+    CleanupStack::Pop( icon );
+    }
+
+
+void CAknTree::SetIconL( TInt aIconId, CFbsBitmap* aIcon, CFbsBitmap* aMask,
+    TBool aTransferOwnership, TScaleMode aScaleMode )
+    {
+    CAknTreeListIcon* icon = CAknTreeListIcon::NewLC( aIconId, aIcon, aMask,
+        aTransferOwnership, aScaleMode );
+    AddIconL( icon );
+    CleanupStack::Pop( icon );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sets color icon for specified ID.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::SetColorIconL( TInt aIconId, const TAknsItemID& aId,
+    const TAknsItemID& aColorId, TInt aColorIndex, const TDesC& aFilename,
+    TInt aBitmapId, TInt aMaskId, TRgb aDefaultColor, TScaleMode aScaleMode )
+    {
+    CAknTreeListIcon* icon = CAknTreeListIcon::NewLC( aIconId, aId, aColorId,
+        aColorIndex, aFilename, aBitmapId, aMaskId, aDefaultColor,
+        aScaleMode );
+    AddIconL( icon );
+    CleanupStack::Pop( icon );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Removes previously added icon from the tree.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::RemoveIconL( TInt aIconId )
+    {
+    // Pre-defined icons constructed by the tree cannot be removed.
+    if ( aIconId <= EPreDefinedIconIdRange )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TInt index = iIcons.FindInOrder( aIconId, CAknTreeListIcon::CompareId );
+    if ( index != KErrNotFound )
+        {
+        delete iIcons[index];
+        iIcons.Remove( index );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns pointer to the requested icon.
+// ---------------------------------------------------------------------------
+//
+CAknTreeListIcon* CAknTree::Icon( TInt aIconId ) const
+    {
+    CAknTreeListIcon* icon = NULL;
+    TInt index = iIcons.FindInOrder( aIconId, CAknTreeListIcon::CompareId );
+    if ( index >= NULL )
+        {
+        icon = iIcons[index];
+        }
+    return icon;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Draws the specified icon.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::DrawIcon( TInt aIconId, const TSize& aSize, CWindowGc& aGc,
+    const TPoint& aPoint, const TRect& aSourceRect )
+    {
+    TInt value = KErrNotFound;
+    CAknTreeListIcon* icon = Icon( aIconId );
+    if ( icon && icon->Bitmap() )
+        {
+        icon->SetSize( aSize );
+        aGc.BitBltMasked( aPoint, icon->Bitmap(), aSourceRect,
+            icon->Mask(), ETrue );
+        value = KErrNone;
+        }
+    return value;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Draws the given text string.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::DrawText( CWindowGc& aGc, const TRect& aRect,
+    const TAknTextComponentLayout& aTextLayout, const TDesC& aText,
+    const CFont* aFont, const CAknTreeItem* aItem, TBool aFocused,
+    TBool aMarquee )
+    {
+    TRgb textColor;
+    TAknsQsnTextColorsIndex index = 
+        aFocused ? EAknsCIQsnTextColorsCG10 : EAknsCIQsnTextColorsCG6;
+    AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
+        KAknsIIDQsnTextColors, index );
+
+    TAknLayoutText layoutText;
+    layoutText.LayoutText( aRect, aTextLayout.LayoutLine(), aFont );
+
+    if ( iMarquee )
+        {
+        if ( aFocused && aItem != iMarqueeItem )
+            {
+            iMarqueeItem = aItem;
+            iMarquee->Reset();
+            }
+        else if ( !aFocused && aItem == iMarqueeItem )
+            {
+            iMarqueeItem = NULL;
+            iMarquee->Stop();
+            }
+        }
+
+    // Marquee scrolling is used when the given text does not fit in the given
+    // layout rectangle, but only if text is focused, marquee is allowed to be
+    // used with the given text, and marquee is enabled for the list.
+    TBool useMarquee = aFocused && aMarquee && iMarquee &&
+        iMarquee->IsMarqueeOn() && layoutText.TextRect().Width() < 
+            layoutText.Font()->TextWidthInPixels( aText );
+    
+    if ( !useMarquee || iMarquee->DrawText( aGc, aRect, aTextLayout, aText,
+            aFont, textColor ) )
+        {
+        layoutText.DrawText( aGc, aText, ETrue, textColor );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handles skin change by reconstruction all the used icons.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::HandleSkinChangeL()
+    {
+    for ( TInt ii = 0; ii < iIcons.Count(); ++ii )
+        {
+        iIcons[ii]->ReconstructL();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Enables or disables marquee scrolling.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::EnableMarquee( TBool aEnable )
+    {
+    if ( iMarquee )
+        {
+        iMarquee->EnableMarquee( aEnable );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns whether marquee scrolling is enabled.
+// ---------------------------------------------------------------------------
+//
+TBool CAknTree::IsMarqueeOn() const
+    {
+    return iMarquee ? iMarquee->IsMarqueeOn() : EFalse;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Redraw request from marquee control.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::MarqueeRedrawRequest( TAny* aThis )
+    {
+    CAknTree* tree = static_cast<CAknTree*>( aThis );
+    return tree ? tree->DoMarqueeRedrawRequest() : NULL;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Enables tabulator mode expand/collapse function indicators.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::EnableTabModeFunctionIndicatorsL( TBool aEnable )
+    {
+    if ( iFlags.IsSet( ETabModeFunctionIndicators ) && !aEnable )
+        {
+        // Change to normal expand/collapse function indicators.
+        SetIconL( ECollapseFunctionIndication, KAknsIIDQgnIndiHlColSuper,
+            AknIconUtils::AvkonIconFileName(),
+            EMbmAvkonQgn_indi_hl_col_super,
+            EMbmAvkonQgn_indi_hl_col_super_mask,
+            EAspectRatioPreserved );
+
+        SetIconL( EExpandFunctionIndication, KAknsIIDQgnIndiHlExpSuper,
+            AknIconUtils::AvkonIconFileName(),
+            EMbmAvkonQgn_indi_hl_exp_super,
+            EMbmAvkonQgn_indi_hl_exp_super_mask,
+            EAspectRatioPreserved );
+
+        iFlags.Clear( ETabModeFunctionIndicators );
+        }
+    else if ( !iFlags.IsSet( ETabModeFunctionIndicators ) && aEnable )
+        {
+        // Change to tab mode expand/collapse function indicators.
+        SetIconL( ECollapseFunctionIndication, KAknsIIDQgnIndiHlTabColSuper,
+            AknIconUtils::AvkonIconFileName(),
+            EMbmAvkonQgn_indi_col_super,
+            EMbmAvkonQgn_indi_col_super_mask,
+            EAspectRatioPreserved );
+
+        SetIconL( EExpandFunctionIndication, KAknsIIDQgnIndiHlTabExpSuper,
+            AknIconUtils::AvkonIconFileName(),
+            EMbmAvkonQgn_indi_exp_super,
+            EMbmAvkonQgn_indi_exp_super_mask,
+            EAspectRatioPreserved );
+
+        iFlags.Set( ETabModeFunctionIndicators );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Checks whether tabulator mode expand/collapse function indicators are
+// enabled.
+// ---------------------------------------------------------------------------
+//
+TBool CAknTree::TabModeFunctionIndicators() const
+    {
+    return iFlags.IsSet( ETabModeFunctionIndicators );
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class CAknTreeItem.
+// Returns the type of concrete item class.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::Type() const
+    {
+    return AknTreeList::KTree;
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class CAknTreeItem.
+// Instance of CAknTree is always set as tree root, so it can just return
+// pointer to itself.
+// ---------------------------------------------------------------------------
+//
+CAknTree* CAknTree::Root() const
+    {
+    return const_cast<CAknTree*>( this );
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class CAknTreeNode.
+// Changes the state of every node in the tree to expanded.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::Expand()
+    {
+    TAknTreeIterator iterator( this, NULL );
+    while ( iterator.HasNext() )
+        {
+        CAknTreeItem* item = iterator.Next();
+        if ( item->IsNode() )
+            {
+            DoExpandNode( item->Node(), EFalse );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class CAknTreeNode.
+// Changes the state of every node in the tree to collapsed.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::Collapse()
+    {
+    TAknTreeIterator iterator( this, NULL );
+    iterator.SetCurrent( iterator.Last() );
+    iterator.Next();
+    while( iterator.HasPrevious() )
+        {
+        CAknTreeItem* item = iterator.Previous();
+        if ( item->IsNode() )
+            {
+            // Note: Might be a good idea to add for internal use an overload
+            // accepting the pointer to the collapsed node as parameter.
+            CollapseNode( Id( item->Node() ), EFalse );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// C++ constructor.
+// ---------------------------------------------------------------------------
+//
+CAknTree::CAknTree( CAknTreeList& aList, CAknTreeOrdering* aOrdering )
+    : CAknTreeNode( EExpanded ),
+      iList( aList ),
+      iOrdering( aOrdering ),
+      iObservers( KObserverArrayGranularity )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// Second phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::ConstructL()
+    {
+    TCallBack callBack( CAknTree::MarqueeRedrawRequest, this );
+    iMarquee = CAknMarqueeControl::NewL();
+    iMarquee->SetRedrawCallBack( callBack );
+
+    SetIconL( ECollapseFunctionIndication, KAknsIIDQgnIndiHlColSuper,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_indi_hl_col_super,
+        EMbmAvkonQgn_indi_hl_col_super_mask,
+        EAspectRatioPreserved );
+
+    SetIconL( EExpandFunctionIndication, KAknsIIDQgnIndiHlExpSuper,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_indi_hl_exp_super,
+        EMbmAvkonQgn_indi_hl_exp_super_mask,
+        EAspectRatioPreserved );
+
+    SetIconL( ELineBranchIndication, KAknsIIDQgnIndiHlLineBranch,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_indi_hl_line_branch,
+        EMbmAvkonQgn_indi_hl_line_branch,
+        EAspectRatioNotPreserved );
+
+    SetIconL( ELineEndIndication, KAknsIIDQgnIndiHlLineEnd,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_indi_hl_line_end,
+        EMbmAvkonQgn_indi_hl_line_end_mask,
+        EAspectRatioNotPreserved );
+
+    SetIconL( ELineStraightIndication, KAknsIIDQgnIndiHlLineStraight,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_indi_hl_line_straight,
+        EMbmAvkonQgn_indi_hl_line_straight_mask,
+        EAspectRatioNotPreserved );
+
+    SetIconL( EDefaultFileIndication, KAknsIIDQgnPropHlFile,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_prop_hl_file,
+        EMbmAvkonQgn_prop_hl_file_mask,
+        EAspectRatioPreserved );
+
+    SetIconL( EClosedFolderIndication, KAknsIIDQgnPropHlFolder,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_prop_hl_folder,
+        EMbmAvkonQgn_prop_hl_folder_mask,
+        EAspectRatioPreserved );
+
+    SetIconL( EOpenFolderIndication, KAknsIIDQgnPropHlFolderOpen,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_prop_hl_folder_open,
+        EMbmAvkonQgn_prop_hl_folder_open_mask,
+        EAspectRatioPreserved );
+
+    SetColorIconL( EMarkedIndication, KAknsIIDQgnIndiMarkedAdd,
+        KAknsIIDQsnIconColors, EAknsCIQsnIconColorsCG13,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_indi_marked_add,
+        EMbmAvkonQgn_indi_marked_add_mask,
+        KRgbBlack, EAspectRatioPreserved );
+
+    SetColorIconL( EHighlightedMarkedIndication, KAknsIIDQgnIndiMarkedAdd,
+        KAknsIIDQsnIconColors, EAknsCIQsnIconColorsCG16,
+        AknIconUtils::AvkonIconFileName(),
+        EMbmAvkonQgn_indi_marked_add,
+        EMbmAvkonQgn_indi_marked_add_mask,
+        KRgbBlack, EAspectRatioPreserved );
+
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sends the specified event to every registered observer.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::NotifyObservers( MAknTreeObserver::TEvent aEvent,
+    CAknTreeItem* aItem, TBool aDrawNow )
+    {
+    const TInt count = iObservers.Count();
+    for ( TInt ii = 0; ii < count; ++ii )
+        {
+        iObservers[ii]->HandleTreeEvent( aEvent, aItem, aDrawNow );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sends notification to tree observers when requested by the marquee control.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::DoMarqueeRedrawRequest()
+    {
+    // Makes sure the tree still contains the scrolled item before sending
+    // the notification to the observers.
+    CAknTreeItem* item;
+    if ( !GetItem( Id( iMarqueeItem ), item ) )
+        {
+        ItemModified( item );
+        return 1;
+        }
+    return NULL;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Searches for available icon ID.
+// ---------------------------------------------------------------------------
+//
+TInt CAknTree::AvailableIconId() const
+    {
+    const TInt count = iIcons.Count();
+    TInt last = count ? iIcons[count - 1]->Id() : NULL;
+    TInt next = Max( last, EPreDefinedIconIdRange ) + 1;
+
+    if ( next <= EPreDefinedIconIdRange )
+        {
+        next = KMaxTInt;
+        TBool found = EFalse;
+        for ( TInt ii = 0; ii < count - 1 && !found; ++ii )
+            {
+            if ( iIcons[ii]->Id() < iIcons[ii + 1]->Id() - 1 )
+                {
+                next = iIcons[ii]->Id() + 1;
+                found = ETrue;
+                }
+            }
+        }
+
+    return next;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Adds icon to the icon array.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::AddIconL( CAknTreeListIcon* aIcon )
+    {
+    __ASSERT_DEBUG( aIcon, User::Invariant() );
+    TLinearOrder<CAknTreeListIcon> order( CAknTreeListIcon::Compare );
+    TInt index = iIcons.FindInOrder( aIcon, order );
+    if ( index == KErrNotFound )
+        {
+        // Add icon to the array.
+        iIcons.InsertInOrderL( aIcon, order );
+        }
+    else
+        {
+        // Replace existing icon in the array.
+        delete iIcons[index];
+        iIcons[index] = aIcon;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Sorts the list by sorting every node in the tree separately.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::Sort( TBool aDrawNow )
+    {
+    CAknTreeNode::Sort();
+    for ( TInt ii = 0; ii < iItems.Count(); ++ii )
+        {
+        CAknTreeNode* node = iItems[ii]->Node();
+        if ( node )
+            {
+            node->Sort();
+            }
+        }
+
+    NotifyObservers( MAknTreeObserver::ETreeSorted, NULL, aDrawNow );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Expands the specified node.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::DoExpandNode( CAknTreeNode* aNode, TBool aDrawNow )
+    {
+    __ASSERT_DEBUG( aNode, User::Invariant() );
+    iList.NotifyObservers( MAknTreeListObserver::ENodeExpanded, Id( aNode ) );
+    aNode->Expand();
+    NotifyObservers( MAknTreeObserver::ENodeExpanded, aNode, aDrawNow );
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class CAknTreeItem.
+// Empty implementation for the pure virtal function declared in CAknTreeItem.
+// ---------------------------------------------------------------------------
+//
+void CAknTree::Draw( CWindowGc& /*aGc*/, const TRect& /*aItemRect*/,
+    const TRect& /*aRect*/, TBool /*aFocused*/ ) const
+    {
+    // The root node should never be drawn!
+    __ASSERT_DEBUG( EFalse, User::Invariant() );
+    }
+