cbs/cbsui/UiSrc/CCbsUiMsgViewContainer.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:15:03 +0100
branchRCL_3
changeset 20 987c9837762f
parent 0 ff3b6d0fd310
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2002-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 CCbsUiMsgViewContainer class.
*
*
*/


// INCLUDES
#include <bldvariant.hrh>       // for feature flags
#include <eikenv.h>
#include <AknLayoutDef.h>       // enum TAknLayoutId
#include <aknenv.h>             // for iAvkonEnv
#include <AknUtils.h>           // AknLayoutUtils
#include <sysutil.h>            // FFS critical level check
#include <eikrted.h>
#include <barsread.h>
#include <txtrich.h>
#include <calslbs.h>
#include <baclipb.h>
#include <aknkeys.h>
#include <applayout.cdl.h>      // Multiline_Message_writing_texts_Line_3
#include <AknLayout2ScalableDef.h>        // TAknLayoutScalableParameterLimits
#include <aknlayoutscalable_apps.cdl.h>   // list_single_mce_message_pane_ParamLimits().iRows
#include <AknDef.h>                       // KEikDynamicLayoutVariantSwitch
#include <AknsConstants.h>      // KAknsMessageSkinChange
#include <aknappui.h>
#include <AknsBasicBackgroundControlContext.h> // CAknsBasicBackgroundControlContext
#include <AknsUtils.h>                    // MAknsSkinInstance
#include <AknsDrawUtils.h>                // AknsDrawUtils
#include <cbsuiApp.rsg>
#include "CbsUiId.h"
#include <csxhelp/cbs.hlp.hrh>
#include "CCbsUIMsgViewContainer.h"
#include "CCbsUIMsgView.h"
#include "Cbsuiapp.hrh"
#include "CbsUiPanic.h"
#include <gdi.h>



// LOCAL CONSTANTS AND MACROS
const TInt KEditorNumOfLines = 7;
const TInt KFirstScreen = 0;
const TInt KOneScreen = 1;
const TInt KMsgNumberOfControls = 1;
const TInt KMsgControlIndexEditor = 0;


// ================= MEMBER FUNCTIONS =======================

// C++ default constructor can NOT contain any code, that
// might leave.
CCbsUiMsgViewContainer::CCbsUiMsgViewContainer( CCbsUiMsgView& aMsgView )
: iMsgView(aMsgView)      
    {
    }

// Symbian OS default constructor can leave.
void CCbsUiMsgViewContainer::ConstructL( const TRect& aRect )
    {
    CreateWindowL();
    SetMopParent(&iMsgView);
    
    iEditor = CreateEditorL();
    SetReadOnly(ETrue);
    
    SetRect(aRect);

    // for Skin Support, Create background control context:
    iBackGroundControlContext = CAknsBasicBackgroundControlContext::NewL(
                    KAknsIIDQsnBgAreaMain,  // Default mainpane skinning
                    Rect(),                 // Layout to the entire client rect
                    EFalse );
    if ( iBackGroundControlContext )
        {
        iEditor->SetSkinBackgroundControlContextL( iBackGroundControlContext );
        }
    }


// Two-phased constructor.
CCbsUiMsgViewContainer* CCbsUiMsgViewContainer::NewL( CCbsUiMsgView& aMsgView, 
                                                     const TRect& aRect )
    {    
    CCbsUiMsgViewContainer* self = new (ELeave) 
        CCbsUiMsgViewContainer(aMsgView);    
    
    CleanupStack::PushL(self);
    self->ConstructL(aRect);
    CleanupStack::Pop();
    return self;
    }

