photosgallery/viewframework/medialists/src/glxmedialistiterator.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:45:44 +0200
changeset 0 4e91876724a2
child 18 bcb43dc84c44
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:    Item ordered for traversing lists
*
*/




#include "mglxmedialist.h"
#include "glxlistutils.h"
#include "glxmedialistiterator.h"

#include <glxtracer.h>
#include <glxlog.h>
#include <hal.h>

const TInt KSequentialIteratorInitialValue = -1;
// Default granularity of items to request for
const TUint KGlxBlockyIteratorDefaultGranularity = 15;

const TInt KGlxLowerMemoryLimitForCacheSize = 15000000;
const TInt KGlxUpperMemoryLimitForCacheSize = 25000000;

const TInt KMaxLowMemOffsetValue = 3;
const TInt KMinLowMemOffsetValue = 1;

EXPORT_C TGlxSequentialIterator::TGlxSequentialIterator()
    {
    TRACER("TGlxSequentialIterator::TGlxSequentialIterator");
    
    iList = NULL;
    iCurrentItem = KSequentialIteratorInitialValue;
    iRange = KMaxTInt;      // To support full list length iteration,if range is not set                         
    }

// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
void TGlxSequentialIterator::SetToFirst(const MGlxMediaList* aList)
    {
    TRACER("TGlxSequentialIterator::SetToFirst");
    
    __ASSERT_DEBUG(aList != NULL, Panic(EGlxPanicNullPointer));
    iList = aList;
    iCurrentItem = KSequentialIteratorInitialValue;
    }

// -----------------------------------------------------------------------------
// Return the next item index or KErrNotFound
// -----------------------------------------------------------------------------
//
TInt TGlxSequentialIterator::operator++(TInt) 
    {
    TRACER("TGlxSequentialIterator::operator++");
    
    iCurrentItem++;
    if (iCurrentItem < iList->Count() && iCurrentItem < iRange )
        {
        return iCurrentItem;
        }
    else
        {
        return KErrNotFound;
        }
    }

// -----------------------------------------------------------------------------
// Return ETrue if index is within range, EFalse otherwise
// -----------------------------------------------------------------------------
//
TBool TGlxSequentialIterator::InRange(TInt aIndex) const
    {
    TRACER("TGlxSequentialIterator::InRange");
    
    return (aIndex < iRange && aIndex < iList->Count() && aIndex >= 0);
    }
// -----------------------------------------------------------------------------
// SetRange
// -----------------------------------------------------------------------------
//
EXPORT_C void TGlxSequentialIterator::SetRange( TInt aRange )
    {
    TRACER("TGlxSequentialIterator::SetRange");
    
    iRange = aRange; 
    }
    
// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxSpecificIdIterator::TGlxSpecificIdIterator(const TGlxIdSpaceId& aIdSpaceId, TGlxMediaId aMediaId)
    : iMediaId(aMediaId), iIdSpaceId(aIdSpaceId), iFinished(EFalse)
    {
    TRACER("TGlxSpecificIdIterator::TGlxSpecificIdIterator");
    
    }

// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
void TGlxSpecificIdIterator::SetToFirst(const MGlxMediaList* aList)
    {
    TRACER("TGlxSpecificIdIterator::SetToFirst");
    
    __ASSERT_DEBUG(aList != NULL, Panic(EGlxPanicNullPointer));
    iList = aList;
    iFinished = EFalse;
    }

// -----------------------------------------------------------------------------
// Return the next item index or KErrNotFound
// -----------------------------------------------------------------------------
//
TInt TGlxSpecificIdIterator::operator++(TInt) 
    {
    TRACER("TGlxSpecificIdIterator::operator++");
    
    if (iFinished)
        {
        return KErrNotFound;
        }
    else
        {
        iFinished = ETrue;        
        return iList->Index(iIdSpaceId, iMediaId);
        }
    }
// -----------------------------------------------------------------------------
// Return ETrue if index is within range, EFalse otherwise
// -----------------------------------------------------------------------------
//
TBool TGlxSpecificIdIterator::InRange(TInt aIndex) const
    {
    TRACER("TGlxSpecificIdIterator::InRange");
    
    return (aIndex == iList->Index(iIdSpaceId, iMediaId));
    }

// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFirstThenLastIterator::TGlxFirstThenLastIterator()
    {
    TRACER("TGlxFirstThenLastIterator::TGlxFirstThenLastIterator");
    
    iCurrentItem = 0;
    iList = NULL;
  }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFirstThenLastIterator::~TGlxFirstThenLastIterator()
    {
    TRACER("TGlxFirstThenLastIterator::~TGlxFirstThenLastIterator");
    
    }

// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
void TGlxFirstThenLastIterator::SetToFirst(const MGlxMediaList* aList) 
    {
    TRACER("TGlxFirstThenLastIterator::SetToFirst");    
    __ASSERT_DEBUG(aList, Panic(EGlxPanicNullPointer));

    iList = aList;
    iCurrentItem = 0;
  }

// -----------------------------------------------------------------------------
// Return the next item index or KErrNotFound
// -----------------------------------------------------------------------------
//
TInt TGlxFirstThenLastIterator::operator++(TInt) 
    {
    TRACER("TGlxFirstThenLastIterator::operator++");    
    __ASSERT_DEBUG(iList != NULL, Panic(EGlxPanicNullPointer));

    TInt count = iList->Count();
    if (count <= 0)
        {
        return KErrNotFound;
        }

    if (iCurrentItem == 0) 
        {
        // Return first item index
       iCurrentItem++;
       return 0; 
        }

    if (iCurrentItem == 1) 
        {
        // Return last item index
        iCurrentItem++;
        return count - 1;
        }
    
  // At last item already
    return KErrNotFound; 
    }
// -----------------------------------------------------------------------------
// Return ETrue if index is within range, EFalse otherwise
// -----------------------------------------------------------------------------
//
TBool TGlxFirstThenLastIterator::InRange(TInt aIndex) const
    {
    TRACER("TGlxFirstThenLastIterator::InRange");
    __ASSERT_DEBUG(aIndex >= 0 && aIndex < iList->Count(), Panic(EGlxPanicIllegalArgument));

    // Return ETrue if first or last item
    return (aIndex == 0) || (aIndex == iList->Count() - 1);
    }

// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromFocusOutwardIterator::TGlxFromFocusOutwardIterator()
    {
    TRACER("TGlxFromFocusOutwardIterator::TGlxFromFocusOutwardIterator");
    iCurrentItem = 0;
    iFrontOffset = 0;
    iRearOffset = 0;
    iList = NULL;
  }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromFocusOutwardIterator::~TGlxFromFocusOutwardIterator()
    {
    TRACER("TGlxFromFocusOutwardIterator::~TGlxFromFocusOutwardIterator");
    } 

// ----------------------------------------------------------------------------
// Set range offsets
// ----------------------------------------------------------------------------
//
EXPORT_C void TGlxFromFocusOutwardIterator::SetRangeOffsets(TInt aRearOffset,
    TInt aFrontOffset)
    { 
    TRACER("TGlxFromFocusOutwardIterator::SetRangeOffsets");
    __ASSERT_DEBUG(aRearOffset >= 0 && aFrontOffset >= 0, Panic(EGlxPanicIllegalArgument)); 
    iFrontOffset = aFrontOffset;
    iRearOffset = aRearOffset;
    iOriginalFrontOffset = iFrontOffset;
    iOriginalRearOffset = iRearOffset;    
    }

// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
void TGlxFromFocusOutwardIterator::SetToFirst(const MGlxMediaList* aList) 
    {
    TRACER("TGlxFromFocusOutwardIterator::SetToFirst");
    __ASSERT_DEBUG(aList != NULL, Panic(EGlxPanicNullPointer));

    iList = aList;
    iCurrentItem = 0;
    }

