diff -r 000000000000 -r f72a12da539e idlehomescreen/xmluirendering/renderingplugins/xnnewstickerfactory/src/xnnewstickercontrol.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/idlehomescreen/xmluirendering/renderingplugins/xnnewstickerfactory/src/xnnewstickercontrol.cpp Thu Dec 17 08:40:49 2009 +0200 @@ -0,0 +1,1402 @@ +/* +* Copyright (c) 2002-2006 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: Text scrolling functionality. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include + +#include "xnnewstickercontrol.h" +#include "xnnewstickeradapter.h" +#include "xnproperty.h" + +// CONSTANTS +/** +* for the empty space in pixels between text and image. +*/ +const TInt KGap = 10; + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::CTitleData +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::CTitleData::CTitleData(TInt aLenghtInPixels) : + iTitleIsSvg(EFalse), iTextLenghtInPixels(aLenghtInPixels) + { + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::CTitleData::~CTitleData() + { + delete iText; + delete iData; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::CTitleData::ConstructL(const TDesC& aTitle) + { + delete iText; + iText = NULL; + iText = aTitle.AllocL(); + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::CTitleData::ConstructL(const TDesC8& aByteData) + { + iTitleIsSvg = ETrue; + iData = aByteData.AllocL(); + iText = KNullDesC().AllocL(); + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::CTitleData* CXnNewstickerControl::CTitleData::NewL( + const TDesC& aTitle, TInt aLenghtInPixels) + { + CXnNewstickerControl::CTitleData* self = + CXnNewstickerControl::CTitleData::NewLC(aTitle, aLenghtInPixels); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::CTitleData* CXnNewstickerControl::CTitleData::NewLC( + const TDesC& aTitle, TInt aLenghtInPixels) + { + CXnNewstickerControl::CTitleData* self = + new(ELeave) CXnNewstickerControl::CTitleData(aLenghtInPixels); + CleanupStack::PushL(self); + self->ConstructL(aTitle); + return self; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::CTitleData* CXnNewstickerControl::CTitleData::NewL( + const TDesC8& aByteData) + { + CXnNewstickerControl::CTitleData* self = + CXnNewstickerControl::CTitleData::NewLC(aByteData); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::CTitleData* CXnNewstickerControl::CTitleData::NewLC( + const TDesC8& aByteData) + { + CXnNewstickerControl::CTitleData* self = + new(ELeave) CXnNewstickerControl::CTitleData(); + CleanupStack::PushL(self); + self->ConstructL(aByteData); + return self; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::TitleText +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +const TDesC& CXnNewstickerControl::CTitleData::TitleText() + { + return *iText; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::SetTitleText +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::CTitleData::SetTitleTextL(const TDesC& aTitle) + { + HBufC* newTitle = aTitle.AllocL(); + delete iText; + iText = newTitle; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::TitleTextLengthInPixels +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CXnNewstickerControl::CTitleData::TitleTextLengthInPixels() + { + return iTextLenghtInPixels; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::SetTitleTextLengthInPixels +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::CTitleData::SetTitleTextLengthInPixels(TInt aLenghtInPixels) + { + iTextLenghtInPixels = aLenghtInPixels; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::IsSvgTitle +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CXnNewstickerControl::CTitleData::IsSvgTitle() + { + return iTitleIsSvg; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CTitleData::SvgTitleData +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +const TDesC8& CXnNewstickerControl::CTitleData::SvgTitleData() + { + return *iData; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CXnNewstickerControl +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::CXnNewstickerControl(CXnNewstickerAdapter* aAdapter) : + iFirstDrawingTitleIndex(0), + iFirstDrawingOffset(0), + iImageWidthInPixels(0), + iCurrentTitleIndex(-1), + iSeparatorimage(NULL), + iSeparatorImageWidth(0), + iFont(NULL), + iTextBaseline(0), + iTextColor(KRgbBlack), + iUnderlining(EUnderlineOff), + iStrikethrough(EStrikethroughOff), + iIsWestern(ETrue), + iAdapter(aAdapter), + iTextAlignment(ELayoutAlignLeft) + { + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::ConstructL() + { + if(AknLayoutUtils::LayoutMirrored()) + { + iIsWestern = EFalse; + iTextAlignment = ELayoutAlignRight; + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl* CXnNewstickerControl::NewL(CXnNewstickerAdapter* aAdapter) + { + CXnNewstickerControl* self = new(ELeave)CXnNewstickerControl(aAdapter); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::~CXnNewstickerControl() +// Destructor. +// ----------------------------------------------------------------------------- +// +CXnNewstickerControl::~CXnNewstickerControl() + { + iTitles.ResetAndDestroy(); + delete iSeparatorimage; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetScrollAmount +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::SetScrollAmount(TInt aScrollAmount) + { + iSpeed = aScrollAmount; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetNewstickerRect +// Set visible rect. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::SetNewstickerRect(TRect& aContentRect) + { + if(iContentRect != aContentRect) + { + iContentRect = aContentRect; + iTextBaseline = iContentRect.Height() / 2 + iFont->AscentInPixels() / 2; + SetBeginningState(); + for(TInt i = 0; i < iTitles.Count(); i++) + { + if(!iTitles[i]->IsSvgTitle()) + { + TInt textWidth = iFont->TextWidthInPixels( + iTitles[i]->TitleText()); + iTitles[i]->SetTitleTextLengthInPixels(textWidth); + } + } + CalculateTextFitInNewstickerRect(); + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::IsWestern +// Returns ETrue if western layout is used, otherwise EFalse is returned. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CXnNewstickerControl::IsWestern() + { + return iIsWestern; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::AppendTitleL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::AppendTitleL(const TDesC& aTitle) + { + TInt textWidth = iFont->TextWidthInPixels(aTitle); + CTitleData* title = CTitleData::NewLC(aTitle, textWidth); + iTitles.AppendL(title); + CleanupStack::Pop(title); + + CalculateTextFitInNewstickerRect(); + + // if this is the first item + if(iTitles.Count() == 1) + { + iCurrentTitleIndex = 0; + iAdapter->StartL(); + } + } + +// --------------------------------------------------------- +// CXnNewstickerControl::InsertTitleL +// --------------------------------------------------------- +// +void CXnNewstickerControl::InsertTitleL(const TDesC& aTitle, TInt aIndex) + { + TInt textWidth = iFont->TextWidthInPixels(aTitle); + CTitleData* title = CTitleData::NewLC(aTitle, textWidth); + iTitles.InsertL(title, aIndex); + CleanupStack::Pop(title); + + + CountIndexAfterInsertL(aIndex); + CalculateTextFitInNewstickerRect(); + } + +// --------------------------------------------------------- +// CXnNewstickerControl::UpdateTitleL +// --------------------------------------------------------- +// +void CXnNewstickerControl::UpdateTitleL(const TDesC& aTitle, TInt aIndex) + { + if ( aIndex >= 0 && aIndex < iTitles.Count() ) + { + CTitleData* titleData = iTitles[aIndex]; + TInt textWidth = iFont->TextWidthInPixels(aTitle); + titleData->SetTitleTextL(aTitle); + titleData->SetTitleTextLengthInPixels(textWidth); + CalculateTextFitInNewstickerRect(); + } + else + { + AppendTitleL(aTitle); + } + } + +// --------------------------------------------------------- +// CXnNewstickerControl::DeleteTitle +// --------------------------------------------------------- +// +void CXnNewstickerControl::DeleteTitleL(TInt aIndex) + { + TInt count = iTitles.Count(); + if (aIndex >= 0 && aIndex < count) + { + // If the last item will be deleted + if(count == 1) + { + iAdapter->StopL(); + iFirstDrawingTitleIndex = GetNextTitleWithContent( 0 ); + SetBeginningState(); + iCurrentTitleIndex = -1; + } + if (aIndex == iFirstDrawingTitleIndex) + { + // If this happens to be the last item in the list + if(aIndex == count - 1) + { + iFirstDrawingTitleIndex = GetNextTitleWithContent( 0 ); + } + SetBeginningState(); + iCurrentTitleIndex = iFirstDrawingTitleIndex; + } + + // Check if the title was deleted before the current title + else if (aIndex < iFirstDrawingTitleIndex) + { + iCurrentTitleIndex--; + iFirstDrawingTitleIndex = GetNextTitleWithContent( iFirstDrawingTitleIndex-1, ETrue); + } + UpdateTitleL(KNullDesC, aIndex); + CalculateTextFitInNewstickerRect(); + } + } + +// --------------------------------------------------------- +// CXnNewstickerControl::CurrentTitleIndex +// --------------------------------------------------------- +// +TInt CXnNewstickerControl::CurrentTitleIndex() + { + return iCurrentTitleIndex; + } + +// --------------------------------------------------------- +// CXnNewstickerControl::Title +// --------------------------------------------------------- +// +const TDesC& CXnNewstickerControl::Title(TInt aIndex) + { + if (aIndex < 0 || aIndex > iTitles.Count()) + { + return KNullDesC; + } + + if (iTitles[aIndex]->IsSvgTitle()) + { + return KNullDesC; + } + + return iTitles[aIndex]->TitleText(); + } + +// --------------------------------------------------------- +// CXnNewstickerControl::SetSeparatorImageL +// --------------------------------------------------------- +// +TInt CXnNewstickerControl::SetSeparatorImageL(CGulIcon* aIcon) + { + CFbsBitmap* bitmap = aIcon->Bitmap(); + if(AknIconUtils::IsMifIcon(bitmap)) + { + delete iSeparatorimage; + iSeparatorimage = aIcon; + TInt maxHeight = iContentRect.Height(); + TSize size = TSize(maxHeight, maxHeight); + AknIconUtils::SetSize(bitmap, size, EAspectRatioPreservedAndUnusedSpaceRemoved); + iSeparatorImageWidth = bitmap->SizeInPixels().iWidth + KGap; + return KErrNone; + } + else + { + iSeparatorimage = NULL; + return KErrNotSupported; + } + } + +// --------------------------------------------------------- +// CXnNewstickerControl::ClearTitles +// --------------------------------------------------------- +// +void CXnNewstickerControl::ClearTitles() + { + TRAP_IGNORE(iAdapter->StopL()); + iFirstDrawingTitleIndex = 0; + SetBeginningState(); + iCurrentTitleIndex = -1; + // Don't delete just clear the contents + for( TInt i = 0; i < iTitles.Count(); ++i ) + { + TRAP_IGNORE( UpdateTitleL( KNullDesC, i ) ); + } + iTextFitInNewstickerRect = EFalse; + } + +// --------------------------------------------------------- +// CXnNewstickerControl::AppendSvgTitleL +// --------------------------------------------------------- +// +void CXnNewstickerControl::AppendSvgTitleL(const TDesC8& aByteData) + { + CTitleData* title = CTitleData::NewLC(aByteData); + iTitles.AppendL(title); + CleanupStack::Pop(title); + + // if this is the first item + if(iTitles.Count() == 1) + { + iCurrentTitleIndex = 0; + iAdapter->StartL(); + } + } + +// --------------------------------------------------------- +// CXnNewstickerControl::InsertSvgTitleL +// --------------------------------------------------------- +// +void CXnNewstickerControl::InsertSvgTitleL(const TDesC8& aByteData, TInt aIndex) + { + CTitleData* title = CTitleData::NewLC(aByteData); + iTitles.InsertL(title, aIndex); + CleanupStack::Pop(title); + CountIndexAfterInsertL(aIndex); + } + +// --------------------------------------------------------- +// CXnNewstickerControl::CurrentSvgTitle +// --------------------------------------------------------- +// +const TDesC8& CXnNewstickerControl::CurrentSvgTitle() + { + CTitleData* title = iTitles[iFirstDrawingTitleIndex]; + // Is it SVG title + if (title->IsSvgTitle()) + { + // Yes, advance the title index + iFirstDrawingTitleIndex++; + if (iFirstDrawingTitleIndex >= iTitles.Count()) + { + iFirstDrawingTitleIndex = 0; + } + + // Return the data + return title->SvgTitleData(); + } + + // Not svg title, return empty desc + return KNullDesC8; + } + +// --------------------------------------------------------- +// CXnNewstickerControl::TitleCount +// --------------------------------------------------------- +// +TInt CXnNewstickerControl::TitleCount() const + { + return iTitles.Count(); + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::MoveToNext +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::MoveToNextL() + { + // If there are no titles, don't do anything. + if (!IsVisibleTitles()) + { + return ; + } + // Skip notification of the first title + if ( iCurrentTitleIndex != GetNextTitleWithContent( 0 ) ) + { + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleScrolled); + } + // Don't report the last TitleToScroll in case the scroll ended + if ( iAdapter->CurrentState() != CXnNewstickerAdapter::EScrollEnded ) + { + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleToScroll); + } + iAdapter->TitleScrolled(iFirstDrawingTitleIndex); + if (iAdapter->CurrentState() == CXnNewstickerAdapter::EAnimation) + { + iCurrentTitleIndex = GetNextTitleWithContent( iCurrentTitleIndex + 1 ); + iFirstDrawingTitleIndex = iCurrentTitleIndex; + } + else + { + iCurrentTitleIndex = GetNextTitleWithContent( iFirstDrawingTitleIndex + 1); + iFirstDrawingTitleIndex = iCurrentTitleIndex; + } + + // Check that we are still in range + if (iFirstDrawingTitleIndex >= iTitles.Count() || iFirstDrawingTitleIndex < 0) + { + iFirstDrawingTitleIndex = GetNextTitleWithContent( 0 ); + iCurrentTitleIndex = iFirstDrawingTitleIndex; + } + + SetBeginningState(); + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::MoveToFirstL +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::MoveToFirstL() + { + // If there are no titles, don't do anything. + if (!IsVisibleTitles()) + { + return ; + } + // Something already scrolling, report scroll done + if ( iAdapter->CurrentState() == CXnNewstickerAdapter::EText ) + { + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleScrolled); + iAdapter->TitleScrolled(iFirstDrawingTitleIndex); + } + + TInt start = 0; // iIsWestern ? 0 : (iTitles.Count() - 1); + + iCurrentTitleIndex = GetNextTitleWithContent( start ); + iFirstDrawingTitleIndex = iCurrentTitleIndex; + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleToScroll); + SetBeginningState(); + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::MoveToLastL +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::MoveToLastL() + { + // If there are no titles, don't do anything. + if (!IsVisibleTitles()) + { + return ; + } + // Something already scrolling, report scroll done + if ( iAdapter->CurrentState() == CXnNewstickerAdapter::EText ) + { + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleScrolled); + iAdapter->TitleScrolled(iFirstDrawingTitleIndex); + } + + TInt start = iTitles.Count() - 1; // iIsWestern ? (iTitles.Count() - 1) : 0; + + iCurrentTitleIndex = GetNextTitleWithContent( start, ETrue ); + iFirstDrawingTitleIndex = iCurrentTitleIndex; + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleToScroll); + SetBeginningState(); + } +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::MoveToPrev +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::MoveToPrevL() + { + // If there are no titles, don't do anything. + if (!IsVisibleTitles()) + { + return ; + } + + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleScrolled); + + if (iAdapter->CurrentState() == CXnNewstickerAdapter::EAnimation) + { + iCurrentTitleIndex = GetNextTitleWithContent( iCurrentTitleIndex - 1, ETrue ); + iFirstDrawingTitleIndex = iCurrentTitleIndex; + } + else + { + iFirstDrawingTitleIndex = GetNextTitleWithContent( iFirstDrawingTitleIndex - 1, ETrue ); + iCurrentTitleIndex = iFirstDrawingTitleIndex; + } + // Check that we are still in range + if (iFirstDrawingTitleIndex >= iTitles.Count() || iFirstDrawingTitleIndex < 0) + { + iFirstDrawingTitleIndex = GetNextTitleWithContent( iTitles.Count() - 1, ETrue ); + iCurrentTitleIndex = iFirstDrawingTitleIndex; + } + + iAdapter->ReportNewstickerEventL(XnPropertyNames::action::trigger::name::KTitleToScroll); + SetBeginningState(); + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::MoveToCurrent +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::MoveToCurrent() + { + // If there are no titles, don't do anything. + if (!IsVisibleTitles()) + { + return ; + } + + iFirstDrawingTitleIndex = iCurrentTitleIndex; + SetBeginningState(); + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CountIndexAfterInsert +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::CountIndexAfterInsertL(TInt aIndex) + { + // Check if the new title was inserted before the first drawing title + if (aIndex <= iFirstDrawingTitleIndex) + { + iCurrentTitleIndex++; + iFirstDrawingTitleIndex++; + } + + // if this is the first item + if(iTitles.Count() == 1 && GetNextTitleWithContent( 0 ) == 0) + { + iCurrentTitleIndex = 0; + iFirstDrawingTitleIndex = 0; + iAdapter->StartL(); + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetFont +// ----------------------------------------------------------------------------- +void CXnNewstickerControl::SetFont(CFont* aFont) + { + if(iFont != aFont) + { + for(TInt i = 0; i < iTitles.Count(); i++) + { + if(!iTitles[i]->IsSvgTitle()) + { + TInt textWidth = aFont->TextWidthInPixels( + iTitles[i]->TitleText()); + iTitles[i]->SetTitleTextLengthInPixels(textWidth); + } + } + iFont = aFont; + iTextBaseline = iContentRect.Height() / 2 + iFont->AscentInPixels() / 2; + CBitmapContext* gc = iAdapter->BufferGc(); + if(gc) + { + gc->UseFont(aFont); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetTextColor +// ----------------------------------------------------------------------------- +void CXnNewstickerControl::SetTextColor(TRgb aColor) + { + iTextColor = aColor; + CBitmapContext* gc = iAdapter->BufferGc(); + if(gc) + { + gc->SetPenColor(iTextColor); + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetTextUnderlineStyle +// ----------------------------------------------------------------------------- +void CXnNewstickerControl::SetTextUnderlineStyle(TFontUnderline aStyle) + { + iUnderlining = aStyle; + CBitmapContext* gc = iAdapter->BufferGc(); + if(gc) + { + gc->SetUnderlineStyle(iUnderlining); + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetTextUnderlineStyle +// ----------------------------------------------------------------------------- +void CXnNewstickerControl::SetTextStrikethroughStyle(TFontStrikethrough aStyle) + { + iStrikethrough = aStyle; + CBitmapContext* gc = iAdapter->BufferGc(); + if(gc) + { + gc->SetStrikethroughStyle(iStrikethrough); + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::PrepareToDrawL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::PrepareToDrawLtrL() + { + CBitmapContext* gc = iAdapter->BufferGc(); + const CFbsBitmap* background = iAdapter->BackgroundBitmap(); + if(!gc || !background || !IsVisibleTitles() ) + { + return; + } + iFirstDrawingTitleIndex = GetNextTitleWithContent( iFirstDrawingTitleIndex ); + if ( iFirstDrawingTitleIndex < 0 ) + { + return; + } + if (iTitles[iFirstDrawingTitleIndex]->IsSvgTitle()) + { + // Show SVG title + iAdapter->ShowSvgL(); + + // Just in case, draw background to d-buffer + gc->BitBlt(TPoint(0,0), background); + return; + } + + CGraphicsContext::TTextAlign alignment = TextAlignment(); + if ( iTextFitInNewstickerRect || + iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EAlternate && iTitles.Count() == 1 ) + { + iAdapter->StopL(); + SetBeginningState(); + } + + TInt drawingPos(-iFirstDrawingOffset); + + // At first, draw background + gc->BitBlt(TPoint(0,0), background); + TInt textLeft = iTitles[iFirstDrawingTitleIndex]->TitleTextLengthInPixels() - + iFirstDrawingOffset; + TInt drawingTitleIndex = iFirstDrawingTitleIndex; + TInt drawingOffset(0); + + // Main drawing loop. This loop runs as long as drawing area is not filled + // if Scroll behaviour is slide, then short text drawn only once. + FOREVER + { + TRect clipRect(TPoint(drawingPos,0), TPoint(iContentRect.Width(), iContentRect.Height())); + if ( iTextFitInNewstickerRect ) + { + clipRect.SetWidth( clipRect.Width()-drawingPos); + } + // if the rest text fits into visible area + if (textLeft <= iContentRect.Width() - drawingOffset) + { + gc->DrawText(iTitles[drawingTitleIndex]->TitleText(), + clipRect, + iTextBaseline, + alignment); + + TInt drawnLength = iTitles[drawingTitleIndex]->TitleTextLengthInPixels() + KGap; + drawingPos += drawnLength; + drawingOffset = drawingPos; + + // Update title index, if needed + drawingTitleIndex++; + if(drawingTitleIndex >= iTitles.Count()) + { + drawingTitleIndex = 0; + if ( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::ESlide || iTextFitInNewstickerRect ) + { + // what a dirty code! + break; + } + } + if(iSeparatorimage) + { + textLeft = 0; + } + else + { + if (iTitles[drawingTitleIndex]->IsSvgTitle()) + { + return; + } + else + { + textLeft = iTitles[drawingTitleIndex]->TitleTextLengthInPixels(); + } + } + } + else + { + // Clip the text if needed in alternate mode + if ( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EAlternate ) + { + HBufC* title = iTitles[drawingTitleIndex]->TitleText().AllocLC(); + TPtr titlePtr = title->Des(); + TInt maxLength = iContentRect.Width(); + AknBidiTextUtils::ConvertToVisualAndClipL( + titlePtr, *iFont, maxLength, maxLength ); + gc->DrawText( titlePtr, clipRect, iTextBaseline, alignment ); + CleanupStack::PopAndDestroy( title ); + } + else + { + gc->DrawText(iTitles[drawingTitleIndex]->TitleText(), + clipRect, + iTextBaseline, + alignment); + + } + break; + } + + if(iSeparatorimage) + { + TInt imageLeft = iSeparatorImageWidth - KGap; + + // if the rest of the image fits into visible area + if (imageLeft <= iContentRect.Width() - drawingOffset) + { + gc->BitBltMasked(TPoint(drawingPos, 0), iSeparatorimage->Bitmap(), + TRect(TPoint(0,0), + iSeparatorimage->Bitmap()->SizeInPixels()), iSeparatorimage->Mask(), ETrue); + drawingPos += iSeparatorImageWidth; + drawingOffset = drawingPos; + textLeft = iTitles[drawingTitleIndex]->TitleTextLengthInPixels(); + if (iTitles[drawingTitleIndex]->IsSvgTitle()) + { + return; + } + } + else + { + gc->BitBltMasked(TPoint(drawingPos, 0), iSeparatorimage->Bitmap(), + TRect(TPoint(0,0), iSeparatorimage->Bitmap()->SizeInPixels()), + iSeparatorimage->Mask(), ETrue); + break; + } + } + + if( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EAlternate || + iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate ) + { + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::PrepareToDrawRtlL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::PrepareToDrawRtlL() + { + CBitmapContext* gc = iAdapter->BufferGc(); + const CFbsBitmap* background = iAdapter->BackgroundBitmap(); + if(!gc || !background || !IsVisibleTitles() ) + { + return; + } + if (iTitles[iFirstDrawingTitleIndex]->IsSvgTitle()) + { + // Show SVG title + iAdapter->ShowSvgL(); + + // Just in case, draw background to d-buffer + gc->BitBlt(TPoint(0,0), background); + return; + } + + CGraphicsContext::TTextAlign alignment = TextAlignment(); + if ( iTextFitInNewstickerRect || + iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EAlternate && iTitles.Count() == 1 ) + { + SetBeginningState(); + iAdapter->StopL(); + } + + // At first, draw background + gc->BitBlt(TPoint(0,0), background); + + TInt textLeft = iFirstDrawingOffset - + iTitles[iFirstDrawingTitleIndex]->TitleTextLengthInPixels(); + if(textLeft >= iContentRect.Width() ) + { + textLeft = 0; + } + TInt drawingTitleIndex = iFirstDrawingTitleIndex; + TInt drawingOffset(iContentRect.iBr.iX); + + TRect clipRect(TPoint(0,0), TPoint(iFirstDrawingOffset, iContentRect.Height())); + TInt clipWidth = clipRect.Width(); + // Main drawing loop. This loop runs as long as drawing area is not filled + FOREVER + { + // if the rest text fits into visible area + if (textLeft <= drawingOffset) + { + HBufC* title = iTitles[drawingTitleIndex]->TitleText().AllocLC(); + TPtr titlePtr = title->Des(); + + // convert to visual, do not clip + TInt maxLength = iTitles[drawingTitleIndex]->TitleTextLengthInPixels(); + AknBidiTextUtils::ConvertToVisualAndClipL( titlePtr, *iFont, + maxLength, maxLength ); + + gc->DrawText( titlePtr, clipRect, iTextBaseline, alignment ); + CleanupStack::PopAndDestroy( title ); + + TInt drawnLength = iTitles[drawingTitleIndex]->TitleTextLengthInPixels() + KGap; + clipWidth -= drawnLength; + clipRect.SetWidth(clipWidth); + drawingOffset = clipRect.iBr.iX; + + // Update title index + drawingTitleIndex++; + if(drawingTitleIndex >= iTitles.Count()) + { + drawingTitleIndex = 0; + if ( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::ESlide || iTextFitInNewstickerRect) + { + // what a dirty code! + break; + } + } + if(iSeparatorimage) + { + textLeft = 0xfff; + } + else + { + if (iTitles[drawingTitleIndex]->IsSvgTitle()) + { + return; + } + else + { + textLeft = iTitles[drawingTitleIndex]->TitleTextLengthInPixels(); + } + } + } + else + { + // Clip the text if needed in alternate mode + if ( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EAlternate ) + { + HBufC* title = iTitles[drawingTitleIndex]->TitleText().AllocLC(); + TPtr titlePtr = title->Des(); + TInt maxLength = iContentRect.Width(); + AknBidiTextUtils::ConvertToVisualAndClipL( + titlePtr, *iFont, maxLength, maxLength ); + gc->DrawText( titlePtr, clipRect, iTextBaseline, alignment ); + CleanupStack::PopAndDestroy( title ); + } + else + { + gc->DrawText(iTitles[drawingTitleIndex]->TitleText(), clipRect, + iTextBaseline, alignment); + } + break; + } + + if(iSeparatorimage) + { + TInt imageLeft = iSeparatorImageWidth - KGap; + + // if the rest of the image fits into visible area + if (imageLeft <= drawingOffset) + { + gc->BitBltMasked(TPoint(clipRect.iBr.iX - imageLeft, 0), + iSeparatorimage->Bitmap(), TRect(TPoint(0,0), + iSeparatorimage->Bitmap()->SizeInPixels()), + iSeparatorimage->Mask(), ETrue); + clipWidth -= iSeparatorImageWidth; + clipRect.SetWidth(clipWidth); + drawingOffset = clipRect.iBr.iX; + textLeft = iTitles[drawingTitleIndex]->TitleTextLengthInPixels(); + if (iTitles[drawingTitleIndex]->IsSvgTitle()) + { + return; + } + } + else + { + gc->BitBltMasked(TPoint(clipRect.iBr.iX - imageLeft, 0), + iSeparatorimage->Bitmap(), TRect(TPoint(0,0), + iSeparatorimage->Bitmap()->SizeInPixels()), + iSeparatorimage->Mask(), ETrue); + break; + } + } + + if( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EAlternate || + iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate ) + { + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::DoScrollL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::DoScrollL() + { + // If there are no titles, don't do anything. + if( !IsVisibleTitles() || iFirstDrawingTitleIndex < 0 ) + { + return; + } + + iAdapter->DrawNow(); + + if( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScroll || + iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::ESlide || + ( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate && + !CalculateCurrentTextFitInNewstickerRect() ) ) + { + iAdapter->SetTimerToScrolltime(); + iFirstDrawingOffset += iSpeed; // advance text + TInt titleLen = iTitles[iFirstDrawingTitleIndex]->TitleTextLengthInPixels() + + iSeparatorImageWidth; + + // if 100% (or more) has been drawn update... + if ((iIsWestern && iFirstDrawingOffset >= titleLen) || + (!iIsWestern && iFirstDrawingOffset - titleLen >= iContentRect.Width())) + { + iAdapter->TitleScrolled(iFirstDrawingTitleIndex); + iFirstDrawingTitleIndex = GetNextTitleWithContent( iFirstDrawingTitleIndex + 1); + if(iFirstDrawingTitleIndex >= iTitles.Count()) + { + iFirstDrawingTitleIndex = GetNextTitleWithContent( 0 ); + if (iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::ESlide ) + { + if ( iIsWestern ) + { + iFirstDrawingOffset = -(iContentRect.iBr.iX-iContentRect.iTl.iX-KGap); + } + else + { + iFirstDrawingOffset = 0; + } + } + else + { + iFirstDrawingOffset -= titleLen + KGap; + } + } + else + { + iFirstDrawingOffset -= titleLen + KGap; + } + iCurrentTitleIndex = iFirstDrawingTitleIndex; + + if( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate && + CalculateCurrentTextFitInNewstickerRect() ) + { + MoveToNextL(); + } + } + // but if less than 100% and more than 75% has been drawn, update only current title index. + else if (((iIsWestern && iFirstDrawingOffset >= titleLen * 0.75) || + (!iIsWestern && iFirstDrawingOffset - titleLen >= iContentRect.iBr.iX * 0.75)) && + iFirstDrawingTitleIndex == iCurrentTitleIndex) + { + iCurrentTitleIndex++; + if(iCurrentTitleIndex >= iTitles.Count()) + { + iCurrentTitleIndex = 0; + } + iCurrentTitleIndex = GetNextTitleWithContent( iCurrentTitleIndex ); + + if( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate && + CalculateCurrentTextFitInNewstickerRect() ) + { + MoveToNextL(); + } + } + } + else if( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate && + CalculateCurrentTextFitInNewstickerRect() ) + { + iAdapter->SetTimerToDisplaytime(); + MoveToNextL(); + } + else + { + MoveToNextL(); + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::Draw +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::Draw() + { + if( IsVisibleTitles() > 0 ) + { + if( iIsWestern ) + { + TRAP_IGNORE( PrepareToDrawLtrL() ); + } + else + { + TRAP_IGNORE( PrepareToDrawRtlL() ); + } + } + else + { + CBitmapContext* gc = iAdapter->BufferGc(); + const CFbsBitmap* background = iAdapter->BackgroundBitmap(); + if ( gc && background ) + { + gc->BitBlt(TPoint(0,0), background); + } + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::DrawStatic +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::DrawStatic() + { + // draw to buffer gc + CBitmapContext* gc = iAdapter->BufferGc(); + const CFbsBitmap* background = iAdapter->BackgroundBitmap(); + if( !gc || !background || !IsVisibleTitles() ) + { + return; + } + gc->BitBlt( TPoint(0,0), background ); + + // Get the last title + TInt index = GetNextTitleWithContent( iTitles.Count() - 1, ETrue ); + const TDesC& title = Title( index ); + + // truncate text if needed + HBufC* visualText = HBufC::New(title.Length() + KAknBidiExtraSpacePerLine); + if (visualText) + { + TPtr visualTextPtr(visualText->Des()); + TInt maxLength = iContentRect.Width(); + AknBidiTextUtils::ConvertToVisualAndClip( + title, visualTextPtr, *iFont, maxLength, maxLength ); + + TRect blitRect( 0, 0, iContentRect.Width(), iContentRect.Height() ); + gc->DrawText( *visualText, blitRect, iTextBaseline, TextAlignment() ); + delete visualText; + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetBeginningState +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::SetBeginningState() + { + iFirstDrawingOffset = 0; + if(!iIsWestern) + { + iFirstDrawingOffset = iContentRect.Width(); + } + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetScrollLooping +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::SetScrollLooping( TBool aLoop ) + { + iScrollLooping = aLoop; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::ScrollLooping +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CXnNewstickerControl::ScrollLooping() + { + return iScrollLooping; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::TextFitInNewstickerRect +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CXnNewstickerControl::TextFitInNewstickerRect() + { + return iTextFitInNewstickerRect; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::CalculateTextFitInNewstickerRect +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CXnNewstickerControl::CalculateTextFitInNewstickerRect() + { + if ( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::ESlide && + iTitles.Count() == 1 ) + { + const TInt count = iTitles.Count(); + TInt textWidth=0; + const TInt rectWidth = iContentRect.Width(); + for (TInt i=0; iTitleTextLengthInPixels(); + } + iTextFitInNewstickerRect = (textWidthScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate ) + { + const TInt count = iTitles.Count(); + TInt textWidth=0; + const TInt rectWidth = iContentRect.Width(); + if( iCurrentTitleIndex < count ) + { + textWidth = iTitles[iCurrentTitleIndex]->TitleTextLengthInPixels(); + } + return ( textWidth < rectWidth ); + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::SetTextAlignment +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CXnNewstickerControl::SetTextAlignment(TInt aAlignment) + { + iTextAlignment = aAlignment; + } + +// ----------------------------------------------------------------------------- +// CXnNewstickerControl::TextAlignment +// if title fits to the drawing rect and scrolling behaviour is ESlide then +// use alignment value +// if scroll behaviour is alternate then use alignment value +// otherwise return ELeft in western and ERight on AH +// ----------------------------------------------------------------------------- +// +CGraphicsContext::TTextAlign CXnNewstickerControl::TextAlignment() + { + CGraphicsContext::TTextAlign alignment = iIsWestern ? CGraphicsContext::ELeft : CGraphicsContext::ERight; + + if ( iTextFitInNewstickerRect || iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EAlternate || + ( iAdapter->ScrollBehaviour() == CXnNewstickerAdapter::EScrollAlternate && + CalculateCurrentTextFitInNewstickerRect() ) ) + { + switch( iTextAlignment ) + { + default: + case ELayoutAlignLeft: + alignment = CGraphicsContext::ELeft; + break; + case ELayoutAlignRight: + alignment = CGraphicsContext::ERight; + break; + case ELayoutAlignCenter: + alignment = CGraphicsContext::ECenter; + break; + } + } + return alignment; + } + +TInt CXnNewstickerControl::GetNextTitleWithContent( TInt aStartSearch, TBool aBackwards ) + { + TInt dir = 1; + if ( aBackwards ) + { + dir = -1; + } + for( TInt i = aStartSearch; i < iTitles.Count() && i >= 0; i += dir ) + { + if ( iTitles[i]->TitleTextLengthInPixels() != 0 ) + { + return i; + } + } + return aStartSearch; + } + +TBool CXnNewstickerControl::IsVisibleTitles() + { + for( TInt i = 0; i < iTitles.Count() ; ++i ) + { + if ( iTitles[i]->TitleTextLengthInPixels() != 0 ) + { + return ETrue; + } + } + return EFalse; + } + + +// End of File