// Destructor
CCbsUiMsgViewContainer::~CCbsUiMsgViewContainer()
    {
    delete iBackGroundControlContext;
    delete iEditor;
    delete iSBFrame;
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::CountComponentControls
// 
// 
// ---------------------------------------------------------
//
TInt CCbsUiMsgViewContainer::CountComponentControls() const
    {
    TInt countScrollBarComponents( 0 );
    if ( iSBFrame )
        {
        countScrollBarComponents = iSBFrame->CountComponentControls();
        }
    return KMsgNumberOfControls + countScrollBarComponents;
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::ComponentControl
// 
// 
// ---------------------------------------------------------
//
CCoeControl* CCbsUiMsgViewContainer::ComponentControl( TInt aIndex ) const
    {
    CCoeControl* control = NULL;
    
    TInt countScrollBarComponents( 0 );
    if ( iSBFrame )
        {
        countScrollBarComponents = iSBFrame->CountComponentControls();
        }
    
    switch ( aIndex )
        {
        case KMsgControlIndexEditor:
            control = iEditor;
            break;
        default:
            if ( iSBFrame
                &&  aIndex >= KMsgNumberOfControls 
                &&  aIndex < countScrollBarComponents + KMsgNumberOfControls )
                {
                control = iSBFrame->ComponentControl( aIndex - KMsgNumberOfControls );
                }
            else
                {
                control = NULL;
                }
            break;
        }
    return control;
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::OfferKeyEventL
// 
// 
// ---------------------------------------------------------
//
TKeyResponse CCbsUiMsgViewContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent, 
                                                    TEventCode /*aType*/ )
    {    
    __ASSERT_DEBUG( iEditor, CbsUiPanic(EEditorNullError) );
    
    switch ( aKeyEvent.iCode )
        {
        case EKeyLeftArrow:
            {
            if( AknLayoutUtils::LayoutMirrored() )
                {
                iMsgView.MoveToNextMessageL();
                }
            else
                {
                iMsgView.MoveToPreviousMessageL();
                }
            break;
            }
        case EKeyRightArrow:
            {
            if( AknLayoutUtils::LayoutMirrored() )
                {
                iMsgView.MoveToPreviousMessageL();
                }
            else
                {
                iMsgView.MoveToNextMessageL();
                }
            break;
            }
        case EKeyUpArrow :
            {
            ScrollMessageUpL();
            break;
            }
        case EKeyDownArrow:
            {
            ScrollMessageDownL();
            break;
            }
        case EKeyOK:
            {
            iMsgView.ProcessCommandL( ECbsUiappCmdOkKey );
            break;
            }
        case EKeyBackspace:
            {
            iMsgView.ProcessCommandL( ECbsUiappCmdMsgMenuDelete );
            break;
            }
        default:
            {
            break;
            }
        }
    
    return EKeyWasConsumed;
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::UpdateMessageL
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::UpdateMessageL( const TDesC& aMessage )
    {
    SetData16L(aMessage);
    
    InitializeMessageInfoL();
    
    CreateScrollBarFrameL();
    UpdateScrollIndicatorL();
    
    iEditor->DrawNow();
    }

// ---------------------------------------------------------
// CCbsUiMsgViewContainer::SizeChanged
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::SizeChanged()
    {
    if ( iEditor ) 
        {
        TRAPD( ignore, iEditor->SelectAllL() ); // This is needed before calling layoutedwin!
        if( ignore )
            {
            ignore = KErrNone; //Prevent ARMV5 compilation varning
            }
        if ( AknLayoutUtils::ScalableLayoutInterfaceAvailable() )
            {
            TAknLayoutScalableParameterLimits scalbleParamLimits;
            scalbleParamLimits = AknLayoutScalable_Apps::list_single_mce_message_pane_ParamLimits();
            AknLayoutUtils::LayoutEdwin( iEditor, Rect(), AppLayout::Multiline_Message_writing_texts_Line_3(scalbleParamLimits.LastRow() ) );
            }
        else
            {
            AknLayoutUtils::LayoutEdwin( iEditor, Rect(), AppLayout::Multiline_Message_writing_texts_Line_3( KEditorNumOfLines ) );
            }
        if ( iBackGroundControlContext )
            {
            TRAPD( ignore, iEditor->SetSkinBackgroundControlContextL( iBackGroundControlContext ) );
            if( ignore )
                {
                ignore = KErrNone; //Prevent ARMV5 compilation varning
                }
            }
        iEditor->DrawNow();
        }
    }


// ---------------------------------------------------------
// CCbsUiMsgViewConctainer::CreateEditorL
// 
// 
// ---------------------------------------------------------
//
CEikRichTextEditor* CCbsUiMsgViewContainer::CreateEditorL() const
    {
    TResourceReader reader;
    iCoeEnv->CreateResourceReaderLC(reader, R_MSG_READER);
    
    CEikRichTextEditor* editor = new (ELeave) CEikRichTextEditor;
    CleanupStack::PushL( editor );
    editor->SetContainerWindowL(*this);
    editor->ConstructFromResourceL( reader );
    CleanupStack::Pop(); // editor
    CleanupStack::PopAndDestroy(); // reader    
    
    __ASSERT_DEBUG( editor, CbsUiPanic(EEditorNullError) );
    
    return editor;
    }

// ---------------------------------------------------------
// CCbsUiMsgViewConctainer::Draw
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::Draw( const TRect& aRect ) const
    {
    CWindowGc& aGc = SystemGc();
    
    // for clearing gap between editor and the view rect
    if ( IsReadyToDraw() )
        {
        aGc.SetBrushColor( AKN_LAF_COLOR (0) );
        DrawUtils::ClearBetweenRects( aGc, aRect, iEditor->Rect() );
        if ( iBackGroundControlContext )
            {//Draw the skin background
            MAknsSkinInstance* skin = AknsUtils::SkinInstance();
            AknsDrawUtils::Background( skin, iBackGroundControlContext, this, aGc, aRect );
            }
        }
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::InitializeMessageInfoL
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::InitializeMessageInfoL()
    {
    
    iEditor->TextLayout()->SetAmountToFormat( CTextLayout::EFFormatAllText );
    
    iEditor->CreateTextViewL();
    iEditor->NotifyNewFormatL();
    TInt numberOfLines = iEditor->TextLayout()->NumFormattedLines();
    
    if ( AknLayoutUtils::ScalableLayoutInterfaceAvailable() )
        {
        TInt linesInScreen;
        TAknLayoutScalableParameterLimits scalbleParamLimits;
        scalbleParamLimits = AknLayoutScalable_Apps::list_single_mce_message_pane_ParamLimits();
        linesInScreen = scalbleParamLimits.LastRow();
        iNumberOfScreens = ( numberOfLines - 1 ) / linesInScreen + 1;
        }
    else
        {
        iNumberOfScreens = ( numberOfLines - 1 ) / KEditorNumOfLines + 1;
        }

    iCurrentScreen = KFirstScreen;
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::CreateScrollBarFrameL
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::CreateScrollBarFrameL()
    {        
    if ( !iSBFrame )
        {
        iSBFrame = new (ELeave) CEikScrollBarFrame( iEditor, this, ETrue );
        }
    
    CAknAppUiBase* appUi = static_cast<CAknAppUiBase*>( iEikonEnv->EikAppUi() );
    if ( AknLayoutUtils::DefaultScrollBarType( appUi ) == CEikScrollBarFrame::EDoubleSpan )
        {
        // For EDoubleSpan type scrollbar
        iSBFrame->CreateDoubleSpanScrollBarsL( EFalse, EFalse ); // non-window owning scrollbar            
        iSBFrame->SetTypeOfVScrollBar( CEikScrollBarFrame::EDoubleSpan );
        iSBFrame->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto );
        TAknWindowLineLayout scrollPane = AknLayoutScalable_Apps::scroll_pane_cp017().LayoutLine();
        AknLayoutUtils::LayoutVerticalScrollBar( iSBFrame, Rect(), scrollPane );
        }
    else
        {
        // For EArrowHead type scrollbar
        iSBFrame->SetTypeOfVScrollBar( CEikScrollBarFrame::EArrowHead );
        iSBFrame->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto );
        }
    ActivateL();
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::UpdateScrollIndicatorL
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::UpdateScrollIndicatorL() const
    {
    if ( !iSBFrame )
        {
        return;
        }
    
    
    TEikScrollBarModel hSbarModel;
    TEikScrollBarModel vSbarModel;
    vSbarModel.iThumbSpan = 1;
    
    vSbarModel.iThumbPosition = iCurrentScreen; // where is the position  
    // how many items
    // if there is only one screen we don't need scroll bars (= 0)
    
    if ( iNumberOfScreens == KOneScreen )
        {
        vSbarModel.iScrollSpan = 0;
        iSBFrame->SetScrollBarVisibilityL( 
            CEikScrollBarFrame::EOff, 
            CEikScrollBarFrame::EOff );
        }
    else
        {
        vSbarModel.iScrollSpan = iNumberOfScreens;
        iSBFrame->SetScrollBarVisibilityL( 
            CEikScrollBarFrame::EOff, 
            CEikScrollBarFrame::EAuto );
        }
    
    if ( iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan )
        {    
        // For EDoubleSpan type scrollbar
        TAknDoubleSpanScrollBarModel hDsSbarModel( hSbarModel );
        TAknDoubleSpanScrollBarModel vDsSbarModel( vSbarModel );
        
        TEikScrollBarFrameLayout layout;
        layout.iTilingMode = TEikScrollBarFrameLayout::EInclusiveRectConstant;
        TRect inclusiveRect( Rect( ) ); // We need to have two of these variables
        TRect clientRect( Rect( ) );
        
        iSBFrame->TileL( &hDsSbarModel, &vDsSbarModel, clientRect, inclusiveRect, layout );
        iSBFrame->SetVFocusPosToThumbPos( vSbarModel.iThumbPosition );
        }
    else
        {
        iSBFrame->Tile( &vSbarModel );
        iSBFrame->SetVFocusPosToThumbPos( vSbarModel.iThumbPosition );
        }
    iSBFrame->DrawScrollBarsNow();
    
    }

// ---------------------------------------------------------
// CCbsUiMsgViewContainer::UpdateCurrentScreen
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::UpdateCurrentScreen( TBool aIncrease )
    {
    if ( aIncrease )
        {
        if ( iCurrentScreen < iNumberOfScreens - 1 )
            {
            iCurrentScreen++;
            }
        }
    else
        {
        if ( iCurrentScreen > KFirstScreen )
            {
            iCurrentScreen--;
            }
        }
    
    }

// ---------------------------------------------------------
// CCbsUiMsgViewContainer::SetReadOnly
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::SetReadOnly( TBool aReadOnly )
    {
    __ASSERT_DEBUG(iEditor, CbsUiPanic(EErrNullPointer) );
    iEditor->SetReadOnly(aReadOnly);
    }

// ---------------------------------------------------------
// CCbsUiMsgViewContainer::SetDataContentL
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::SetDataContentL( CRichText& aText )
    {
    iEditor->SetDocumentContentL(aText);
    iEditor->SelectAllL(); // This is needed before calling layoutedwin!


    if ( AknLayoutUtils::ScalableLayoutInterfaceAvailable() )
        {
        TAknLayoutScalableParameterLimits scalbleParamLimits;
        scalbleParamLimits = AknLayoutScalable_Apps::list_single_mce_message_pane_ParamLimits();
        AknLayoutUtils::LayoutEdwin( iEditor, Rect(), AppLayout::Multiline_Message_writing_texts_Line_3(scalbleParamLimits.LastRow() ) );
        }
    else
        {
        AknLayoutUtils::LayoutEdwin( iEditor, Rect(), AppLayout::Multiline_Message_writing_texts_Line_3( KEditorNumOfLines ) );
        }
    }

// ---------------------------------------------------------
// CCbsUiMsgViewContainer::SetData16L
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::SetData16L( const TDesC& aBuf )
    {
    __ASSERT_DEBUG(aBuf.Length() > 0, CbsUiPanic(EErrInvalidValue) );
    
    CParaFormatLayer* globalParaLayer = CParaFormatLayer::NewL();
    CleanupStack::PushL(globalParaLayer);
                   
    CCharFormatLayer* globalCharLayer = NULL;   
    TRgb textColor;

    TCharFormat charFormat;
    TCharFormatMask formatMask;
        
    ( reinterpret_cast< CGlobalText* >( iEditor->Text() ) )
        ->GetCharFormat( charFormat, formatMask, 0, 0 );                        

    TInt error = AknsUtils::GetCachedColor(
        AknsUtils::SkinInstance(),
        textColor,
        KAknsIIDQsnTextColors,
        EAknsCIQsnTextColorsCG6 );
        
    if ( error != KErrNone )
        {
        textColor = KRgbBlack;
        }
                
    charFormat.iFontPresentation.iTextColor = textColor;
    formatMask.SetAll();

    globalCharLayer = CCharFormatLayer::NewL( charFormat, formatMask );
    CleanupStack::PushL( globalCharLayer );
     
    CRichText* richText = CRichText::NewL( globalParaLayer, globalCharLayer );
    CleanupStack::PushL( richText );
    
    TInt length( aBuf.Size() / 2 );
    
    for (TInt i = 0; i < length; i++)
        {     
        if ( aBuf[i] == EKeyLineFeed )
            {            
            richText->InsertL( i, CEditableText::EParagraphDelimiter );
            }
        else 
            {
            richText->InsertL( i, aBuf[i] );
            }
        }
    
    SetDataContentL( *richText );
    
    iEditor->SetCharFormatLayer( globalCharLayer );
                
    CleanupStack::PopAndDestroy();  // richText
    CleanupStack::Pop();            // globalCharLayer
    CleanupStack::PopAndDestroy();  // globalParaLayer
    }

// ---------------------------------------------------------
// CCbsUiMsgViewContainer::GetEditor
// 
// 
// ---------------------------------------------------------
//
CRichText* CCbsUiMsgViewContainer::GetEditor() const
    {
    __ASSERT_DEBUG(iEditor->RichText()->LdDocumentLength() > 0, 
        CbsUiPanic(EErrInvalidValue) );
    
    return iEditor->RichText();
    }


// ---------------------------------------------------------
// CCbsUiMsgViewContainer::CopyToClipboard
// 
// 
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::CopyToClipboardL() const
    {
    TInt msgLength;
    
    msgLength = iEditor->TextLength();
    if ( SysUtil::FFSSpaceBelowCriticalLevelL(  &iCoeEnv->FsSession(), 2 * msgLength ) )
        {
        User::Leave( KErrDiskFull );
        }
    
    CPlainText* plainText = CPlainText::NewL();
    
    CleanupStack::PushL(plainText);
    plainText->InsertL( 0, iEditor->RichText()->Read(0) );
    plainText->ConvertAllFieldsToText();
    
    CClipboard* cb = CClipboard::NewForWritingLC( iCoeEnv->FsSession() );
    plainText->CopyToStoreL( 
        cb->Store(), 
        cb->StreamDictionary(), 
        0, 
        plainText->DocumentLength() );
    
    cb->CommitL();
    CleanupStack::PopAndDestroy(2);  //cb, plainText
    }


// ----------------------------------------------------
// CCbsUiMsgViewContainer::HandleResourceChange
//
//
// ----------------------------------------------------
void CCbsUiMsgViewContainer::HandleResourceChange( TInt aType )
    {
    CCoeControl::HandleResourceChange( aType );
    if( aType == KEikDynamicLayoutVariantSwitch )
        {
        TRAPD( ignore, iMsgView.HandleRectChangeInContainerL() );
        if ( iBackGroundControlContext )
            {
            iBackGroundControlContext->SetRect( Rect() );
            }
        
        if( ignore )
            {
            ignore = KErrNone; //Prevent ARMV5 compilation varning
            }
        }
    else
        {
        if( ( aType == KAknsMessageSkinChange ) && ( iBackGroundControlContext ) )
            {
            TRAPD( ignore, iEditor->SetSkinBackgroundControlContextL( iBackGroundControlContext ) );
            if( ignore )
                {
                ignore = KErrNone; //Prevent ARMV5 compilation varning
                }
            } 
        }
    
     }


// ----------------------------------------------------
// CCbsUiMsgViewContainer::HandleScrollEventL
// ----------------------------------------------------
void CCbsUiMsgViewContainer::HandleScrollEventL( CEikScrollBar* aScrollBar, 
                                         TEikScrollEvent aEventType )
    {
    switch( aEventType )
        {
        case EEikScrollUp:
        case EEikScrollPageUp:
            {
            ScrollMessageUpL();
            break;
            }
        case EEikScrollDown:
        case EEikScrollPageDown:
            {
            ScrollMessageDownL();
            break;
            }
        case EEikScrollThumbDragVert:
            {
            if( aScrollBar->ThumbPosition() > iCurrentScreen )
                {
                ScrollMessageDownL();
                }
            else if ( aScrollBar->ThumbPosition() < iCurrentScreen )
                {
                ScrollMessageUpL();    
                }
            break;
            }
        default:
            break;
        }
    }

// ----------------------------------------------------
// CCbsUiMsgViewContainer::ScrollMessageUpL
// ----------------------------------------------------
void CCbsUiMsgViewContainer::ScrollMessageUpL()
    {
    if( iCurrentScreen > 0 )
        {
        iEditor->MoveDisplayL( TCursorPosition::EFPageUp );
        iEditor->MoveDisplayL( TCursorPosition::EFLineUp );
        UpdateCurrentScreen( EFalse );
        UpdateScrollIndicatorL();
        }
    }

// ----------------------------------------------------
// CCbsUiMsgViewContainer::ScrollMessageDownL
// ----------------------------------------------------
void CCbsUiMsgViewContainer::ScrollMessageDownL()
    {
    if( iCurrentScreen < iNumberOfScreens-1 )
        {
        iEditor->MoveDisplayL( TCursorPosition::EFPageDown );
        iEditor->MoveDisplayL( TCursorPosition::EFLineDown );
        UpdateCurrentScreen( ETrue );
        UpdateScrollIndicatorL();
        }
    }

// ---------------------------------------------------------
// CCbsUiMsgViewContainer::GetHelpContext
// 
// Gets the control's help context.
// ---------------------------------------------------------
//
void CCbsUiMsgViewContainer::GetHelpContext( TCoeHelpContext& aContext ) const
    {
    aContext.iMajor = TUid::Uid(KUidCbsUiappDef);
    aContext.iContext = KCBS_HLP_MSG;
    }


//  End of File