// -----------------------------------------------------------------------------
// Return the item index or KErrNotFound, and goes to next
// -----------------------------------------------------------------------------
//
TInt TGlxFromFocusOutwardIterator::operator++(TInt) 
    {
    TRACER("TGlxFromFocusOutwardIterator::operator++");
    __ASSERT_DEBUG(iList != NULL, Panic(EGlxPanicNullPointer));

    TInt count = iList->Count();
    if (count <= 0)
        {
        return KErrNotFound;
        }
  
    if (iOriginalFrontOffset > KMaxLowMemOffsetValue && 
        iOriginalRearOffset > KMaxLowMemOffsetValue)
        {
        TInt freeMemory = 0;
        HAL::Get( HALData::EMemoryRAMFree, freeMemory );    
        if ( freeMemory < KGlxUpperMemoryLimitForCacheSize &&
             freeMemory > KGlxLowerMemoryLimitForCacheSize )
            {
            iFrontOffset = KMaxLowMemOffsetValue;
            iRearOffset = KMaxLowMemOffsetValue;
            }
        else if ( freeMemory < KGlxLowerMemoryLimitForCacheSize )
            {
            iFrontOffset = KMinLowMemOffsetValue;
            iRearOffset = KMinLowMemOffsetValue;
            }
        else if (iFrontOffset != iOriginalFrontOffset 
                 && iRearOffset!= iOriginalRearOffset)
            {
            iFrontOffset = Max(iFrontOffset, iOriginalFrontOffset );
            iRearOffset = Max(iRearOffset, iOriginalRearOffset );
            }
        }
  
   // Check if out of bounds
    if (iFrontOffset + iRearOffset < iCurrentItem || count <= iCurrentItem)
        {
        return KErrNotFound;
        }
    
    // The ranges may be inequal, which means there won't be any jumping between
    // front and rear. 
    
    // |-------F----------------------|
    // |< jumping zone>|

    TInt index = iList->FocusIndex();

    TInt min = Min(iFrontOffset, iRearOffset);
    TInt jumpingZoneLength = min * 2;
    if (iCurrentItem <= jumpingZoneLength) 
        {
        // Still within the (rear-front-rear-front) jumping zone
        TInt distanceFromFocus = (iCurrentItem + 1) / 2;
        TBool rear = !(iCurrentItem & 1); // Rear if number is even
        if (rear) 
             {
             index -= distanceFromFocus; 
             }
        else 
             {
             index += distanceFromFocus; 
             }
        }
     else 
         {
         __ASSERT_DEBUG(iFrontOffset != iRearOffset, Panic(EGlxPanicLogicError));
    
         // index is currently focus index. Figure out how much need to move.
         TInt indexesFromFocus = iCurrentItem - min; 
         if (iRearOffset < iFrontOffset)
             {
             // Front range is longer than rear, so the item is on the front side
             index += indexesFromFocus;
             }
         else 
             {
             // Rear range is longer than front, so the item is on the rear side
             index -= indexesFromFocus;
             }
         }

      iCurrentItem++;
    
      // The index may be below 0 or above count. Normalise back to list indexes.
      return GlxListUtils::NormalizedIndex(index, count); 
      } 
  
// -----------------------------------------------------------------------------
// Return ETrue if index is within range, EFalse otherwise
// -----------------------------------------------------------------------------
//
TBool TGlxFromFocusOutwardIterator::InRange(TInt aIndex) const
    {
    TRACER("TGlxFromFocusOutwardIterator::InRange");
    TInt count = iList->Count();
  
    // Handle the case where range is longer than count separately, because looping will
    // confuse otherwise
    if (count <= iRearOffset + iFrontOffset) 
        {
        // Range is longer than count, must be in range
        return ETrue;
        }
  
    TInt focusIndex = iList->FocusIndex();
    TInt firstInRange = GlxListUtils::NormalizedIndex(focusIndex - iRearOffset, count);
    TInt lastInRange = GlxListUtils::NormalizedIndex(focusIndex + iFrontOffset, count);
  
    if (firstInRange <= lastInRange)
        {
        // Normal case:  |    F-------L   |
        return aIndex >= firstInRange && aIndex <= lastInRange;
        }
    else 
        {
        // Looping case: |----L      F----|
        return aIndex <= lastInRange || aIndex >= firstInRange;
        }
    }

// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromIndexOutwardBlockyIterator::TGlxFromIndexOutwardBlockyIterator(
    const MGlxIndex& aIndexFunctor ) 
        : iIndexFunctor( aIndexFunctor )
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::TGlxFromIndexOutwardBlockyIterator");
            
    iCurrentItem = 0;
    iFrontOffset = 2 * KGlxBlockyIteratorDefaultGranularity;
    iRearOffset = 2 * KGlxBlockyIteratorDefaultGranularity;
    iList = NULL;
  }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromIndexOutwardBlockyIterator::~TGlxFromIndexOutwardBlockyIterator()
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::~TGlxFromIndexOutwardBlockyIterator");
    
    } 

