mulwidgets/muldatamodel/src/mulpullmode.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:23:18 +0100
branchRCL_3
changeset 26 0e9bb658ef58
parent 0 e83bab7cf002
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2007-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:  Implementation of Pull Mode
*
*/


//Includes
#include "mulpullmode.h"

#include <mul/imulmodelprovider.h>


#include "mulassert.h"
#include "mulcachemanager.h"
#include "muldatawindow.h"
#include "mulpagedatawindow.h"
#include "mul/mulmodelutility.h"
#include "mullog.h"
#include "mulasyncdataprovider.h"

namespace Alf
    { 
    
// ---------------------------------------------------------------------------
// MulPullMode()
// ---------------------------------------------------------------------------
//
MulPullMode::MulPullMode(MulPageDataWindow& aDataWindow,
						 const IMulModelProvider& aModelProvider)
			:MulPushMode( aDataWindow )
	{	
	//mModelProvider = const_cast<IMulModelProvider*>( &aModelProvider );
	MUL_LOG_ENTRY_EXIT("MUL::MulPullModeImpl::MulPullModeImpl()");
	mModelProvider.reset( new (ELeave) MulAsyncDataProvider( const_cast<IMulModelProvider&>(aModelProvider), aDataWindow ));		
	}

// ---------------------------------------------------------------------------
// ~MulPullMode()
// ---------------------------------------------------------------------------
//
MulPullMode::~MulPullMode()
	{
	// No implementation is required.
	MUL_LOG_ENTRY_EXIT("MUL::MulPullModeImpl::~MulPullModeImpl()");
	}

// ------------------------ From IMulModel -----------------------------------

// ---------------------------------------------------------------------------
// Update
// ---------------------------------------------------------------------------
//
void MulPullMode::Update(int aIndex, int aCount, const MulDataPath& /*aPath*/)
	{
	// throw exception if index is out of bound
	__MUL_ASSERT( aIndex >= 0 && aCount > 0 && aIndex+aCount <= mCacheManager->ExpandedNodeCount(), KLInvalidArgument );
	
	int startIndex = aIndex;
	int range = 0;
	bool firstTime = true;
	for(int i = aIndex; i < aCount+aIndex ; ++i)
		{
		if( mDataWindow.IsItemInDataWindow(i) )
			{
			range++;
			firstTime = true;
			}
		else
			{
			if(firstTime)
				{
				firstTime = false;
				if(range>0)
					{
					ProvideData(startIndex,range);
					range = 0;						
					}
				}
			startIndex = i + 1;			
			}
		}
	ProvideData(startIndex,range);	
	}

// ---------------------------------------------------------------------------
// Refresh
// ---------------------------------------------------------------------------
//
void MulPullMode::Refresh( int aCount, const MulDataPath& aPath )
	{
	int modelCountBefore  = mCacheManager->ExpandedNodeCount();
	
	// remove all old nodes
    for(int currentIndex = 0; currentIndex < modelCountBefore; currentIndex++)	
		{
		mCacheManager->RemoveVisualItem(aPath,0);			
		}
    
    //mCacheManager->RemoveVisalItem(0, aCount, aPath );
	
    // insert new nodes	
	mCacheManager->CreateNodes( 0, aCount, aPath );	

	int modelCount = mCacheManager->ExpandedNodeCount();		
	// update alf model accordingly
	if(mDataWindow.IsWindowEnabled())
		{
		if(modelCountBefore == modelCount)
			{
			Update(0,aCount,aPath);
			}
		else
			{
			ModelCountChanged(modelCountBefore,modelCount);	
			}		
		}				
	}
		
// ---------------------------------------------------------------------------
// SetData
// ---------------------------------------------------------------------------
//
void MulPullMode::SetData(int aIndex, auto_ptr<MulVisualItem> aVisualItem,const MulDataPath& aPath)
	{
	MUL_LOG_ENTRY_EXIT("MUL::MulPullModeImpl::SetData()");
	
	__MUL_ASSERT( aIndex >= 0 && aIndex < Count(aPath),_L("Invalid Argument."));
		
	//Set data to model
	if( mDataWindow.IsItemInDataWindow( aIndex ) )
		{		
		MulPushMode::SetData( aIndex, aVisualItem, aPath );
		}
	}

// ---------------------------------------------------------------------------
// SetTemplate
// ---------------------------------------------------------------------------
//
void MulPullMode::SetTemplate( mulwidget::TLogicalTemplate aTemplateId )
	{
	mDefaultTemplate = aTemplateId;

	MulDataPath path ;
	if( mDataWindow.IsWindowEnabled() )
		{
		int topOffset = mDataWindow.TopOffset();
		int bottomOffset = mDataWindow.BottomOffset();
		for( int i = topOffset ; i <= bottomOffset ; i++ )
			{
			MulPushMode::SetTemplate( i, mDefaultTemplate, path);			
			}
		
		int rearTopOffset = mDataWindow.RearTopOffset();
		int rearBottomOffset = mDataWindow.RearBottomOffset();
        for( int i = rearTopOffset; i <= rearBottomOffset && i >= 0 ; i++ )
			{	
			MulPushMode::SetTemplate( i, mDefaultTemplate, path);
			}
		}
	}

// ---------------------------------------------------------------------------
// WindowSiftedDown
// ---------------------------------------------------------------------------
//
void MulPullMode::WindowSiftedDown()
	{
	MUL_LOG_ENTRY_EXIT("MUL::MulPullModeImpl::WindowSiftedDown"); 	
		
	// If the complete datawindow is invalid.   	
//	if(mDataWindow.TopOffset() - mDataWindow.OldTopOffset() > mDataWindow.ActualBufferSize() 
//		&& mDataWindow.OldTopOffset() != KNotInitialized)
	//if(mDataWindow.TopOffset() - mDataWindow.OldTopOffset() > mDataWindow.ActualBufferSize() )
	int oldTopOffset = mDataWindow.OldTopOffset();
	int oldBottomOffset = mDataWindow.OldBottomOffset();
	int topOffset = mDataWindow.TopOffset();
	int bottomOffset = mDataWindow.BottomOffset();
	int oldRearTopOffset = mDataWindow.OldRearTopOffset();
	int oldRearBottomOffset = mDataWindow.OldRearBottomOffset();
	
	 if(  ( oldTopOffset == KNotInitialized && oldBottomOffset == KNotInitialized ) ||
	      ( topOffset - oldTopOffset >= mDataWindow.ActualBufferSize()) ||
	      ( oldRearTopOffset != KNotInitialized && 
	      ( topOffset - oldTopOffset >= ( mDataWindow.WindowSize() + mDataWindow.BufferSize() ) ) 
	    ) ) 
		{
		//remove old data from  cache
        for( int i = oldTopOffset ; i <= oldBottomOffset && i >= 0 ; i++ )
            {
            mCacheManager->RemoveVisualItem( i );          
            }
        
        for( int i = oldRearTopOffset; i <= oldRearBottomOffset && i >= 0 ; i++ )
            {   
            mCacheManager->RemoveVisualItem( i );
            }
        
		int startIndex = topOffset;
		int range = bottomOffset - startIndex + 1;
		
		MUL_LOG_INFO2("MUL::MulPullModeImpl::WindowSiftedUp ProvideData startIndex:%d,range:%d",startIndex,range);
    	ProvideData(startIndex,range);
		} 
	else
		{
		//remove extra items from top and add new items at bottom
		for( int i = oldTopOffset ; i >= 0 && i < topOffset ; i++ )
			{       
			//remove item from top
			mCacheManager->RemoveVisualItem( i );
			}

		int startIndex = oldBottomOffset +1 ;
		int range = ( bottomOffset - oldBottomOffset );				
		MUL_LOG_INFO2("MUL::MulPullModeImpl::DataWindowUpdated ProvideData startIndex:%d,range:%d",startIndex,range); 		       
    	ProvideData(startIndex,range);				
		}
	}

// ---------------------------------------------------------------------------
// WindowSiftedUp
// ---------------------------------------------------------------------------
//
void MulPullMode::WindowSiftedUp()
	{
	MUL_LOG_ENTRY_EXIT("MUL::MulPullModeImpl::WindowSiftedUp "); 
	// If the complete datawindow is invalid.  	
//	if(mDataWindow.OldBottomOffset() - mDataWindow.BottomOffset() > mDataWindow.ActualBufferSize()
//		&& mDataWindow.OldBottomOffset() != KNotInitialized)

	  if( mDataWindow.OldBottomOffset() - mDataWindow.BottomOffset() >= mDataWindow.ActualBufferSize() ||
	    ( mDataWindow.OldRearBottomOffset() != KNotInitialized && 
	      ( mDataWindow.OldBottomOffset() - mDataWindow.BottomOffset() >= ( mDataWindow.WindowSize() + mDataWindow.BufferSize() ) ) 
	    ) )	
		{
		//remove old data from  cache
        for( int i = mDataWindow.OldTopOffset() ; i <= mDataWindow.OldBottomOffset() && i >= 0 ; i++ )
            {
            mCacheManager->RemoveVisualItem( i );          
            }
        
        for( int i = mDataWindow.OldRearTopOffset( ); i <= mDataWindow.OldRearBottomOffset() && i >= 0 ; i++ )
            {   
            mCacheManager->RemoveVisualItem( i );
            }
		        
		int startIndex = mDataWindow.TopOffset();
		int range = mDataWindow.BottomOffset() - startIndex + 1;
		
		MUL_LOG_INFO2("MUL::MulPullModeImpl::WindowSiftedUp ProvideData startIndex:%d,range:%d",startIndex,range);
		ProvideData(startIndex,range);
		}  
	else
		{
		//remove extra items from bottom and add at top
		for( int i = mDataWindow.BottomOffset() ; i < mDataWindow.OldBottomOffset() ; i++ )
			{		
			mCacheManager->RemoveVisualItem(i+1);
			}

		int startIndex = mDataWindow.TopOffset();
		int range = mDataWindow.OldTopOffset() - mDataWindow.TopOffset();

		MUL_LOG_INFO2("MUL::MulPullModeImpl::WindowSiftedUp ProvideData startIndex:%d,range:%d",startIndex,range); 		       
		ProvideData(startIndex,range);			
		}  			
	}

// ---------------------------------------------------------------------------
// ProvideData
// ---------------------------------------------------------------------------
//
void MulPullMode::ProvideData(int aStartIndex, int aRange)
	{
	 //call provide data for visible window first then for buffer
	if( aRange > 0 )
	    {
	    // check if the current higlighted item is there in the data asked for
	    if( mDataWindow.Highlight() >= aStartIndex &&
	            mDataWindow.Highlight() < aStartIndex+aRange )
	        {
	        mModelProvider->ProvideData( mDataWindow.Highlight(), 1 ,MulDataPath(),true );
	        }
	    //__MUL_ASSERT( ( aRange % 18 ) == 0, _L("Invalid Renage") );
	    //check that visible data is there in provide data call
	    if( aStartIndex < mDataWindow.TopWindowOffset() && 
	        aStartIndex+aRange > mDataWindow.BottomWindowOffset() )
	        {
	            {
	            //request visible item
                int startIndex = mDataWindow.TopWindowOffset();
                int range = ( mDataWindow.BottomWindowOffset() - mDataWindow.TopWindowOffset() ) + 1 ; 
                
                MUL_LOG_INFO2("MUL::MulPullModeImpl::ProvideData visible buffer startIndex:%d,range:%d",startIndex,range);
                mModelProvider->ProvideData(startIndex, range ,MulDataPath() );
                }
	        
    	        {
    	        //request item from top
    	        int startIndex = aStartIndex;
    	        int range = mDataWindow.TopWindowOffset() - startIndex; 
    	        
    	        MUL_LOG_INFO2("MUL::MulPullModeImpl::ProvideData top buffer startIndex:%d,range:%d",startIndex,range);
    	        mModelProvider->ProvideData(startIndex, range ,MulDataPath() );
    	        }
    	        
    	        {
    	        //request item from bottom
                int startIndex = mDataWindow.BottomWindowOffset() + 1 ;
                int range = ( aStartIndex + aRange - 1) - mDataWindow.BottomWindowOffset(); 

                MUL_LOG_INFO2("MUL::MulPullModeImpl::ProvideData bottom buffer startIndex:%d,range:%d",startIndex,range);
                mModelProvider->ProvideData(startIndex, range ,MulDataPath() );
                }
	        }
	    else
	        {
	        //there is not provide data pending for visible window
	        mModelProvider->ProvideData(aStartIndex, aRange ,MulDataPath() );
	        }
	    }
	}

// ---------------------------------------------------------------------------
// ModelCountChanged
// ---------------------------------------------------------------------------
//
void MulPullMode::ModelCountChanged(int aOldCount, int aNewCount)
    {
    MUL_LOG_ENTRY_EXIT("MUL::MulPullMode::AdjustOffsetAndData()");
    
    MUL_LOG_INFO1("MUL::MulPullMode::AdjustAlfModelData() modelCount:%d", aNewCount );
    
    MulPushMode::ModelCountChanged( aOldCount, aNewCount );
    
    // fetch data for the new buffers
    if( mDataWindow.RearTopOffset() != KNotInitialized &&
        mDataWindow.RearBottomOffset() != KNotInitialized )
        {   
        if(mDataWindow.RearTopOffset() == 0)
            {
            //updating all buffer
            ProvideData( mDataWindow.RearTopOffset() , mDataWindow.RearBottomOffset() - 
                mDataWindow.RearTopOffset() + 1);
            
            ProvideData( mDataWindow.TopOffset() , mDataWindow.BottomOffset() -
                mDataWindow.TopOffset() + 1);
            }
        else
            {
            ProvideData( mDataWindow.TopOffset() , mDataWindow.BottomOffset() -
                mDataWindow.TopOffset() + 1);
                
            ProvideData( mDataWindow.RearTopOffset() , mDataWindow.RearBottomOffset() - 
                mDataWindow.RearTopOffset() + 1);                               
            }       
        }
    else
        {
        ProvideData( mDataWindow.TopOffset() , mDataWindow.BottomOffset() -
             mDataWindow.TopOffset() + 1);  
        }
    }

// ---------------------------------------------------------------------------
// DataWindowUpdated
// ---------------------------------------------------------------------------
//    
void MulPullMode::DataWindowUpdated()
    {
    //here sequence of Function call are important dont change function call sequences
    //UpdateLoopBuffer must be called first 
    if( mDataWindow.RearTopOffset() != KNotInitialized &&
        mDataWindow.OldRearTopOffset() != KNotInitialized ) //there is looping on
        {
        UpdateLoopBuffer();
        //returning from here only dont need to do any thing else
        return ;
        }
    //window shifted down
    if( mDataWindow.OldBottomOffset() < mDataWindow.BottomOffset() )
        {
        WindowSiftedDown();     
        }       
    //window shifted up
    else if( mDataWindow.OldTopOffset() > mDataWindow.TopOffset())
        {
        WindowSiftedUp();       
        }

     //add buffer in looping case
    if(mDataWindow.RearTopOffset() != KNotInitialized && mDataWindow.RearBottomOffset() != KNotInitialized) //rear offset changed
        {
        // here ask data from top to bottom
        int startIndex = mDataWindow.RearTopOffset()  ;
        int range = mDataWindow.RearBottomOffset() - mDataWindow.RearTopOffset() + 1;
                
        MUL_LOG_INFO2("MUL::MulPullMode::DataWindowUpdated startIndex:%d,range:%d",startIndex,range);              
        ProvideData(startIndex,range); 
        }       
    }

// ---------------------------------------------------------------------------
// UpdateLoopBuffer
// ---------------------------------------------------------------------------
//
void MulPullMode::UpdateLoopBuffer()
    {
    MUL_LOG_ENTRY_EXIT("MUL::MulPushMode::UpdateLoopBuffer");   
    if( mDataWindow.RearTopOffset() < mDataWindow.OldRearTopOffset() )
        {
        int startIndex = mDataWindow.TopOffset();
        int range = mDataWindow.OldRearTopOffset() - startIndex;
    
        MUL_LOG_INFO2("MUL::MulPushMode::UpdateLoopBuffer startIndex:%d,range:%d",startIndex,range);               
        ProvideData(startIndex,range);
        }
    else
        {
        int startIndex = mDataWindow.OldRearBottomOffset()+1 ;
        int range = mDataWindow.BottomOffset() - startIndex + 1;
         
        MUL_LOG_INFO2("MUL::MulPushMode::UpdateLoopBuffer startIndex:%d,range:%d",startIndex,range);               
        ProvideData(startIndex,range);
        }
    }

// ---------------------------------------------------------------------------
// Item
// ---------------------------------------------------------------------------
//
const MulVisualItem& MulPullMode::Item( int aAbsoluteIndex )
    {
    MulVisualItem* visualItem = mCacheManager->Data( aAbsoluteIndex );
    if( !visualItem )
        {
        if( mDataWindow.IsItemInDataWindow(aAbsoluteIndex) )
            {
            std::auto_ptr<MulVisualItem> dummyItem = MulModelUtility::CreateVisualItem( Template() );
            visualItem = dummyItem.get();
            mCacheManager->AddVisualItem(dummyItem, MulDataPath() ,aAbsoluteIndex );  
            }
        else
            {
            throw std::invalid_argument(KInvalidArgument);  
            }
        }
    return *visualItem; 
    }

				
    } // namespace Alf

//End of file