// ----------------------------------------------------------------------------
// Set range offsets
// ----------------------------------------------------------------------------
//
EXPORT_C void TGlxFromIndexOutwardBlockyIterator::SetRangeOffsets(TInt aRearOffset,
    TInt aFrontOffset)
    { 
    TRACER("TGlxFromIndexOutwardBlockyIterator::SetRangeOffsets");
    
    __ASSERT_DEBUG(aRearOffset >= 0 && aFrontOffset >= 0, Panic(EGlxPanicIllegalArgument)); 
    iFrontOffset = Max(aFrontOffset, KGlxBlockyIteratorDefaultGranularity );
    iRearOffset = Max(aRearOffset, KGlxBlockyIteratorDefaultGranularity );
    }

// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
void TGlxFromIndexOutwardBlockyIterator::SetToFirst(const MGlxMediaList* aList) 
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::SetToFirst");
    __ASSERT_DEBUG(aList != NULL, Panic(EGlxPanicNullPointer));

    iList = aList;
    iCurrentItem = 0;
    }

// -----------------------------------------------------------------------------
// Return the item index or KErrNotFound, and goes to next
// -----------------------------------------------------------------------------
//
TInt TGlxFromIndexOutwardBlockyIterator::operator++(TInt) 
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::operator++");
    __ASSERT_DEBUG(iList != NULL, Panic(EGlxPanicNullPointer));

    TInt count = iList->Count();
    if (count <= 0)
        {
        return KErrNotFound;
        }
  
   // Check if out of bounds
    if (iFrontOffset + iRearOffset < iCurrentItem || count <= iCurrentItem)
        {
        return KErrNotFound;
        }
    
    // The ranges may be inequal, which means there won't be any jumping between
    // front and rear. 
    
    // |-------F----------------------|
    // |< jumping zone>|

    TInt index = iIndexFunctor.Index();
    __ASSERT_ALWAYS( index >= 0 && index < iList->Count(), Panic( EGlxPanicIllegalState ) );
    index -= index % KGlxBlockyIteratorDefaultGranularity;

    TInt min = Min(iFrontOffset, iRearOffset);
    TInt jumpingZoneLength = min * 2;
    if (iCurrentItem <= jumpingZoneLength) 
        {
        // Still within the (rear-front-rear-front) jumping zone
        TInt distanceFromFocus = (iCurrentItem + 1) / 2;
        TBool rear = !(iCurrentItem & 1); // Rear if number is even
        if (rear) 
             {
             index -= distanceFromFocus; 
             }
        else 
             {
             index += distanceFromFocus; 
             }
        }
     else 
         {
         __ASSERT_DEBUG(iFrontOffset != iRearOffset, Panic(EGlxPanicLogicError));
    
         // index is currently focus index. Figure out how much need to move.
         TInt indexesFromFocus = iCurrentItem - min; 
         if (iRearOffset < iFrontOffset)
             {
             // Front range is longer than rear, so the item is on the front side
             index += indexesFromFocus;
             }
         else 
             {
             // Rear range is longer than front, so the item is on the rear side
             index -= indexesFromFocus;
             }
         }

      iCurrentItem++;
    
      // The index may be below 0 or above count. Normalise back to list indexes.
      return GlxListUtils::NormalizedIndex(index, count); 
      } 
  
// -----------------------------------------------------------------------------
// Return ETrue if index is within range, EFalse otherwise
// -----------------------------------------------------------------------------
//
TBool TGlxFromIndexOutwardBlockyIterator::InRange(TInt aIndex) const
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::InRange");
    TInt count = iList->Count();
  
    // Handle the case where range is longer than count separately, because looping will
    // confuse otherwise
    if (count <= iRearOffset + iFrontOffset) 
        {
        // Range is longer than count, must be in range
        return ETrue;
        }
  
    TInt index = iIndexFunctor.Index();
    __ASSERT_ALWAYS( index >= 0 && index < iList->Count(), Panic( EGlxPanicIllegalState ) );
    index -= index % KGlxBlockyIteratorDefaultGranularity;
    TInt firstInRange = GlxListUtils::NormalizedIndex(index - iRearOffset, count);
    TInt lastInRange = GlxListUtils::NormalizedIndex(index + iFrontOffset, count);
  
    if (firstInRange <= lastInRange)
        {
        // Normal case:  |    F-------L   |
        return aIndex >= firstInRange && aIndex <= lastInRange;
        }
    else 
        {
        // Looping case: |----L      F----|
        return aIndex <= lastInRange || aIndex >= firstInRange;
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
    
// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromFocusOutwardBlockyIterator::TGlxFromFocusOutwardBlockyIterator()
        : TGlxFromIndexOutwardBlockyIterator(*static_cast<TGlxFromIndexOutwardBlockyIterator::MGlxIndex*>(this)  )
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::TGlxFromFocusOutwardBlockyIterator");
    }

// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromFocusOutwardBlockyIterator::~TGlxFromFocusOutwardBlockyIterator()
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::~TGlxFromFocusOutwardBlockyIterator");
    }

// -----------------------------------------------------------------------------
// Index
// -----------------------------------------------------------------------------
//
TInt TGlxFromFocusOutwardBlockyIterator::Index() const
    {
    TRACER("TGlxFromIndexOutwardBlockyIterator::Index");
    return iList->FocusIndex();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromManualIndexOutwardBlockyIterator::TGlxFromManualIndexOutwardBlockyIterator()
        : TGlxFromIndexOutwardBlockyIterator( *static_cast<TGlxFromIndexOutwardBlockyIterator::MGlxIndex*>(this) ), iIndex( 0 )
    {
    TRACER("TGlxFromManualIndexOutwardBlockyIterator::TGlxFromManualIndexOutwardBlockyIterator");
    }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromManualIndexOutwardBlockyIterator::~TGlxFromManualIndexOutwardBlockyIterator()
    {
    TRACER("TGlxFromManualIndexOutwardBlockyIterator::~TGlxFromManualIndexOutwardBlockyIterator");
    }
   
// -----------------------------------------------------------------------------
// SetIndex
// -----------------------------------------------------------------------------
//
EXPORT_C void TGlxFromManualIndexOutwardBlockyIterator::SetIndex( TInt aIndex )
    {
    TRACER("TGlxFromManualIndexOutwardBlockyIterator::SetIndex");
    
    __ASSERT_DEBUG( aIndex >= 0 && aIndex < iList->Count(), Panic( EGlxPanicIllegalArgument ) );
    iIndex = aIndex;
    }
    
// -----------------------------------------------------------------------------
// Index
// -----------------------------------------------------------------------------
//
TInt TGlxFromManualIndexOutwardBlockyIterator::Index() const
    {
    TRACER("TGlxFromManualIndexOutwardBlockyIterator::Index");
    
    return iIndex;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
    
// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxSelectionIterator::TGlxSelectionIterator()
    {
    TRACER("TGlxSelectionIterator::TGlxSelectionIterator");
    
    iCurrentItem = 0;
    iList = NULL;
    iRange = KMaxTInt;
    iDisabledIfMoreThanRangeSelected = EFalse;
    }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxSelectionIterator::~TGlxSelectionIterator()
    {
    TRACER("TGlxSelectionIterator::~TGlxSelectionIterator");
    }

// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
EXPORT_C void TGlxSelectionIterator::SetToFirst(const MGlxMediaList* aList) 
    {
    TRACER("TGlxSelectionIterator::SetToFirst");
    __ASSERT_DEBUG(aList != NULL, Panic(EGlxPanicNullPointer));
  
    iList = aList;
    iCurrentItem = 0;
    }

// -----------------------------------------------------------------------------
// Return the next item index or KErrNotFound
// -----------------------------------------------------------------------------
//
EXPORT_C TInt TGlxSelectionIterator::operator++(TInt) 
    {
    TRACER("TGlxSelectionIterator::operator++");
    __ASSERT_DEBUG(iList != NULL, Panic(EGlxPanicNullPointer));

    TInt result = KErrNotFound;

    TInt selectionCount = iList->SelectionCount();
  
    if (!iDisabledIfMoreThanRangeSelected || (selectionCount <= iRange))
    { 
    if (selectionCount == 0)
        {
        // If no items are selected, treat the focused index as the selection
        if ( iCurrentItem == 0 )
            {
            result = iList->FocusIndex();
            iCurrentItem++;
            }
        }
    else
        {
        if ( iCurrentItem < iRange && iCurrentItem < selectionCount )
            {
            result = iList->SelectedItemIndex(iCurrentItem);
            iCurrentItem++;
            }
        }
    }
  return result; 
  }

// -----------------------------------------------------------------------------
// TGlxSelectionIterator::InRange
// -----------------------------------------------------------------------------
//

EXPORT_C TBool TGlxSelectionIterator::InRange(TInt aIndex) const
    {
    TRACER("TGlxSelectionIterator::InRange");
    __ASSERT_DEBUG(aIndex >= 0 && aIndex < iList->Count(), Panic(EGlxPanicIllegalArgument));

    TInt selectionCount = iList->SelectionCount();
    TBool inRange = EFalse;
  
    if (selectionCount)
        {
        TBool legalIndex = EFalse;
        if (selectionCount > iRange)
            {
            if (iDisabledIfMoreThanRangeSelected)
                {
                legalIndex = EFalse;
                }
            else
                {
                legalIndex = (iList->SelectedItemIndex(iRange) > aIndex);
                }
            }
        else
            {
            legalIndex = ETrue;
            }
    
        if(legalIndex)
            {
            inRange = iList->IsSelected(aIndex);
            }
       }
    else
       {
       if (!(iDisabledIfMoreThanRangeSelected && (iRange == 0)))
           {
           inRange = (aIndex == iList->FocusIndex());
           }
       }
    return inRange;
}

// -----------------------------------------------------------------------------
// TGlxSelectionIterator::SetRange
// -----------------------------------------------------------------------------
//
EXPORT_C void TGlxSelectionIterator::SetRange(TInt aMaxItems)
    {
    TRACER("TGlxSelectionIterator::SetRange");
    iRange = aMaxItems;
    }

// -----------------------------------------------------------------------------
// TGlxSelectionIterator::SetDisabledIfMoreThanRangeSelected
// -----------------------------------------------------------------------------
//
EXPORT_C void TGlxSelectionIterator::SetDisabledIfMoreThanRangeSelected(TBool aDisabledIfMoreThanRangeSelected)
    {
    TRACER("TGlxSelectionIterator::SetDisabledIfMoreThanRangeSelected");
    iDisabledIfMoreThanRangeSelected = aDisabledIfMoreThanRangeSelected;
    }
// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxExclusionIterator::TGlxExclusionIterator( MGlxMediaListIterator& aIncludedItemsIterator,
                                                       MGlxMediaListIterator& aExcludedItemsIterator )
                                                       :iIncludedItemsIterator( aIncludedItemsIterator ),
                                                       iExcludedItemsIterator( aExcludedItemsIterator )
    {           
    TRACER("TGlxExclusionIterator::TGlxExclusionIterator" );
    }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxExclusionIterator::~TGlxExclusionIterator()
    {
    TRACER("TGlxExclusionIterator::~TGlxExclusionIterator");
    } 
    
// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
EXPORT_C void TGlxExclusionIterator::SetToFirst(const MGlxMediaList* aList)
    {
    TRACER("TGlxExclusionIterator::SetToFirst");
    __ASSERT_DEBUG(aList != NULL, Panic(EGlxPanicNullPointer));

    //implementation delegates to both the iterators         
    iIncludedItemsIterator.SetToFirst( aList );
    iExcludedItemsIterator.SetToFirst( aList ); 
    }
    
// -----------------------------------------------------------------------------
// Return the next item index or KErrNotFound
// -----------------------------------------------------------------------------
//
TInt TGlxExclusionIterator::operator++(TInt ) 
    { 
    TRACER("TGlxExclusionIterator::operator++");

    // This method returns the next valid item of the iterator such that 
    // (1) The index is within the range of iIncludedItemsIterator
    // and
    // (2) The index is not in the range of iExcludedItemsIterator.
    // If iIncludedItemsIterator reaches its end in this process then we loop to the 
    // first item and repeat the above steps.

    TInt index = KErrNotFound; // assign initial value for maintenance safety

    do  {
        index = iIncludedItemsIterator++;
        } while ( KErrNotFound != index && iExcludedItemsIterator.InRange( index ) );

    return index;
    }
    
    
// -----------------------------------------------------------------------------
// Return ETrue if index is within range, EFalse otherwise
// -----------------------------------------------------------------------------
//
TBool TGlxExclusionIterator::InRange(TInt aIndex) const
    { 
    TRACER("TGlxExclusionIterator::InRange");
    
    // Verify that aIndex is 
    // (1) In the range of iIncludedItemsIterator 
    // and 
    // (2) Not in the range of iExcludedItemsIterator  
    

    return iIncludedItemsIterator.InRange(aIndex) &&
                    !iExcludedItemsIterator.InRange(aIndex); 
    }

// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromManualIndexBlockyIterator::TGlxFromManualIndexBlockyIterator( )
    {
    TRACER("TGlxFromManualIndexBlockyIterator::TGlxFromManualIndexBlockyIterator");
    iDefaultVisItems = GlxListUtils::VisibleItemsGranularityL();       
    iCurrentItem = 0;
    iFrontOffset = 4 * iDefaultVisItems;
    iRearOffset = 2 * iDefaultVisItems;
    iOriginalFrontOffset = iFrontOffset;
    iOriginalRearOffset = iRearOffset;
    iList = NULL;
  }
    
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C TGlxFromManualIndexBlockyIterator::~TGlxFromManualIndexBlockyIterator()
    {
    TRACER("TGlxFromManualIndexBlockyIterator::~TGlxFromManualIndexBlockyIterator");
    
    } 

// ----------------------------------------------------------------------------
// Set range offsets
// ----------------------------------------------------------------------------
//
EXPORT_C void TGlxFromManualIndexBlockyIterator::SetRangeOffsets(TInt aRearOffset,
    TInt aFrontOffset)
    { 
    TRACER("TGlxFromManualIndexBlockyIterator::SetRangeOffsets");
    
    __ASSERT_DEBUG(aRearOffset >= 0 && aFrontOffset >= 0, Panic(EGlxPanicIllegalArgument)); 
    iFrontOffset = Max(aFrontOffset, iDefaultVisItems );
    iRearOffset = Max(aRearOffset, iDefaultVisItems );
    iOriginalFrontOffset = iFrontOffset;
    iOriginalRearOffset = iRearOffset;    
    }

// -----------------------------------------------------------------------------
// Set to first item
// -----------------------------------------------------------------------------
//
void TGlxFromManualIndexBlockyIterator::SetToFirst(const MGlxMediaList* aList) 
    {
    TRACER("TGlxFromManualIndexBlockyIterator::SetToFirst");
    __ASSERT_DEBUG(aList != NULL, Panic(EGlxPanicNullPointer));

    iList = aList;
    iCurrentItem = 0;
    }

// -----------------------------------------------------------------------------
// Return the item index or KErrNotFound, and goes to next
// -----------------------------------------------------------------------------
//
TInt TGlxFromManualIndexBlockyIterator::operator++(TInt) 
    {
    TRACER("TGlxFromManualIndexBlockyIterator::operator++");
    __ASSERT_DEBUG(iList != NULL, Panic(EGlxPanicNullPointer));

    TInt count = iList->Count();
    if (count <= 0)
        {
        return KErrNotFound;
        }

    if (iOriginalFrontOffset > KMaxLowMemOffsetValue* iDefaultVisItems &&
        iOriginalRearOffset > KMaxLowMemOffsetValue * iDefaultVisItems)
        {
        TInt freeMemory = 0;
        HAL::Get( HALData::EMemoryRAMFree, freeMemory );    
        if ( freeMemory < KGlxUpperMemoryLimitForCacheSize &&
             freeMemory > KGlxLowerMemoryLimitForCacheSize )
            {
            iFrontOffset = 2*iDefaultVisItems;
            iRearOffset = 3*iDefaultVisItems;
            }
        else if ( freeMemory < KGlxLowerMemoryLimitForCacheSize )
            {
            iFrontOffset = iDefaultVisItems;
            iRearOffset = iDefaultVisItems;
            }
        else if (iFrontOffset != iOriginalFrontOffset 
                 && iRearOffset!= iOriginalRearOffset)
            {
            iFrontOffset = Max(iFrontOffset, iOriginalFrontOffset );
            iRearOffset = Max(iRearOffset, iOriginalRearOffset );
            }
        }
  
   // Check if out of bounds
    if (iFrontOffset + iRearOffset < iCurrentItem || count <= iCurrentItem)
        {
        return KErrNotFound;
        }
    
    // The ranges may be inequal, which means there won't be any jumping between
    // front and rear. 
    
    // |-------F----------------------|
    // |< jumping zone>|

    TInt visIndex = iList->VisibleWindowIndex();
    TInt index = visIndex;
    TInt listCount = iList->Count();
    __ASSERT_ALWAYS( index >= 0 && index <= listCount, Panic( EGlxPanicIllegalState ) );
    //Inorder to ensure that the start of refresh of thumbnails is contained in
    //in the current visible window. We set the startIndex to center element of 
    //the current visible window.
    TInt startIndex = index + iDefaultVisItems/2;
    if (listCount < iDefaultVisItems)
        {
        startIndex = listCount/2;
        }
    
    index = ( (startIndex) <= (listCount)) ? startIndex : listCount;	    	

    TInt min = Min(iFrontOffset, iRearOffset);
    TInt jumpingZoneLength = min * 2;
    if (iCurrentItem <= jumpingZoneLength) 
        {
        // Still within the (rear-front-rear-front) jumping zone
        TInt distanceFromFocus = (iCurrentItem + 1) / 2;
        TBool rear = !(iCurrentItem & 1); // Rear if number is even
        // Check if out of bounds
        if (rear) 
             {
             if (index - distanceFromFocus <= visIndex - iRearOffset)
                 {
                 return KErrNotFound;
                 }
             index -= distanceFromFocus; 
             }
        else 
             {
             if (index + distanceFromFocus >= visIndex + iFrontOffset)
                 {
                 return KErrNotFound;
                 }
             index += distanceFromFocus; 
             }
        }
     else 
         {
         __ASSERT_DEBUG(iFrontOffset != iRearOffset, Panic(EGlxPanicLogicError));
    
         // index is currently visible index. Figure out how much need to move.
         TInt indexesFromFocus = iCurrentItem - min; 
         if (iRearOffset < iFrontOffset)
             {
             // Front range is longer than rear, so the item is on the front side
             index += indexesFromFocus;
             }
         else 
             {
             // Rear range is longer than front, so the item is on the rear side
             index -= indexesFromFocus;
             }
         }

      iCurrentItem++;
    
      // The index may be below 0 or above count. Normalise back to list indexes.
      return GlxListUtils::NormalizedIndex(index, count); 
      } 
  
// -----------------------------------------------------------------------------
// Return ETrue if index is within range, EFalse otherwise
// -----------------------------------------------------------------------------
//
TBool TGlxFromManualIndexBlockyIterator::InRange(TInt aIndex) const
    {
    TRACER("TGlxFromManualIndexBlockyIterator::InRange");
    TInt count = iList->Count();
  
    // Handle the case where range is longer than count separately, because looping will
    // confuse otherwise
    if (count <= iRearOffset + iFrontOffset) 
        {
        // Range is longer than count, must be in range
        return ETrue;
        }
  
    TInt index = iList->VisibleWindowIndex();
    __ASSERT_ALWAYS( index >= 0 && index < iList->Count(), Panic( EGlxPanicIllegalState ) );
    
    TInt firstInRange = GlxListUtils::NormalizedIndex(index - iRearOffset, count);
    TInt lastInRange = GlxListUtils::NormalizedIndex(index + iFrontOffset, count);
  
    if (firstInRange <= lastInRange)
        {
        // Normal case:  |    F-------L   |
        return aIndex >= firstInRange && aIndex <= lastInRange;
        }
    else 
        {
        // Looping case: |----L      F----|
        return aIndex <= lastInRange || aIndex >= firstInRange;
        }
    }